-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[analyzer] Model overflow builtins #102602
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
Changes from 7 commits
7b4f999
23923df
2e067c8
d1bb65e
c170268
b2b0b98
412baea
e03fdb4
2cd9158
bb82bfb
dd89f8b
f2b4053
41bf101
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,157 @@ | ||
| // RUN: %clang_analyze_cc1 -triple x86_64-unknown-unknown -verify %s \ | ||
| // RUN: -analyzer-checker=core,debug.ExprInspection | ||
|
|
||
| #define __UINT_MAX__ (__INT_MAX__ * 2U + 1U) | ||
| #define __INT_MIN__ (-__INT_MAX__ - 1) | ||
|
|
||
| void clang_analyzer_dump_int(int); | ||
| void clang_analyzer_dump_long(long); | ||
| void clang_analyzer_eval(int); | ||
| void clang_analyzer_warnIfReached(void); | ||
|
|
||
| void test_add_nooverflow(void) | ||
| { | ||
| int res; | ||
|
|
||
| if (__builtin_add_overflow(10, 20, &res)) { | ||
| clang_analyzer_warnIfReached(); | ||
| return; | ||
| } | ||
|
|
||
| clang_analyzer_dump_int(res); //expected-warning{{30 S32b}} | ||
| } | ||
|
|
||
| void test_add_overflow(void) | ||
| { | ||
| int res; | ||
|
|
||
| if (__builtin_add_overflow(__INT_MAX__, 1, &res)) { | ||
| clang_analyzer_dump_int(res); //expected-warning{{1st function call argument is an uninitialized value}} | ||
| return; | ||
| } | ||
|
|
||
| clang_analyzer_warnIfReached(); | ||
| } | ||
|
|
||
| void test_add_underoverflow(void) | ||
| { | ||
| int res; | ||
|
|
||
| if (__builtin_add_overflow(__INT_MIN__, -1, &res)) { | ||
| clang_analyzer_dump_int(res); //expected-warning{{1st function call argument is an uninitialized value}} | ||
| return; | ||
| } | ||
|
|
||
| clang_analyzer_warnIfReached(); | ||
| } | ||
|
|
||
| void test_sub_underflow(void) | ||
| { | ||
| int res; | ||
|
|
||
| if (__builtin_sub_overflow(__INT_MIN__, 10, &res)) { | ||
| return; | ||
| } | ||
|
|
||
| clang_analyzer_warnIfReached(); | ||
| } | ||
|
|
||
| void test_sub_overflow(void) | ||
| { | ||
| int res; | ||
|
|
||
| if (__builtin_sub_overflow(__INT_MAX__, -1, &res)) { | ||
| return; | ||
| } | ||
|
|
||
| clang_analyzer_warnIfReached(); | ||
| } | ||
|
|
||
| void test_sub_nooverflow(void) | ||
| { | ||
| int res; | ||
|
|
||
| if (__builtin_sub_overflow(__INT_MAX__, 1, &res)) { | ||
| clang_analyzer_warnIfReached(); | ||
| return; | ||
| } | ||
|
|
||
| clang_analyzer_dump_int(res); //expected-warning{{2147483646 S32b}} | ||
| } | ||
|
|
||
| void test_mul_overrflow(void) | ||
pskrgag marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| int res; | ||
|
|
||
| if (__builtin_mul_overflow(__INT_MAX__, 2, &res)) { | ||
| return; | ||
| } | ||
|
|
||
| clang_analyzer_warnIfReached(); | ||
| } | ||
|
|
||
| void test_mul_underrflow(void) | ||
pskrgag marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| int res; | ||
|
|
||
| if (__builtin_mul_overflow(__INT_MIN__, -2, &res)) { | ||
| return; | ||
| } | ||
|
|
||
| clang_analyzer_warnIfReached(); | ||
| } | ||
|
|
||
| void test_mul_nooverflow(void) | ||
| { | ||
| int res; | ||
|
|
||
| if (__builtin_mul_overflow(10, -2, &res)) { | ||
| clang_analyzer_warnIfReached(); | ||
| return; | ||
| } | ||
|
|
||
| clang_analyzer_dump_int(res); //expected-warning{{-20 S32b}} | ||
| } | ||
|
|
||
| void test_nooverflow_diff_types(void) | ||
| { | ||
| long res; | ||
|
|
||
| // This is not an overflow, since result type is long. | ||
| if (__builtin_add_overflow(__INT_MAX__, 1, &res)) { | ||
| clang_analyzer_warnIfReached(); | ||
| return; | ||
| } | ||
|
|
||
| clang_analyzer_dump_long(res); //expected-warning{{2147483648 S64b}} | ||
| } | ||
|
|
||
| void test_uaddll_overflow_contraints(unsigned long a, unsigned long b) | ||
| { | ||
| unsigned long long res; | ||
|
|
||
| if (a != 10) | ||
| return; | ||
| if (b != 10) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Such constraints we call "perfect constraints" as they narrow down the value domain to a single value. After this, the engine will fold all uses of this into a concreteInt, eliminating the symbolic value. Consequently, perfect constraints are different to common constraints. They should have separate tests. That said, two symbolic values with half side constraints are missing. x>=(int max -2, y>= 10 for instance.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've tried to add smth like this, but it fails even for more simple constraint like |
||
| return; | ||
|
|
||
| if (__builtin_uaddll_overflow(a, b, &res)) { | ||
| clang_analyzer_warnIfReached(); | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| void test_uadd_overflow_contraints(unsigned a, unsigned b) | ||
| { | ||
| unsigned res; | ||
|
|
||
| if (a > 5) | ||
| return; | ||
| if (b != 10) | ||
| return; | ||
|
|
||
| if (__builtin_uadd_overflow(a, b, &res)) { | ||
| clang_analyzer_warnIfReached(); | ||
| return; | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.