lxbme commented on issue #13673:
URL: https://github.com/apache/apisix/issues/13673#issuecomment-4921754993

   Hi @mcupei, thanks for the issue. I've reproduced this bug and it seems 
caused by a rebase mistake at api7/apisix-nginx-module repository.
   
   ## Reproduction
   
   Confirmed with byte-identical standalone configs, only swapping the image 
tag (`apache/apisix:3.16.0-debian` vs `3.17.0-debian`, default 
`client_max_body_size: 0`):
   
   | Test (11-byte body `hello=world`) | 3.16.0 | 3.17.0 |
   |---|---|---|
   | POST with `Content-Length` | 201 | 200 |
   | POST with `Transfer-Encoding: chunked` | 200 | **413** |
   
   Error log on 3.17:
   
   ```
   [error] client intended to send too large chunked body: 0+11 bytes
   ```
   
   An 11-byte body triggering "too large" shows this is not a real size 
overflow.
   
   ## Root cause
   
   APISIX 3.17 bumped the base from OpenResty **1.27.1.2** (apisix-runtime 
1.3.3, apisix-nginx-module 1.19.3) to **1.29.2.4** (apisix-runtime 1.3.6, 
apisix-nginx-module 1.19.5). It is **not** an upstream nginx change — vanilla 
`nginx:1.29.2` with `client_max_body_size 0` proxies chunked requests fine, and 
so does a bare (Lua-free) nginx built from the 3.16 image. The regression is in 
the rebased patch in apisix-nginx-module:
   
   `patch/1.29.2.4/nginx-client_max_body_size.patch`, hunk for 
`ngx_http_request_body_chunked_filter()`:
   
   ```c
   /* old patch (1.27.1.1, module 1.19.3) — correct */
   if (max_body_size
       && max_body_size
          - r->headers_in.content_length_n < rb->chunked->size)
   
   /* new patch (1.29.2.4, module 1.19.5 / 1.19.6 / master) — guard line lost 
in rebase */
   if (max_body_size
          - r->headers_in.content_length_n < rb->chunked->size)
   ```
   
   The `&& max_body_size` zero-guard (which implements nginx's "0 = unlimited" 
semantics) was dropped. With the default `client_max_body_size 0`, the check 
becomes `0 - 0 < 11` → true → 413 for **every** HTTP/1.1 chunked request, 
regardless of size. That's exactly the `0+11 bytes` in the log.
   
   Requests with `Content-Length` take a different code path whose guards are 
intact, which is why only chunked requests fail. The HTTP/2 hunk in the same 
patch kept its guard, so only the HTTP/1.1 chunked path is affected. Note this 
also breaks the `client-control` plugin's dynamic path: 
`set_client_max_body_size(0)` returns 413 on 3.17 as well.
   
   ## Fix
   
   Restore the lost guard line in 
[`patch/1.29.2.4/nginx-client_max_body_size.patch#L86`](https://github.com/api7/apisix-nginx-module/blob/1.19.5/patch/1.29.2.4/nginx-client_max_body_size.patch#L86)
 (still missing on `master` and tag `1.19.6`):
   
   ```diff
   -@@ -1139,8 +1165,14 @@ 
ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
   +@@ -1139,8 +1165,15 @@ 
ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
    ...
    +                if (max_body_size
   ++                    && max_body_size
    +#else
   ```
   
   This makes the hunk identical in shape to the old `1.27.1.1` patch. For any 
non-zero limit `X`, `X && (X - n < s)` is equivalent to `X - n < s`, so the 
change only affects the `0` case — restoring the "0 = unlimited" behavior with 
no other behavior change.
   
   I verified the fix by building openresty-1.29.2.4 + apisix-nginx-module 
1.19.5 twice (as shipped vs. with the guard restored):
   
   - As-shipped build reproduces the bug exactly (chunked + limit `0` → 413).
   - Fixed build: chunked with limit `0` → 200 (11B and 5MB bodies); non-zero 
limits still enforced (1m limit, 2MB chunked → 413); exact boundary preserved 
(20-byte limit: 20B → 200, 21B → 413); `client-control` dynamic path correct 
(`set_client_max_body_size(5)` → 413, `(0)` → 200).
   - The fixed patch applies cleanly on a pristine openresty-1.29.2.4 tree.
   
   Shipping it would need a new apisix-nginx-module tag, an apisix-runtime 
release, and rebuilt 3.17.x images. Until then, a verified workaround for users 
is setting any non-zero limit in `config.yaml`:
   
   ```yaml
   nginx_config:
     http:
       client_max_body_size: 1000m
   ```
   
   @Baoyuantop What do you think of this fix?


-- 
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