This is an automated email from the ASF dual-hosted git repository.

xuetaoli pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go-pixiu.git


The following commit(s) were added to refs/heads/develop by this push:
     new 51050091 fix(filter): use shallow copy of factory config for filters 
violating interface to avoid pointer sharing (#815)
51050091 is described below

commit 51050091313ccde9603a39f6dc069b4513bd8bd4
Author: dubbo-go-bot <[email protected]>
AuthorDate: Fri Nov 28 10:28:21 2025 +0800

    fix(filter): use shallow copy of factory config for filters violating 
interface to avoid pointer sharing (#815)
    
    * fix(filter): deep copy complex filter configs 
(https://github.com/dubbo-go-pixiu/dubbo-go-pixiu/pull/38)
    
    Some Pixiu filters have complex configurations (maps, slices, nested 
structs). Passing the factory.cfg pointer directly can cause in-flight requests 
to read inconsistent or modified configs when FilterManager.ReLoad() updates 
factory instances at runtime, violating the HttpFilterFactory interface 
contract.
    
    This commit implements DeepCopy() for complex filter configs and updates 
PrepareFilterChain to use it. Each filter instance now has its own independent 
config, preventing runtime inconsistencies.
    
    Affected files:
    - pkg/filter/auth/jwt/jwt.go
    - pkg/filter/authority/authority.go
    - pkg/filter/authority/config.go
    - pkg/filter/cors/cors.go
    - pkg/filter/csrf/csrf.go
    - pkg/filter/event/event.go
    - pkg/filter/failinject/filter.go
    - pkg/filter/http/grpcproxy/grpc.go
    - pkg/filter/mcp/mcpserver/filter.go
    - pkg/filter/sentinel/circuitbreaker/circuit_breaker.go
    - pkg/filter/sentinel/config.go
    - pkg/filter/sentinel/ratelimit/rate_limit.go
    - pkg/model/mcpserver.go
    
    Signed-off-by: Aetherance <[email protected]>
    Co-authored-by: Aetherance <[email protected]>
    
    * fix(filter): shallow copy factory config to avoid pointer sharing 
(https://github.com/dubbo-go-pixiu/dubbo-go-pixiu/pull/35)
    
    Shallow copy the factory configuration in filters that previously passed
    factory pointers directly. This ensures compliance with the 
HttpFilterFactory
    interface contract and avoids accidental sharing of config between filters
    and the factory.
    
    Affected filters (shallow copy sufficient):
    - opa/opa.go
    - llm/tokenizer/tokenizer.go
    - http/loadbalancer/loadbalancer.go
    - host/host.go
    - header/header.go
    - prometheus/metric
    - accesslog/access_log.go
    
    Note: Although prometheus/metric.go uses a nested struct
    (MetricCollectConfiguration -> MetricCollectRule), all fields are value 
types
    (string, bool, int). Therefore, shallow copy is sufficient; deep copy is not
    required.
    
    Signed-off-by: Aetherance <[email protected]>
    Co-authored-by: Aetherance <[email protected]>
    
    ---------
    
    Signed-off-by: Aetherance <[email protected]>
    Co-authored-by: The_INK <[email protected]>
    Co-authored-by: Aetherance <[email protected]>
---
 pkg/filter/accesslog/access_log.go           | 4 +++-
 pkg/filter/header/header.go                  | 6 ++++--
 pkg/filter/host/host.go                      | 6 ++++--
 pkg/filter/http/loadbalancer/loadbalancer.go | 4 +++-
 pkg/filter/llm/tokenizer/tokenizer.go        | 4 +++-
 pkg/filter/opa/opa.go                        | 4 +++-
 pkg/filter/prometheus/metric.go              | 4 +++-
 7 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/pkg/filter/accesslog/access_log.go 
b/pkg/filter/accesslog/access_log.go
index 0b9e1cca..2aa26e0c 100644
--- a/pkg/filter/accesslog/access_log.go
+++ b/pkg/filter/accesslog/access_log.go
@@ -76,8 +76,10 @@ func (p *Plugin) CreateFilterFactory() 
(filter.HttpFilterFactory, error) {
 
 // PrepareFilterChain prepare chain when http context init
 func (factory *FilterFactory) PrepareFilterChain(ctx *http.HttpContext, chain 
filter.FilterChain) error {
+       // Make a shallow copy of the factory config to avoid sharing the 
factory's pointer.
+       cpConf := *factory.conf
        f := &Filter{
-               conf: factory.conf,
+               conf: &cpConf,
                alw:  factory.alw,
        }
        chain.AppendDecodeFilters(f)
diff --git a/pkg/filter/header/header.go b/pkg/filter/header/header.go
index 4b078eda..16062a72 100644
--- a/pkg/filter/header/header.go
+++ b/pkg/filter/header/header.go
@@ -56,7 +56,7 @@ func (p *Plugin) Kind() string {
 }
 
 func (p *Plugin) CreateFilterFactory() (filter.HttpFilterFactory, error) {
-       return &FilterFactory{}, nil
+       return &FilterFactory{cfg: &Config{}}, nil
 }
 
 func (factory *FilterFactory) Config() any {
@@ -68,7 +68,9 @@ func (factory *FilterFactory) Apply() error {
 }
 
 func (factory *FilterFactory) PrepareFilterChain(ctx *http.HttpContext, chain 
filter.FilterChain) error {
-       f := &Filter{cfg: factory.cfg}
+       // Make a shallow copy of the factory config to avoid sharing the 
factory's pointer
+       cfgCopy := *factory.cfg
+       f := &Filter{cfg: &cfgCopy}
        chain.AppendDecodeFilters(f)
        return nil
 }
diff --git a/pkg/filter/host/host.go b/pkg/filter/host/host.go
index 233cf43c..2d7c77b4 100644
--- a/pkg/filter/host/host.go
+++ b/pkg/filter/host/host.go
@@ -55,11 +55,13 @@ func (p *Plugin) Kind() string {
 }
 
 func (p *Plugin) CreateFilterFactory() (filter.HttpFilterFactory, error) {
-       return &FilterFactory{}, nil
+       return &FilterFactory{cfg: &Config{}}, nil
 }
 
 func (factory *FilterFactory) PrepareFilterChain(ctx *contexthttp.HttpContext, 
chain filter.FilterChain) error {
-       f := &Filter{cfg: factory.cfg}
+       // Make a shallow copy of the factory config to avoid sharing the 
factory's pointer
+       cfgCopy := *factory.cfg
+       f := &Filter{cfg: &cfgCopy}
        chain.AppendDecodeFilters(f)
        return nil
 }
diff --git a/pkg/filter/http/loadbalancer/loadbalancer.go 
b/pkg/filter/http/loadbalancer/loadbalancer.go
index ffc6166f..9c4a5933 100644
--- a/pkg/filter/http/loadbalancer/loadbalancer.go
+++ b/pkg/filter/http/loadbalancer/loadbalancer.go
@@ -69,7 +69,9 @@ func (factory *FilterFactory) Apply() error {
 }
 
 func (factory *FilterFactory) PrepareFilterChain(ctx *contexthttp.HttpContext, 
chain filter.FilterChain) error {
-       f := &Filter{cfg: factory.cfg}
+       // Make a shallow copy of the factory config to avoid sharing the 
factory's pointer
+       cfgCopy := *factory.cfg
+       f := &Filter{cfg: &cfgCopy}
        chain.AppendDecodeFilters(f)
        return nil
 }
diff --git a/pkg/filter/llm/tokenizer/tokenizer.go 
b/pkg/filter/llm/tokenizer/tokenizer.go
index bc9d6825..71d0c664 100644
--- a/pkg/filter/llm/tokenizer/tokenizer.go
+++ b/pkg/filter/llm/tokenizer/tokenizer.go
@@ -134,7 +134,9 @@ func (factory *FilterFactory) Config() any { return 
factory.cfg }
 func (factory *FilterFactory) Apply() error { return registerLLMMetrics() }
 
 func (factory *FilterFactory) PrepareFilterChain(ctx *contexthttp.HttpContext, 
chain filter.FilterChain) error {
-       f := &Filter{cfg: factory.cfg}
+       // Make a shallow copy of the factory config to avoid sharing the 
factory's pointer
+       cfgCopy := *factory.cfg
+       f := &Filter{cfg: &cfgCopy}
        chain.AppendDecodeFilters(f)
        chain.AppendEncodeFilters(f)
        return nil
diff --git a/pkg/filter/opa/opa.go b/pkg/filter/opa/opa.go
index 56bae54d..1d6fca3f 100644
--- a/pkg/filter/opa/opa.go
+++ b/pkg/filter/opa/opa.go
@@ -99,7 +99,9 @@ func (factory *FilterFactory) PrepareFilterChain(ctx 
*http.HttpContext, chain fi
                return fmt.Errorf("failed to prepare OPA query: %w", err)
        }
 
-       f := &Filter{cfg: factory.cfg, preparedQuery: &preparedQuery}
+       // Make a shallow copy of the factory config to avoid sharing the 
factory's pointer.
+       cfgCopy := *factory.cfg
+       f := &Filter{cfg: &cfgCopy, preparedQuery: &preparedQuery}
        chain.AppendDecodeFilters(f)
        return nil
 }
diff --git a/pkg/filter/prometheus/metric.go b/pkg/filter/prometheus/metric.go
index 08e9e081..ac830530 100644
--- a/pkg/filter/prometheus/metric.go
+++ b/pkg/filter/prometheus/metric.go
@@ -76,8 +76,10 @@ func (factory *FilterFactory) Apply() error {
 
 func (factory *FilterFactory) PrepareFilterChain(ctx *contextHttp.HttpContext, 
chain filter.FilterChain) error {
 
+       // Shallow copy config to avoid pointer sharing (factory.cfg may change 
at runtime)
+       cpConfig := *factory.Cfg
        f := &Filter{
-               Cfg:  factory.Cfg,
+               Cfg:  &cpConfig,
                Prom: factory.Prom,
        }
        f.Prom.SetPushGatewayUrl(f.Cfg.Rules.PushGatewayURL, 
f.Cfg.Rules.MetricPath)

Reply via email to