util: LineReader - Don't include newline and acknowledge single-char \r
What changed, and why it matters
This is a small code cleanup in Bitcoin Core's line-reading utility. It changes how the reader strips newline characters from input lines. The old code tried to remove both '\n' and '\r' from the end of a line after the fact; the new code builds the line without the '\n' in the first place and only strips a trailing '\r' if present. The commit message frames this as a correctness improvement for single-character '\r' line endings. There is no direct evidence in the commit or supplied references that this fixes an active security vulnerability.
Review as normal code-quality/maintenance change. No urgent security action required based on the supplied commit alone. If this utility is used to parse untrusted configuration or RPC input, consider whether lone '\r' handling could affect downstream parsing, but the change appears to make behavior more consistent rather than less safe.
Security signals we found
Input parsing boundary change
Line termination handling change
No explicit security claim in commit message
Evidence from the diff
The patch modifies LineReader::ReadLine() in src/util/string.cpp. Previously, after detecting a ‘\n’ terminator, it constructed a string_view of length count and then called RemoveSuffixView twice to strip ‘\n’ and then ‘\r’. The new code constructs the string_view with length count-1 (excluding the ‘\n’ by construction) and conditionally removes a single trailing ‘\r’. This is functionally equivalent for normal CRLF/LF input but differs for a lone ‘\r’ followed by ‘\n’: the old code would strip both, while the new code also strips both (since ‘\r’ is now at position count-2). The commit message says this ‘acknowledge[s] single-char \r’, suggesting the intent is to handle a bare ‘\r’ line ending correctly. The change is defensive and reduces reliance on suffix-stripping helpers.
Changed components
src/util/string.cppLineReader::ReadLine()Inspect captured patch +4 / −3
diff --git a/src/util/string.cpp b/src/util/string.cpp
index a203bc1b..8962513d 100644
--- a/src/util/string.cpp
+++ b/src/util/string.cpp
@@ -36,9 +36,10 @@ std::optional<std::string_view> LineReader::ReadLine()
// If the character we just consumed was \n, the line is terminated.
// The \n itself does not count against max_line_length.
if (c == '\n') {
- const std::string_view untrimmed_line(reinterpret_cast<const char*>(std::to_address(line_start)), count);
- std::string_view line = RemoveSuffixView(untrimmed_line, "\n");
- return RemoveSuffixView(line, "\r");
+ std::string_view line{reinterpret_cast<const char*>(std::to_address(line_start)), count - 1};
+ if (!line.empty() && line.back() == '\r')
+ line.remove_suffix(1);
+ return line;
}
// If the character we just consumed gives us a line length greater
// than max_line_length, and we are not at the end of the line (or buffer) yet,
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.