redis codec: fix \xHH hex escape crashing on literal 'x' in inline args - #46643
Open
waterWang wants to merge 3 commits into
Open
redis codec: fix \xHH hex escape crashing on literal 'x' in inline args#46643waterWang wants to merge 3 commits into
waterWang wants to merge 3 commits into
Conversation
Fixes envoyproxy#46642 — an unauthenticated client can crash any Envoy process that exposes a redis_proxy listener by sending a single inline Redis command containing a double-quoted argument with a literal 'x' followed by a \x hex escape sequence. The root cause: InlineStringQuotedEscape pushed the escape marker 'x' into the value string, then scanned 3-back for the same marker. A literal 'x' in user input triggered std::stoul on an invalid hex string, throwing std::invalid_argument that escaped the filter chain and reached std::terminate. Fix: track hex-digit count with a member variable instead of pushing the escape marker into the value string. Convert exactly two hex digits matching Redis \xHH semantics.
Remove the escape marker 'x' push and track hex-digit count instead of scanning 3-back in the string. This prevents std::stoul on invalid input when the user's argument contains a literal 'x' before a \x hex escape sequence.
Defense in depth: ensure any exception (e.g. std::invalid_argument from std::stoul) that escapes the decoder is caught and mapped to the downstream protocol error path instead of reaching std::terminate.
waterWang
requested a deployment
to
external-contributors
August 11, 2026 15:58 — with
GitHub Actions
Waiting
|
Hi @waterWang, welcome and thank you for your contribution. We will try to review your Pull Request as quickly as possible. In the meantime, please take a look at the contribution guidelines if you have not done so already. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #46642
Root cause
InlineStringQuotedEscapeHexpushes the escape markerxinto the valuestring, then scans 3 characters back for the same marker. When the user's
argument already contains a literal
xbefore a\xhex escape, the 3-backtest matches the literal
xinstead of the escape marker, andstd::stoulthrows
std::invalid_argumenton an invalid hex string. The exceptionescapes the filter chain (only
Redis::ProtocolErroris caught) and reachesstd::terminate, aborting the entire Envoy process.Fix
codec_impl.h— addinline_hex_digit_count_member to track hexdigits seen in the current
\xHHescape.codec_impl.cc— stop pushing the escape marker into the valuestring. Track hex-digit count instead of scanning 3-back. After exactly two
hex digits, convert and replace them with the decoded byte, matching Redis
\xHHsemantics.proxy_filter.cc— defense in depth: catchstd::exceptioninonData()alongside the existingProtocolErrorcatch, so any futuredecoder exception maps to the downstream protocol error path instead of
aborting the process.
Testing
SET key "x\x41"(literal x before hex escape) no longercrash; they decode the hex escape correctly.
\x4) are left as-is (matching Redisbehavior for incomplete escapes).
s[s.size() - 3]whens.size() == 2(first hex digit ona fresh escape) is eliminated by the state tracking approach.