config: accept empty lines in quoted strings - #5448
Conversation
Handle physical line endings independently from preceding characters so a blank line or an escaped literal backslash before a newline does not look like EOF. Preserve CRLF as a unit for line continuation. Signed-off-by: Akash Kumar <meakash7902@gmail.com>
Watson1978
left a comment
There was a problem hiding this comment.
Nice fix.
The token-based handling of line breaks reads much more clearly than the old [^"]-plus-line-end pairing. The small follow-up suggestions on the same change.
|
This PR has been automatically marked as stale because it has been open 30 days with no activity. Remove stale label or comment or this PR will be closed in 7 days |
|
#4691 (comment) |
Extract LINE_BREAK and LINE_CONTINUATION in LiteralParser and use them in scan_double_quoted_string. Drop LINE_END_WITHOUT_SPACING_AND_COMMENT, which no longer has any caller. Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
scan(/./) does not match a newline, so a single-quoted value spanning multiple lines failed with "unexpected end of file". Scan line breaks explicitly, as scan_double_quoted_string already does. Unlike a double-quoted string, a backslash before a line break stays literal here because single-quoted strings have no line continuation. Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
A physical line break inside a quoted value was stored verbatim, so the same config text yielded a different value depending on whether the file was saved with LF or CRLF. Ruby and YAML both normalize here. An escaped "\r\n" still produces CRLF, and a lone CR is kept as before. Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
d2d1e02 to
6d3f550
Compare
|
I pushed three commits to this branch, please take a look. Of the three non-working examples in the issue, only the double-quoted one was fixed, so I applied the same line break handling to scan_single_quoted_string. I also normalized CRLF to LF inside quoted strings, so that the same config text does not produce a different value depending on whether the file was saved with LF or CRLF. The last one extracts the line break patterns as named constants and drops LINE_END_WITHOUT_SPACING_AND_COMMENT, which no longer has any caller. |
|
@kenhys Can you review this PR? |
|
nitpick: https://docs.fluentd.org/configuration/config-file#config-file-location
It appears that it behaves a bit differently. |
|
Thanks |
**Which issue(s) this PR fixes**: Fixes fluent#4691 **What this PR does / why we need it**: The quoted configuration values previously handled a physical line ending together with its preceding character. When the parser was already positioned at a line ending—such as on an empty line or after an escaped literal backslash—it instead reported an unexpected end of file. Handle backslash line continuations and preserved line endings explicitly. This accepts empty lines, preserves LF and CRLF, and retains the existing single-backslash continuation behavior. **Docs Changes**: None. The existing multiline-string documentation already describes the intended behavior. **Release Note**: config: accept empty lines in quoted strings. **Testing**: Automated: - `bundle exec rake test TEST=test/config/test_literal_parser.rb` — 220 tests, 223 assertions, 0 failures, 0 errors - `TEST_ENV_NUMBER=focus4691 bundle exec rake test TEST=test/config/test_config_parser.rb` — 56 tests, 106 assertions, 0 failures, 0 errors - `bundle exec rake test` (two independent runs) — 4,343 tests, 15,829 and 15,830 assertions respectively; 0 failures, 0 errors, 3 pendings, and 36 omissions in both - `rubocop` — 459 files inspected, no offenses - `ruby -c` for all three changed Ruby files and `git diff --check` Manual (Ruby 4.0.6): - Built and separately installed gems from baseline `f380d996bc828b5cd488b578018c06826ebcbf7e` and candidate `7d017869a55e179da4d195806f26d33dc485fc9d`. - The baseline built gem rejected the reproducing configuration with a false unexpected-EOF error; the candidate built gem accepted it with `fluentd --dry-run`; a genuinely unterminated double-quoted value remained rejected. - Ran the candidate built gem as a separate `fluentd --no-supervisor` process through `dummy` → `record_transformer` → `stdout` and externally parsed its emitted JSON as `{"message":"seed","blank":"world\n\n","literal_backslash":"left\\\nright","continued":"leftright"}`. --------- Signed-off-by: Akash Kumar <meakash7902@gmail.com> Signed-off-by: Shizuo Fujita <fujita@clear-code.com> Co-authored-by: Shizuo Fujita <fujita@clear-code.com>
**Which issue(s) this PR fixes**: Fixes fluent#4691 **What this PR does / why we need it**: The quoted configuration values previously handled a physical line ending together with its preceding character. When the parser was already positioned at a line ending—such as on an empty line or after an escaped literal backslash—it instead reported an unexpected end of file. Handle backslash line continuations and preserved line endings explicitly. This accepts empty lines, preserves LF and CRLF, and retains the existing single-backslash continuation behavior. **Docs Changes**: None. The existing multiline-string documentation already describes the intended behavior. **Release Note**: config: accept empty lines in quoted strings. **Testing**: Automated: - `bundle exec rake test TEST=test/config/test_literal_parser.rb` — 220 tests, 223 assertions, 0 failures, 0 errors - `TEST_ENV_NUMBER=focus4691 bundle exec rake test TEST=test/config/test_config_parser.rb` — 56 tests, 106 assertions, 0 failures, 0 errors - `bundle exec rake test` (two independent runs) — 4,343 tests, 15,829 and 15,830 assertions respectively; 0 failures, 0 errors, 3 pendings, and 36 omissions in both - `rubocop` — 459 files inspected, no offenses - `ruby -c` for all three changed Ruby files and `git diff --check` Manual (Ruby 4.0.6): - Built and separately installed gems from baseline `f380d996bc828b5cd488b578018c06826ebcbf7e` and candidate `7d017869a55e179da4d195806f26d33dc485fc9d`. - The baseline built gem rejected the reproducing configuration with a false unexpected-EOF error; the candidate built gem accepted it with `fluentd --dry-run`; a genuinely unterminated double-quoted value remained rejected. - Ran the candidate built gem as a separate `fluentd --no-supervisor` process through `dummy` → `record_transformer` → `stdout` and externally parsed its emitted JSON as `{"message":"seed","blank":"world\n\n","literal_backslash":"left\\\nright","continued":"leftright"}`. --------- Signed-off-by: Akash Kumar <meakash7902@gmail.com> Signed-off-by: Shizuo Fujita <fujita@clear-code.com> Co-authored-by: Shizuo Fujita <fujita@clear-code.com>
Which issue(s) this PR fixes:
Fixes #4691
What this PR does / why we need it:
The quoted configuration values previously handled a physical line ending together with its preceding character. When the parser was already positioned at a line ending—such as on an empty line or after an escaped literal backslash—it instead reported an unexpected end of file.
Handle backslash line continuations and preserved line endings explicitly. This accepts empty lines, preserves LF and CRLF, and retains the existing single-backslash continuation behavior.
Docs Changes:
None. The existing multiline-string documentation already describes the intended behavior.
Release Note:
config: accept empty lines in quoted strings.
Testing:
Automated:
bundle exec rake test TEST=test/config/test_literal_parser.rb— 220 tests, 223 assertions, 0 failures, 0 errorsTEST_ENV_NUMBER=focus4691 bundle exec rake test TEST=test/config/test_config_parser.rb— 56 tests, 106 assertions, 0 failures, 0 errorsbundle exec rake test(two independent runs) — 4,343 tests, 15,829 and 15,830 assertions respectively; 0 failures, 0 errors, 3 pendings, and 36 omissions in bothrubocop— 459 files inspected, no offensesruby -cfor all three changed Ruby files andgit diff --checkManual (Ruby 4.0.6):
f380d996bc828b5cd488b578018c06826ebcbf7eand candidate7d017869a55e179da4d195806f26d33dc485fc9d.fluentd --dry-run; a genuinely unterminated double-quoted value remained rejected.fluentd --no-supervisorprocess throughdummy→record_transformer→stdoutand externally parsed its emitted JSON as{"message":"seed","blank":"world\n\n","literal_backslash":"left\\\nright","continued":"leftright"}.