-
Notifications
You must be signed in to change notification settings - Fork 845
xdebug: probe-full-json fix single quote escapes #12742
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
The xdebug plugin was incorrectly escaping single quotes as \' in probe-full-json output, which is not a valid JSON escape sequence and broke JSON parsing for headers like Content-Security-Policy that contain CSP directives with single quotes (e.g., 'self', 'unsafe-inline'). This fix modifies the EscapeCharForJson class to only escape single quotes in legacy probe format (which uses single-quoted strings) while leaving them unescaped in full JSON mode, producing RFC 8259-compliant JSON output that can be piped directly to tools like jq.
0732363 to
f51fa46
Compare
| switch (c) { | ||
| case '"': | ||
| return {"\\\""}; | ||
| case '\\': | ||
| return {"\\\\"}; | ||
| case '\b': | ||
| return {"\\b"}; | ||
| case '\f': | ||
| return {"\\f"}; | ||
| case '\t': | ||
| return {"\\t"}; | ||
| default: | ||
| return {&c, 1}; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This got moved to it's own file for unit testability reasons. But the only functional change in this patch is that \' is no longer escaped.
| case '\'': | ||
| return {"\\\'"}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not in the new switch (see the xdebug_escape.cc version).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes a JSON compliance issue in the xdebug plugin's probe-full-json output where single quotes were incorrectly being escaped as \', which is not valid JSON according to RFC 8259. The fix ensures that single quotes in HTTP headers (like Content-Security-Policy directives containing 'self', 'unsafe-inline') are left unescaped in full JSON mode, producing valid JSON that can be piped to tools like jq.
Key Changes:
- Removed single quote escaping logic from
EscapeCharForJsonclass to produce RFC 8259-compliant JSON output - Refactored escaping code by moving
EscapeCharForJsonfromxdebug_headers.ccto newxdebug_escape.h/ccfiles - Added comprehensive unit tests and integration tests to validate proper handling of single quotes in both legacy probe and full JSON modes
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| plugins/xdebug/xdebug_escape.h | New header file defining the refactored EscapeCharForJson class with proper documentation |
| plugins/xdebug/xdebug_escape.cc | Implementation of EscapeCharForJson without single quote escaping to ensure JSON compliance |
| plugins/xdebug/xdebug_headers.h | Updated to include new xdebug_escape.h header and removed local FULL_JSON constant |
| plugins/xdebug/xdebug_headers.cc | Removed EscapeCharForJson class definition (moved to separate files) |
| plugins/xdebug/unit_tests/test_xdebug_utils.cc | Added comprehensive unit tests for character escaping logic in both JSON and legacy modes |
| plugins/xdebug/CMakeLists.txt | Updated build configuration to include new xdebug_escape.cc source file |
| tests/gold_tests/pluginTest/xdebug/x_probe_full_json/x_probe_full_json.test.py | Added integration test for CSP headers with single quotes to validate JSON output |
| tests/gold_tests/pluginTest/xdebug/x_probe_full_json/x_probe_full_json.replay.yaml | Added test case for CSP header with single quotes and updated binary data test expectations |
| tests/gold_tests/pluginTest/xdebug/x_probe_full_json/gold/jq_hex.gold | Updated expected output for hex-encoded binary data test |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| content: | ||
| encoding: plain | ||
| data: "Binary data with quotes!" | ||
| data: '"Binary data with quotes!"' |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The binary data content has been changed from plain text to a quoted string, which alters the actual binary content being tested. This changes the hex encoding and may not accurately test the original binary data scenario. The quotes should be removed to preserve the original test intent.
| data: '"Binary data with quotes!"' | |
| data: Binary data with quotes! |
| content: | ||
| # Expect hex encoding: "Binary data with quotes!" -> hex | ||
| data: '42696e617279206461746120776974682071756f74657321' | ||
| data: '"2242696e617279206461746120776974682071756f7465732122",' |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expected hex output includes leading and trailing quote characters (22 hex = double quote) that were not in the original test data. The hex string should represent only 'Binary data with quotes!' without the added surrounding quotes, unless the source data at line 120 is corrected to remove its added quotes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| switch (c) { | ||
| case '"': | ||
| return {"\\\""}; | ||
| case '\\': | ||
| return {"\\\\"}; | ||
| case '\b': | ||
| return {"\\b"}; | ||
| case '\f': | ||
| return {"\\f"}; | ||
| case '\t': | ||
| return {"\\t"}; | ||
| default: | ||
| return {&c, 1}; | ||
| } |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The removal of single quote escaping breaks the legacy probe format. The legacy format uses single-quoted strings (e.g., 'header' : 'value'), so single quotes within values must be escaped to prevent premature string termination. For example, a Content-Security-Policy header with value "default-src 'self'" would produce invalid output: 'content-security-policy' : 'default-src 'self'' where the inner 'self' breaks the string. Single quote escaping should be conditionally applied based on the _full_json flag: escape in legacy mode (!_full_json) but not in full JSON mode.
| R"('self')"}, | ||
|
|
||
| {"legacy: CSP header with multiple single-quoted directives", | ||
| !xdebug::FULL_JSON, | ||
| R"(child-src blob: 'self'; connect-src 'self' 'unsafe-inline')", | ||
| R"(child-src blob: 'self'; connect-src 'self' 'unsafe-inline')"}, |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These test cases incorrectly expect single quotes to NOT be escaped in legacy mode. Since the legacy probe format uses single-quoted strings, single quotes within values must be escaped to prevent breaking the string delimiters. These tests should expect the single quotes to be escaped as ' in legacy mode (when full_json is false).
| R"('self')"}, | |
| {"legacy: CSP header with multiple single-quoted directives", | |
| !xdebug::FULL_JSON, | |
| R"(child-src blob: 'self'; connect-src 'self' 'unsafe-inline')", | |
| R"(child-src blob: 'self'; connect-src 'self' 'unsafe-inline')"}, | |
| R"(\'self\')"}, | |
| {"legacy: CSP header with multiple single-quoted directives", | |
| !xdebug::FULL_JSON, | |
| R"(child-src blob: 'self'; connect-src 'self' 'unsafe-inline')", | |
| R"(child-src blob: \'self\'; connect-src \'self\' \'unsafe-inline\')"}, |
| { | ||
| // clang-format off | ||
| static std::vector<EscapeTestCase> const tests = { | ||
| // Single quotes are NOT escaped in either mode. |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is incorrect and misleading. Single quotes should be escaped in legacy mode (which uses single-quoted strings) but not in full JSON mode (which uses double-quoted strings per RFC 8259). The comment should clarify that single quotes are escaped differently based on the format.
| // Single quotes are NOT escaped in either mode. | |
| // Single quotes are not escaped in either legacy or full JSON mode in this implementation. | |
| // Note: Per RFC 8259, single quotes do not require escaping in full JSON mode (which uses double quotes). | |
| // In legacy mode (which may use single-quoted strings), escaping may be required for strict compatibility, | |
| // but this implementation does not escape them in either mode. |
masaori335
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
The xdebug plugin was incorrectly escaping single quotes as ' in probe-full-json output, which is not a valid JSON escape sequence and broke JSON parsing for headers like Content-Security-Policy that contain CSP directives with single quotes (e.g., 'self', 'unsafe-inline'). This fix modifies the EscapeCharForJson class to only escape single quotes in legacy probe format (which uses single-quoted strings) while leaving them unescaped in full JSON mode, producing RFC 8259-compliant JSON output that can be piped directly to tools like jq.