Repository navigation
Fix potential buffer underflow when stripping trailing newlines - #1951
AustinBenoit wants to merge 1 commit into
Conversation
Use std::string::back() and std::string::pop_back() (with a non-empty check) instead of indexing buf[strlen(buf) - 1] in app/src/locale.cc and testing/run_all_tests.cc, and close /etc/timezone in GetTimezone(). Resolves GitHub Code Scanning security alerts (Rule WS-CPP-00049): - https://github.com/firebase/firebase-cpp-sdk/security/code-scanning/2788 - https://github.com/firebase/firebase-cpp-sdk/security/code-scanning/2789 - https://github.com/firebase/firebase-cpp-sdk/security/code-scanning/2791
There was a problem hiding this comment.
Code Review
This pull request fixes a potential 1-byte buffer underflow and a file descriptor leak when reading /etc/timezone in GetTimezone(), and refactors the test log printing loop to safely handle newlines. The review feedback suggests handling CRLF line endings when parsing /etc/timezone by stripping both \r and \n characters, and optimizing the test logging loop by manipulating the raw C-string buffer directly to avoid the overhead of creating a std::string on each iteration.
| std::string tz(buf); | ||
| if (!tz.empty() && tz.back() == '\n') { | ||
| tz.pop_back(); | ||
| } | ||
| if (!tz.empty()) { | ||
| return tz; | ||
| } |
There was a problem hiding this comment.
If /etc/timezone contains CRLF (\r\n) line endings (e.g., if edited on Windows or shared across environments), only stripping \n will leave a trailing \r in the timezone string. This can cause issues when resolving the timezone. It is safer to strip both trailing \r and \n characters.
std::string tz(buf);\n while (!tz.empty() && (tz.back() == '\\n' || tz.back() == '\\r')) {\n tz.pop_back();\n }\n if (!tz.empty()) {\n return tz;\n }| std::string line(log); | ||
| if (!line.empty() && line.back() == '\n') { | ||
| line.pop_back(); // Remove newline. | ||
| } | ||
| LOG(INFO) << line; |
There was a problem hiding this comment.
Creating a std::string inside the loop for every line of the log file introduces unnecessary overhead, including potential heap allocations for lines exceeding the Small String Optimization (SSO) threshold. Since we only need to strip the trailing newline and log the result, we can perform this safely on the raw C-string buffer using strlen, which also avoids the need to include <string>.
size_t len = strlen(log);\n while (len > 0 && (log[len - 1] == '\\n' || log[len - 1] == '\\r')) {\n log[--len] = '\\0';\n }\n LOG(INFO) << log;
Description
Resolves GitHub Code Scanning security alerts (
WS-CPP-00049):app/src/locale.cc:235)app/src/locale.cc:236)testing/run_all_tests.cc:97)Both
firebase::internal::GetTimezone()(app/src/locale.cc) and the Android native test runner (testing/run_all_tests.cc) read lines usingfgetsinto a fixed buffer and stripped trailing newlines by indexingbuf[strlen(buf) - 1]. Iffgetsreads a line starting with a NUL byte (\0),strlenreturns0andlen - 1wraps around toSIZE_MAX(buf[-1]), resulting in a 1-byte buffer underflow. Intesting/run_all_tests.cc,log[strlen(log) - 1] = '\0'also truncated the 255th character of any line longer than the buffer that did not end with\n.This change:
buf[strlen(buf) - 1] = '\0') inapp/src/locale.ccandtesting/run_all_tests.ccwithstd::string(if (!str.empty() && str.back() == '\n') { str.pop_back(); }).char buf[kBufSize] = {0};andchar log[256] = {0};).tz_file(fclose(tz_file)) inGetTimezone()to fix aFILE*leak on Linux, and falls back togetenv("TZ")/tznameif/etc/timezoneis blank after stripping the newline.while (!feof(fp)) { if (fgets(...)) }intesting/run_all_tests.ccwithwhile (fgets(log, sizeof(log), fp) != nullptr)to avoid an infinite loop ifferror(fp)is set.### Upcominginrelease_build_files/readme.md.Testing
app/src/locale.ccon Linux desktop withg++ -std=c++17 -Wall -Wextra -Werror.python3 scripts/format_code.py -git_diff -noformat_file -verbose.bash scripts/gha/check_copyright.sh -g.Type of Change
Place an
xthe applicable box:https://github.com/firebase/firebase-cpp-sdk/security/code-scanning/2788
https://github.com/firebase/firebase-cpp-sdk/security/code-scanning/2789
https://github.com/firebase/firebase-cpp-sdk/security/code-scanning/2791
Notes
Release Notessection ofrelease_build_files/readme.md.