Aias00 opened a new issue, #7473:
URL: https://github.com/apache/shenyu/issues/7473

   ## Finding
   
   `CachePlugin.CacheHttpResponse.writeWith()` joins the response body and 
reads it into a byte array without releasing the joined `DataBuffer`:
   
   - 
`shenyu-plugin/shenyu-plugin-cache/shenyu-plugin-cache-handler/src/main/java/org/apache/shenyu/plugin/cache/CachePlugin.java:129-135`
   
   Other response decorators in this repository release the joined buffer after 
reading:
   
   - 
`shenyu-plugin/shenyu-plugin-modify-response/src/main/java/org/apache/shenyu/plugin/modify/response/ModifyResponsePlugin.java:104-108`
   - 
`shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/support/ResponseDecorator.java:51-55`
   - 
`shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-response-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/response/AiResponseTransformerPlugin.java:307-311`
   
   ## Trigger / caller flow
   
   A request goes through the cache plugin, misses the cache, and writes a 
response body:
   
   `CachePlugin` decorates the response -> `CacheHttpResponse.writeWith(body)` 
-> `DataBufferUtils.join(body)` -> read bytes -> 
`WebFluxResultUtils.result(exchange, cacheResponse(bytes))`.
   
   ## Actual behavior
   
   The joined `DataBuffer` is read but never released.
   
   ## Expected behavior
   
   The joined buffer should be released after copying bytes, using a 
finally-safe path, matching the repository's other response decorators.
   
   ## Impact
   
   Every cacheable response miss can retain pooled Netty buffer memory longer 
than intended, increasing direct-memory pressure and leak-detector noise under 
cache-plugin traffic.
   
   ## Suggested fix
   
   Release the joined buffer after reading:
   
   ```java
   return dataBufferMono.flatMap(dataBuffer -> {
       byte[] bytes = new byte[dataBuffer.readableByteCount()];
       try {
           dataBuffer.read(bytes);
       } finally {
           DataBufferUtils.release(dataBuffer);
       }
       return WebFluxResultUtils.result(this.exchange, cacheResponse(bytes));
   });
   ```
   
   Add a regression test using a pooled/leak-aware buffer if feasible.
   
   ## Existing issue de-dupe
   
   This is not #7452, which covers a null cache handle crash, not #6505/#6506 
cache behavior issues, and not #6643, which is an MCP DataBuffer leak.
   
   ## Validation
   
   - Source flow inspected at `a89b6a2338c24e978428b731e8f1edce86022418`.
   - `./mvnw -pl shenyu-plugin/shenyu-plugin-cache/shenyu-plugin-cache-handler 
-Dtest=CachePluginTest test -Dcheckstyle.skip -Drat.skip=true 
-Djacoco.skip=true` passed. Existing tests do not assert `DataBuffer` release.
   
   
   
   ## Reviewed Revision And Validation
   
   Apache ShenYu 2.7.2-SNAPSHOT, master at 
a89b6a2338c24e978428b731e8f1edce86022418. Severity: high. Confidence: high.
   
   Actual current CacheHttpResponse wrote a valid response but the pooled input 
ByteBuf refCnt remained1. Test cleanup released it to0; isolated review traced 
real retained Netty upstream ownership.
   
   Current source references:
   
   - 
`shenyu-plugin/shenyu-plugin-cache/shenyu-plugin-cache-handler/src/main/java/org/apache/shenyu/plugin/cache/CachePlugin.java:129`
   - 
`shenyu-plugin/shenyu-plugin-modify-response/src/main/java/org/apache/shenyu/plugin/modify/response/ModifyResponsePlugin.java:104`
   - 
`shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/support/ResponseDecorator.java:51`
   - 
`shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-response-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/response/AiResponseTransformerPlugin.java:307`
   
   No implementation fix or full deployed end-to-end validation was performed 
by this review. Source-flow and runtime evidence are distinguished above.
   
   High-severity verification: reachable normal cache-miss response; client 
request path/query controls cache keys; no joined-buffer release; successful 
write leaves actual pooled native-buffer refCnt1; production Netty response 
ownership uses receive().retain().map(factory::wrap). The test separately frees 
that reference and confirms refCnt0. Cache hits/unpooled fixtures are outside 
this leaking path.
   


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