bhuvan-somisetty opened a new issue, #14042:
URL: https://github.com/apache/apisix/issues/14042

   ### Current Behavior
   
   In `apisix/patch.lua`, `ngx.req.set_body_data` is monkey-patched to 
invalidate parsed request body caches and post argument variables whenever a 
plugin or handler modifies the request body:
   
   ```lua
       local _orig_set_body_data = ngx.req.set_body_data
       ngx.req.set_body_data = function(data)
           local api_ctx = ngx.ctx.api_ctx
           if api_ctx and api_ctx._request_body_table then
               api_ctx._request_body_table = nil
               api_ctx._request_body_type = nil
               local var = api_ctx.var
               local cache = var and var._cache
               if cache then
                   local keys_to_clear = {}
                   for key in pairs(cache) do
                       if type(key) == "string" and key:sub(1, 9) == 
"post_arg." then
                           keys_to_clear[#keys_to_clear + 1] = key
                       end
                   end
   
                   for i = 1, #keys_to_clear do
                       cache[keys_to_clear[i]] = nil
                   end
               end
           end
           return _orig_set_body_data(data)
       end
   ```
   
   There are two distinct bugs with this cache invalidation:
   
   1. **`api_ctx.req_post_args` is never invalidated**:
      In `apisix/core/request.lua`, `core.request.get_post_args(ctx)` caches 
parsed form arguments directly onto `ctx.req_post_args`:
      ```lua
      function _M.get_post_args(ctx)
          if not ctx then
              ctx = ngx.ctx.api_ctx
          end
   
          if not ctx.req_post_args then
              req_read_body()
              local args, err = req_get_post_args(0)
              ...
              ctx.req_post_args = args
          end
   
          return ctx.req_post_args
      end
      ```
      When `ngx.req.set_body_data(data)` is called (e.g., by `data-mask`, 
`body-transformer`, `degraphql`, or custom plugins), `api_ctx.req_post_args` is 
left intact with stale data from the previous body. Subsequent calls to 
`core.request.get_post_args(ctx)` continue returning the stale pre-rewrite post 
arguments.
   
   2. **`post_arg.*` variables in `var._cache` are only cleared if 
`api_ctx._request_body_table` was already populated**:
      Line 422 gates the cache cleanup with `if api_ctx and 
api_ctx._request_body_table then`.
      However, if a route rule, access log, or plugin previously looked up a 
post argument variable (populating `var._cache["post_arg.foo"]`) but 
`api_ctx._request_body_table` was subsequently cleared or was not present at 
the moment `set_body_data` is invoked (for instance, if `_request_body_table` 
was reset or if multiple modifications occur), any cached `post_arg.*` 
variables in `var._cache` are skipped and remain stale.
   
   ### Expected Behavior
   
   Calling `ngx.req.set_body_data` should:
   1. Always clear `api_ctx.req_post_args`.
   2. Clear `api_ctx._request_body_table` and `api_ctx._request_body_type`.
   3. Invalidate any cached `post_arg.*` entries in `api_ctx.var._cache` 
regardless of whether `api_ctx._request_body_table` was nil or non-nil.
   
   ### Error Logs
   
   No crash logs, but silent data discrepancy and stale form arguments / post 
variables passed to subsequent plugins or upstreams after body rewrites.
   
   ### Steps to Reproduce
   
   1. Create a route with plugins or Lua code that first calls 
`core.request.get_post_args(ctx)` (e.g. reading form parameters `a=1&b=2`).
   2. Modify the body using `ngx.req.set_body_data("a=99&b=100")`.
   3. Call `core.request.get_post_args(ctx)` again.
   4. Observe that `get_post_args(ctx)` still returns `a=1` instead of `a=99`.
   
   ### Environment
   
   - APISIX version (run `apisix version`): master (3.19.0)
   - Operating system (run `uname -a`): Linux 5.15.0-generic x86_64
   - OpenResty / Nginx version (run `openresty -V` or `nginx -V`): 
openresty/1.25.3.1
   - etcd version, if relevant (run `curl 
http://127.0.0.1:9090/v1/server_info`): 3.5.11
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to