strinc() in ConflictSet.cpp used std::string_view::size() (size_t) and subtracted 1 without first checking for an empty string. For the root node, getSearchPath() returns the empty string, so every debug correctness check underflowed size_t and relied on implementation-defined conversion to int.
prefixRange() in Bench.cpp had the same loop shape. Although TrivialSpan::size() returns int, on an empty (or all-\xff) key the function asserted and then continued executing, allocating a zero-length buffer and writing before its start.
Changes:
In strinc(), initialize index as signed int(str.size()) - 1 so the loop is skipped for empty input, and return ok = false cleanly.
In prefixRange(), initialize index the same way and call std::abort() after the assert so invalid input cannot fall through to an out-of-bounds write.
Replace C-style uint8_t casts with explicit static_casts.
Closes #59
`strinc()` in `ConflictSet.cpp` used `std::string_view::size()` (`size_t`) and subtracted `1` without first checking for an empty string. For the root node, `getSearchPath()` returns the empty string, so every debug correctness check underflowed `size_t` and relied on implementation-defined conversion to `int`.
`prefixRange()` in `Bench.cpp` had the same loop shape. Although `TrivialSpan::size()` returns `int`, on an empty (or all-`\xff`) key the function asserted and then continued executing, allocating a zero-length buffer and writing before its start.
Changes:
- In `strinc()`, initialize `index` as signed `int(str.size()) - 1` so the loop is skipped for empty input, and return `ok = false` cleanly.
- In `prefixRange()`, initialize `index` the same way and call `std::abort()` after the assert so invalid input cannot fall through to an out-of-bounds write.
- Replace C-style `uint8_t` casts with explicit `static_cast`s.
strinc() in ConflictSet.cpp used std::string_view::size() (size_t) and subtracted 1 without first checking for an empty string. For the root node, getSearchPath() returns the empty string, so every debug correctness check underflowed size_t and relied on implementation-defined conversion to signed int.
prefixRange() in Bench.cpp had the same loop shape. Although TrivialSpan::size() returns int, on an empty (or all-0xff) key the function then asserted and continued executing, allocating a zero-length buffer and writing before its start.
Changes:
- In strinc(), initialize index as signed int(str.size()) - 1 so the loop is skipped for empty input, and return ok=false cleanly.
- In prefixRange(), initialize index the same way and call std::abort() after the assert so invalid input cannot fall through to an out-of-bounds write.
- Replace C-style uint8_t casts with explicit static_casts.
Closes#59
andrew
merged commit 9449190d02 into main2026-06-29 18:26:05 +00:00
andrew
deleted branch weaselbot/issue-592026-06-29 18:26:06 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #59
strinc()inConflictSet.cppusedstd::string_view::size()(size_t) and subtracted1without first checking for an empty string. For the root node,getSearchPath()returns the empty string, so every debug correctness check underflowedsize_tand relied on implementation-defined conversion toint.prefixRange()inBench.cpphad the same loop shape. AlthoughTrivialSpan::size()returnsint, on an empty (or all-\xff) key the function asserted and then continued executing, allocating a zero-length buffer and writing before its start.Changes:
strinc(), initializeindexas signedint(str.size()) - 1so the loop is skipped for empty input, and returnok = falsecleanly.prefixRange(), initializeindexthe same way and callstd::abort()after the assert so invalid input cannot fall through to an out-of-bounds write.uint8_tcasts with explicitstatic_casts.