overflow-prone binary search algorithms in 3rd-party code
Categories
(Core :: Security, defect)
Tracking
()
People
(Reporter: gfritzsche, Unassigned)
References
Details
(Keywords: sec-audit)
Attachments
(1 file)
8.12 KB,
text/plain
|
Details |
Reporter | ||
Comment 1•10 years ago
|
||
Reporter | ||
Comment 2•10 years ago
|
||
Reporter | ||
Comment 3•10 years ago
|
||
Comment 4•10 years ago
|
||
Reporter | ||
Comment 5•10 years ago
|
||
Comment 6•10 years ago
|
||
Updated•9 years ago
|
Updated•5 years ago
|
Comment 7•5 years ago
|
||
So, this is the matcher that would find overflows like the one shared in comment 0, https://godbolt.org/z/cVJD6K, i.e.:
set bind-root false
let assignmentRight expr(
binaryOperator(
allOf(
hasOperatorName("/"),
hasRHS(
integerLiteral(equals(2))),
hasLHS(
binaryOperator(
allOf(
hasOperatorName("+"),
unless(
anyOf(
hasLHS(anyOf(integerLiteral(), characterLiteral(), floatLiteral())),
hasRHS(anyOf(integerLiteral(), characterLiteral(), floatLiteral()))
)
)
)
).bind("addition"))
)
)
).bind("midcalculation")
m assignmentRight
which is matching code like int mid = (low + high) / 2;
and binds the addition enclosed in the parentheses to a node called "addition" and the whole expression on the right-hand side of the assignment to "midcalculation".
This has a couple of minor issues, that I'd like to sort out:
- this doesn't match the whole line (i.e., the assignment) and I can't seem to find a assignmentExpression kind of matcher.
- this doesn't match the types of variables in the addition (e.g.,
low
andhigh
) and I'm not sure whether I want to make this exclusively for integers or also include other sized types (e.g.,uint32_t
) - this explicitly excludes literals by naming them all in an
unless()
-statement (integerLiteral, characterLiteral etc.). They all directly inherit fromexpr()
and AFAIU there's no way to say "any literal".
As a next step, I will sort out how big of these issues listed above are by looking at violations and false positives in our source code.
Looking forward to any guiding comment that folks reading along might have.
Comment 8•5 years ago
|
||
I wrote the LLVM matcher several years ago (code is at https://bug917918.bmoattachments.org/attachment.cgi?id=8486207). In my matcher, I included both (low + high) / 2 and (low + high) >> 1. As I reported in bug 917918 comment 42, the quick-and-dirty matcher only found one false-positive. Considering that the check to make sure it was actually a search only required that the low and high were loop-varying phis, that's pretty precise.
It's been several years, but my recollection is that the >> 1 check did catch a few binary searches.
Comment 9•5 years ago
|
||
Thanks, Joshua. That's super valuable input. My understanding is that I'll get to a better end-result doing the following:
- Build a clang-plugin rule that uses the matcher from comment 8
- adding the right-shift case
- in the
check
function, make sure that low & high are loop-variables (using code from bug 917918 comment 42)
I see how your code is doing step 3, but I don't really understand the underlying logic, just from looking at the patch and the class description at http://llvm.org/doxygen/classllvm_1_1PHINode.html - is there something else you could provide as reading material or maybe explain here in the bug?
I'll also follow up with a WIP patch so we can iterate on working code
Comment 10•4 years ago
|
||
This was implemented in the civet repo.
Updated•4 years ago
|
Updated•4 years ago
|
Updated•3 years ago
|
Description
•