Avoid send empty body to ext_proc server if decodeData() never called#28672
Avoid send empty body to ext_proc server if decodeData() never called#28672yanavlasov merged 4 commits intoenvoyproxy:mainfrom
Conversation
Signed-off-by: Yanjun Xiang <yanjunxiang@google.com>
|
CC @envoyproxy/api-shepherds: Your approval is needed for changes made to |
|
The solution is to add a bufferedData() check before sending body to ext_proc server. bufferedData() will only become valid pointer if decodeData() is every called. If no data received, and decodeData() is never called, it will be nullptr. |
Signed-off-by: Yanjun Xiang <yanjunxiang@google.com>
Signed-off-by: Yanjun Xiang <yanjunxiang@google.com>
|
/retest |
|
/assign @tyxia @yanavlasov |
…_body_add Signed-off-by: Yanjun Xiang <yanjunxiang@google.com>
|
/assign @stevenzzzz |
| } | ||
|
|
||
| if (!body_delivered && state.bodyMode() == ProcessingMode::BUFFERED) { | ||
| if (!body_delivered && state.bufferedData() && state.bodyMode() == ProcessingMode::BUFFERED) { |
There was a problem hiding this comment.
The other utility function hasBufferedData() can not be used here since it not only check bufferedData() not nullptr, also checks the data->length >0. Using hasBufferedData() here will break the decodeData() with an empty chunk case.
There was a problem hiding this comment.
QQ: I am wondering when do we need to decodeData() with an empty chunk case? What are the use cases for this?
|
This is the crash log and crash traceback decode: |
|
The root cause of the issue is this: If ext_proc filter is configured to send body, and if only headers and trailers are received, no body is received by the ext_proc filter, it will send an empty boy to the ext_proc server. envoy/source/common/http/filter_manager.cc Line 426 in 522f991 So, filter_manager carefully maintain state_.latest_data_decoding_filter_ during decodeData(): envoy/source/common/http/filter_manager.cc Line 658 in 522f991 In this case, decodeData() is never called due to client is not sending data, and data is constructed by ext_proc filter itself. That leads to latest_data_decoding_filter_ is an empty pointer not pointing the ext_proc filter Thus the ASSERT failed, and crashed there. Overall, the ext_proc filter should not send data based on the ext_proc filter configuration. It should only send data if the data presents. Concept wise, this issue is similar to sending trailer when trailer is not present case : #28592 |
|
/assign @mattklein123 |
|
Kind Ping |
| } | ||
|
|
||
| if (!body_delivered && state.bodyMode() == ProcessingMode::BUFFERED) { | ||
| if (!body_delivered && state.bufferedData() && state.bodyMode() == ProcessingMode::BUFFERED) { |
There was a problem hiding this comment.
QQ: I am wondering when do we need to decodeData() with an empty chunk case? What are the use cases for this?
stevenzzzz
left a comment
There was a problem hiding this comment.
The "skipping body" approach in this PR feels like a behavior change that we can avoid by calling de/encodeData(dataMutations, false); on receiving the data mutation response from ext_server.
But no strong feelings.
| } | ||
|
|
||
| if (!body_delivered && state.bodyMode() == ProcessingMode::BUFFERED) { | ||
| if (!body_delivered && state.bufferedData() && state.bodyMode() == ProcessingMode::BUFFERED) { |
Thanks for the comments! The ext_proc behavior is now changed into "if configured as such, deliver body/trailer to the ext_proc server if they are present". |
|
@envoyproxy/api-shepherds PTAL |
|
API change is comment only. |
If decodeData() is not called, currently ext_proc filter is still possible to send an empty body to ext_proc server with
envoy/source/extensions/filters/http/ext_proc/ext_proc.cc
Line 480 in b8853df
and
envoy/source/extensions/filters/http/ext_proc/ext_proc.cc
Line 565 in b8853df
After body mutation from ext_proc server is received by ext_proc filter, it will modify the decoding buffer, which leads to an ASSERT() in filter manager
common/http/filter_manager.cc:426] assert failure: parent_.state_.latest_data_decoding_filter_ == this
The condition to trigger this ASSERT is ext_proc filter is configured to send body, but client only sends headers and trailers.
Commit Message:
Additional Description:
Risk Level:
Testing:
Docs Changes:
Release Notes:
Platform Specific Features:
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Fixes commit #PR or SHA]
[Optional Deprecated:]
[Optional API Considerations:]