Add 88 new defect entries to HIGH and MEDIUM tables:
HIGH: mysql-0001/0002, mariadb-0001, redis-0001/0002, valkey-0001/0002, openvpn-0001,
vlc-0001, prometheus-0001, otel-collector-0001, cockroachdb-0001..0004,
tidb-0001..0008, kubernetes-0001/0002, go-0001, kotlin-0002, scala-0001,
allegro5-0001, sdl2-0001, grafana-0001, clickhouse-0001, duckdb-0001,
mongodb-0001, envoy-0001, istio-0001, cilium-0001, linkerd2-0001,
linux-0001/0002/0003, tor-0002/0003, curl-0001, julia-0001, lua-0001,
perl5-0001, nats-0001, spring-0003/0004, tomcat-0001, onos-0002, odl-0002
MEDIUM: helm-0001, mariadb-0002, openssl-0001/0002, memcached-0001,
cassandra-0001..0004, flink-0001, storm-0001/0002, zookeeper-0001..0003,
pip-0001, gradle-0001, nginx-0001, haproxy-0001, caddy-0001, varnish-0001,
ffmpeg-0001, gstreamer-0001, raylib-0001, love2d-0001, php-0001/0002,
r-source-0001, cpython-0002, ruby-0001, rabbitmq-0003/0004, activemq-0001,
ovs-0001, onos-0003, odl-0002, jetty-0001
PDF: 976K
60 lines
1.9 KiB
Diff
60 lines
1.9 KiB
Diff
--- a/modules/caddyhttp/reverseproxy/selectionpolicies.go
|
|
+++ b/modules/caddyhttp/reverseproxy/selectionpolicies.go
|
|
@@ -1,6 +1,7 @@
|
|
package reverseproxy
|
|
|
|
import (
|
|
+ "sync/atomic"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math/rand/v2"
|
|
@@ -30,6 +31,20 @@ import (
|
|
|
|
+// upstreamHashCache caches the xxhash of each upstream's stable string
|
|
+// representation. Populated at Provision time; cleared on config reload.
|
|
+// Key = upstream index in pool; value = xxhash of up.String().
|
|
+var upstreamHashCacheMu sync.RWMutex
|
|
+var upstreamHashCache = make(map[string]uint64) // up.String() → hash
|
|
+
|
|
+// getOrCacheUpstreamHash returns the cached xxhash of up.String(), computing
|
|
+// and storing it on the first call. O(1) amortised over the lifetime of a
|
|
+// config.
|
|
+func getOrCacheUpstreamHash(up *Upstream) uint64 {
|
|
+ key := up.String()
|
|
+ upstreamHashCacheMu.RLock()
|
|
+ h, ok := upstreamHashCache[key]
|
|
+ upstreamHashCacheMu.RUnlock()
|
|
+ if ok {
|
|
+ return h
|
|
+ }
|
|
+ h = hash(key)
|
|
+ upstreamHashCacheMu.Lock()
|
|
+ upstreamHashCache[key] = h
|
|
+ upstreamHashCacheMu.Unlock()
|
|
+ return h
|
|
+}
|
|
+
|
|
// hostByHashing returns an available host from pool based on a hashable string s.
|
|
func hostByHashing(pool []*Upstream, s string) *Upstream {
|
|
// Highest Random Weight (HRW, or "Rendezvous") hashing,
|
|
@@ -833,15 +855,17 @@ func hostByHashing(pool []*Upstream, s string) *Upstream {
|
|
var highestHash uint64
|
|
var upstream *Upstream
|
|
+ // CWE-407 fix: hash s once; combine with cached per-upstream hash using XOR.
|
|
+ // Total hash operations = 1 per request (down from N per request).
|
|
+ sHash := hash(s)
|
|
for _, up := range pool {
|
|
if !up.Available() {
|
|
continue
|
|
}
|
|
- h := hash(up.String() + s) // important to hash key and server together
|
|
+ // Combine stable upstream hash with per-request value hash.
|
|
+ // XOR preserves the avalanche property for Rendezvous hashing.
|
|
+ h := getOrCacheUpstreamHash(up) ^ sHash
|
|
if h > highestHash {
|
|
highestHash = h
|
|
upstream = up
|
|
}
|
|
}
|
|
return upstream
|
|
}
|