-
Notifications
You must be signed in to change notification settings - Fork 1.9k
storage: fix heap corruption in chunk sort parser #11017
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
storage: fix heap corruption in chunk sort parser #11017
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughAdds Changes
Sequence Diagram(s)sequenceDiagram
participant Sort as sort_chunk_cmp
participant A as cio_chunk A
participant B as cio_chunk B
participant P as parse_stamp
Sort->>A: extract timestamp segment from name A
Sort->>P: parse_stamp(segment A)
alt parse A OK
P-->>Sort: timespec A (sec,nsec), ok
else parse A invalid
P-->>Sort: error/invalid
end
Sort->>B: extract timestamp segment from name B
Sort->>P: parse_stamp(segment B)
alt parse B OK
P-->>Sort: timespec B (sec,nsec), ok
else parse B invalid
P-->>Sort: error/invalid
end
alt both valid
Sort-->>Sort: compare sec then nsec -> return ordering
else one valid, one invalid
Sort-->>Sort: valid sorts before invalid -> return ordering
else both invalid
Sort-->>Sort: compare names deterministically -> return ordering
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (30)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
157966f to
eb64e4b
Compare
Signed-off-by: Hiroshi Hatake <[email protected]>
eb64e4b to
a2a523b
Compare
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.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/flb_storage.c (1)
413-451: Fix antisymmetry violation in the comparator.When either chunk is invalid,
sort_chunk_cmpimmediately returns-1. This violates the antisymmetry requirement for comparison functions. Consider two invalid chunks A and B:
cmp(A, B)checks A first, finds it invalid, returns-1(claiming A < B)cmp(B, A)checks B first, finds it invalid, returns-1(claiming B < A)Both statements cannot be true. This inconsistency causes undefined behavior in
qsort—potentially infinite loops, incorrect orderings, or heap corruption.To fix, validate both chunks before deciding the result. For example, treat two invalid chunks as equal and place all invalid chunks at the end of the sorted list:
static int sort_chunk_cmp(const void *a_arg, const void *b_arg) { const struct cio_chunk *chunk_a = *(const struct cio_chunk **)a_arg; const struct cio_chunk *chunk_b = *(const struct cio_chunk **)b_arg; const char *p; struct timespec tm_a = {0}, tm_b = {0}; + int a_valid = 0, b_valid = 0; /* Scan Chunk A */ p = strchr(chunk_a->name, '-'); - if (!p || parse_stamp(p + 1, &tm_a.tv_sec, &tm_a.tv_nsec) != 0) { - return -1; + if (p && parse_stamp(p + 1, &tm_a.tv_sec, &tm_a.tv_nsec) == 0) { + a_valid = 1; } /* Scan Chunk B */ p = strchr(chunk_b->name, '-'); - if (!p || parse_stamp(p + 1, &tm_b.tv_sec, &tm_b.tv_nsec) != 0) { - return -1; + if (p && parse_stamp(p + 1, &tm_b.tv_sec, &tm_b.tv_nsec) == 0) { + b_valid = 1; + } + + /* Handle invalid chunks: place them at the end and treat them as equal */ + if (!a_valid && !b_valid) { + return 0; /* Both invalid → equal */ + } + if (!a_valid) { + return 1; /* A invalid → A > B (sort A after B) */ + } + if (!b_valid) { + return -1; /* B invalid → A < B (sort B after A) */ } /* Compare */ if (tm_a.tv_sec != tm_b.tv_sec) { if (tm_a.tv_sec > tm_b.tv_sec) { return 1; } else { return -1; } } else { if (tm_a.tv_nsec > tm_b.tv_nsec) { return 1; } else if (tm_a.tv_nsec < tm_b.tv_nsec) { return -1; } } return 0; }
🧹 Nitpick comments (1)
src/flb_storage.c (1)
393-411: Consider strengthening the format validation.The
sscanfcall returns the count of successfully assigned items. With format"%" SCNu64 ".%" SCNu64 ".flb", if the input is"123.456.txt",sscanfparses both numbers successfully (returns 2) even though the literal.flbdoesn't match—soparse_stampwould incorrectly succeed. Files with a valid timestamp pattern but a different extension (or extra trailing characters) can slip through.To ensure the string ends exactly at
.flbwith no trailing characters, use the%nspecifier to capture how many characters were consumed, then verify the string terminates there:static int parse_stamp(const char *p, time_t *sec, long *nsec) { uint64_t s = 0, ns = 0; + int consumed = 0; if (!p || !sec || !nsec) { return -1; } /* expected: "1234567890.123456789.flb" format */ - if (sscanf(p, "%" SCNu64 ".%" SCNu64 ".flb", &s, &ns) != 2) { + if (sscanf(p, "%" SCNu64 ".%" SCNu64 ".flb%n", &s, &ns, &consumed) != 2) { + return -1; + } + if (p[consumed] != '\0') { return -1; } if (ns >= 1000000000ULL) { return -1; } *sec = (time_t)s; *nsec = (long)ns; return 0; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
include/fluent-bit/flb_storage.h(1 hunks)src/flb_storage.c(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- include/fluent-bit/flb_storage.h
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (30)
- GitHub Check: pr-windows-build / call-build-windows-package (Windows 64bit (Arm64), amd64_arm64, -DCMAKE_SYSTEM_NAME=Windows -DCMA...
- GitHub Check: pr-windows-build / call-build-windows-package (Windows 32bit, x86, x86-windows-static, 3.31.6)
- GitHub Check: pr-windows-build / call-build-windows-package (Windows 64bit, x64, x64-windows-static, 3.31.6)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_ARROW=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_COVERAGE=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_ADDRESS=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_ADDRESS=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=On, 3.31.6, clang, clang++)
- GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-22.04, clang-12)
- GitHub Check: pr-compile-without-cxx (3.31.6)
- GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-22.04, clang-12)
- GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-24.04, clang-14)
- GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-24.04, clang-14)
- GitHub Check: pr-compile-centos-7
- GitHub Check: PR - fuzzing test
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.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/flb_storage.c (1)
393-411: Good fix; add cast-overflow guards before assigning to time_t/longSCNu64 usage and ns<1e9 validation look correct. To avoid UB when time_t or long are narrower (e.g., 32-bit), guard the downcasts.
Apply within this function:
@@ - *sec = (time_t)s; - *nsec = (long)ns; - return 0; + { + time_t ts = (time_t) s; + long tns = (long) ns; + + /* Reject values that don't round-trip into target types */ + if ((uint64_t) ts != s || (uint64_t) tns != ns) { + return -1; + } + + *sec = ts; + *nsec = tns; + return 0; + }Also, confirm <inttypes.h> is visible here (via flb_storage.h include) on all platforms so SCNu64 expands properly. The current format string itself is correct (no stray quotes). Based on learnings
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
include/fluent-bit/flb_storage.h(1 hunks)src/flb_storage.c(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- include/fluent-bit/flb_storage.h
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (30)
- GitHub Check: pr-windows-build / call-build-windows-package (Windows 64bit (Arm64), amd64_arm64, -DCMAKE_SYSTEM_NAME=Windows -DCMA...
- GitHub Check: pr-windows-build / call-build-windows-package (Windows 64bit, x64, x64-windows-static, 3.31.6)
- GitHub Check: pr-windows-build / call-build-windows-package (Windows 32bit, x86, x86-windows-static, 3.31.6)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_ARROW=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_ADDRESS=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_COVERAGE=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_ADDRESS=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, clang, clang++)
- GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-24.04, clang-14)
- GitHub Check: pr-compile-without-cxx (3.31.6)
- GitHub Check: pr-compile-centos-7
- GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-22.04, clang-12)
- GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-22.04, clang-12)
- GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-24.04, clang-14)
- GitHub Check: PR - fuzzing test
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.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/flb_storage.c (1)
401-410: Anchor parsing to end-of-string: ensure input ends exactly after “.flb” by adding “%n” and checking the consumed count:- if (sscanf(p, "%" SCNu64 ".%" SCNu64 ".flb", &s, &ns) != 2) { + int consumed = 0; + if (sscanf(p, "%" SCNu64 ".%" SCNu64 ".flb%n", &s, &ns, &consumed) != 2 || + p[consumed] != '\0') { return -1; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
include/fluent-bit/flb_storage.h(1 hunks)src/flb_storage.c(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- include/fluent-bit/flb_storage.h
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (30)
- GitHub Check: pr-windows-build / call-build-windows-package (Windows 64bit, x64, x64-windows-static, 3.31.6)
- GitHub Check: pr-windows-build / call-build-windows-package (Windows 64bit (Arm64), amd64_arm64, -DCMAKE_SYSTEM_NAME=Windows -DCMA...
- GitHub Check: pr-windows-build / call-build-windows-package (Windows 32bit, x86, x86-windows-static, 3.31.6)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_ARROW=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_ADDRESS=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_COVERAGE=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_ADDRESS=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=On, 3.31.6, clang, clang++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=On, 3.31.6, gcc, g++)
- GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, gcc, g++)
- GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-24.04, clang-14)
- GitHub Check: PR - fuzzing test
- GitHub Check: pr-compile-centos-7
- GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-22.04, clang-12)
- GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-22.04, clang-12)
- GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-24.04, clang-14)
- GitHub Check: pr-compile-without-cxx (3.31.6)
🔇 Additional comments (1)
src/flb_storage.c (1)
433-441: Invalid-chunk ordering policy LGTMTreating both invalid as equal and pushing invalid after valid improves safety and determinism during sorting.
Signed-off-by: Hiroshi Hatake <[email protected]>
e06dab5 to
1eaf490
Compare
Fix heap corruption in sort_chunk_cmp by replacing unsafe sscanf with a validated parse_stamp().
Use SCNu64 to parse timestamps as 64-bit, since on Windows unsigned long is 32-bit while time_t is 64-bit, causing type mismatches with %lu.
Prevents crashes when malformed/non-chunk files are scanned.
Enter
[N/A]in the box, if an item is not applicable to your change.Testing
Before we can approve your change; please submit the following in a comment:
If this is a change to packaging of containers or native binaries then please confirm it works for all targets.
ok-package-testlabel to test for all targets (requires maintainer to do).Documentation
Backporting
Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.
Summary by CodeRabbit
Bug Fixes
Refactor
Chores