1295fe0bdSJustin Stitt // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-undefined-ignore-overflow-pattern=all %s -emit-llvm -o - | FileCheck %s 2295fe0bdSJustin Stitt // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-undefined-ignore-overflow-pattern=all -fwrapv %s -emit-llvm -o - | FileCheck %s 376236fafSJustin Stitt // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-undefined-ignore-overflow-pattern=add-signed-overflow-test,add-unsigned-overflow-test %s -emit-llvm -o - | FileCheck %s --check-prefix=ADD 4295fe0bdSJustin Stitt // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-undefined-ignore-overflow-pattern=negated-unsigned-const %s -emit-llvm -o - | FileCheck %s --check-prefix=NEGATE 576236fafSJustin Stitt // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-undefined-ignore-overflow-pattern=unsigned-post-decr-while %s -emit-llvm -o - | FileCheck %s --check-prefix=WHILE 6295fe0bdSJustin Stitt 7295fe0bdSJustin Stitt // Ensure some common overflow-dependent or overflow-prone code patterns don't 8295fe0bdSJustin Stitt // trigger the overflow sanitizers. In many cases, overflow warnings caused by 9295fe0bdSJustin Stitt // these patterns are seen as "noise" and result in users turning off 10295fe0bdSJustin Stitt // sanitization all together. 11295fe0bdSJustin Stitt 12295fe0bdSJustin Stitt // A pattern like "if (a + b < a)" simply checks for overflow and usually means 13295fe0bdSJustin Stitt // the user is trying to handle it gracefully. 14295fe0bdSJustin Stitt 15295fe0bdSJustin Stitt // Similarly, a pattern resembling "while (i--)" is extremely common and 16295fe0bdSJustin Stitt // warning on its inevitable overflow can be seen as superfluous. Do note that 17295fe0bdSJustin Stitt // using "i" in future calculations can be tricky because it will still 18295fe0bdSJustin Stitt // wrap-around. 19295fe0bdSJustin Stitt 20295fe0bdSJustin Stitt // Another common pattern that, in some cases, is found to be too noisy is 21295fe0bdSJustin Stitt // unsigned negation, for example: 22295fe0bdSJustin Stitt // unsigned long A = -1UL; 23295fe0bdSJustin Stitt 24*1e5c1a34SChandler Carruth // Skip over parts of the IR containing this file's name. 25*1e5c1a34SChandler Carruth // CHECK: source_filename = {{.*}} 26295fe0bdSJustin Stitt 27*1e5c1a34SChandler Carruth // Ensure we don't see anything about handling overflow before the tests below. 28295fe0bdSJustin Stitt // CHECK-NOT: handle{{.*}}overflow 29295fe0bdSJustin Stitt 30295fe0bdSJustin Stitt extern unsigned a, b, c; 3176236fafSJustin Stitt extern int u, v; 32295fe0bdSJustin Stitt extern unsigned some(void); 33295fe0bdSJustin Stitt 34295fe0bdSJustin Stitt // ADD-LABEL: @basic_commutativity 35295fe0bdSJustin Stitt // WHILE-LABEL: @basic_commutativity 36295fe0bdSJustin Stitt // NEGATE-LABEL: @basic_commutativity 37295fe0bdSJustin Stitt // WHILE: handler.add_overflow 38295fe0bdSJustin Stitt // NEGATE: handler.add_overflow 39295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow 40295fe0bdSJustin Stitt void basic_commutativity(void) { 41295fe0bdSJustin Stitt if (a + b < a) 42295fe0bdSJustin Stitt c = 9; 43295fe0bdSJustin Stitt if (a + b < b) 44295fe0bdSJustin Stitt c = 9; 45295fe0bdSJustin Stitt if (b + a < b) 46295fe0bdSJustin Stitt c = 9; 47295fe0bdSJustin Stitt if (b + a < a) 48295fe0bdSJustin Stitt c = 9; 49295fe0bdSJustin Stitt if (a > a + b) 50295fe0bdSJustin Stitt c = 9; 51295fe0bdSJustin Stitt if (a > b + a) 52295fe0bdSJustin Stitt c = 9; 53295fe0bdSJustin Stitt if (b > a + b) 54295fe0bdSJustin Stitt c = 9; 55295fe0bdSJustin Stitt if (b > b + a) 56295fe0bdSJustin Stitt c = 9; 5776236fafSJustin Stitt if (u + v < u) 5876236fafSJustin Stitt c = 9; 59295fe0bdSJustin Stitt } 60295fe0bdSJustin Stitt 61295fe0bdSJustin Stitt // ADD-LABEL: @arguments_and_commutativity 62295fe0bdSJustin Stitt // WHILE-LABEL: @arguments_and_commutativity 63295fe0bdSJustin Stitt // NEGATE-LABEL: @arguments_and_commutativity 64295fe0bdSJustin Stitt // WHILE: handler.add_overflow 65295fe0bdSJustin Stitt // NEGATE: handler.add_overflow 66295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow 67295fe0bdSJustin Stitt void arguments_and_commutativity(unsigned V1, unsigned V2) { 68295fe0bdSJustin Stitt if (V1 + V2 < V1) 69295fe0bdSJustin Stitt c = 9; 70295fe0bdSJustin Stitt if (V1 + V2 < V2) 71295fe0bdSJustin Stitt c = 9; 72295fe0bdSJustin Stitt if (V2 + V1 < V2) 73295fe0bdSJustin Stitt c = 9; 74295fe0bdSJustin Stitt if (V2 + V1 < V1) 75295fe0bdSJustin Stitt c = 9; 76295fe0bdSJustin Stitt if (V1 > V1 + V2) 77295fe0bdSJustin Stitt c = 9; 78295fe0bdSJustin Stitt if (V1 > V2 + V1) 79295fe0bdSJustin Stitt c = 9; 80295fe0bdSJustin Stitt if (V2 > V1 + V2) 81295fe0bdSJustin Stitt c = 9; 82295fe0bdSJustin Stitt if (V2 > V2 + V1) 83295fe0bdSJustin Stitt c = 9; 84295fe0bdSJustin Stitt } 85295fe0bdSJustin Stitt 86295fe0bdSJustin Stitt // ADD-LABEL: @pointers 87295fe0bdSJustin Stitt // WHILE-LABEL: @pointers 88295fe0bdSJustin Stitt // NEGATE-LABEL: @pointers 89295fe0bdSJustin Stitt // WHILE: handler.add_overflow 90295fe0bdSJustin Stitt // NEGATE: handler.add_overflow 91295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow 92295fe0bdSJustin Stitt void pointers(unsigned *P1, unsigned *P2, unsigned V1) { 93295fe0bdSJustin Stitt if (*P1 + *P2 < *P1) 94295fe0bdSJustin Stitt c = 9; 95295fe0bdSJustin Stitt if (*P1 + V1 < V1) 96295fe0bdSJustin Stitt c = 9; 97295fe0bdSJustin Stitt if (V1 + *P2 < *P2) 98295fe0bdSJustin Stitt c = 9; 99295fe0bdSJustin Stitt } 100295fe0bdSJustin Stitt 101295fe0bdSJustin Stitt struct OtherStruct { 102295fe0bdSJustin Stitt unsigned foo, bar; 103295fe0bdSJustin Stitt }; 104295fe0bdSJustin Stitt 105295fe0bdSJustin Stitt struct MyStruct { 106295fe0bdSJustin Stitt unsigned base, offset; 107295fe0bdSJustin Stitt struct OtherStruct os; 108295fe0bdSJustin Stitt }; 109295fe0bdSJustin Stitt 110295fe0bdSJustin Stitt extern struct MyStruct ms; 111295fe0bdSJustin Stitt 112295fe0bdSJustin Stitt // ADD-LABEL: @structs 113295fe0bdSJustin Stitt // WHILE-LABEL: @structs 114295fe0bdSJustin Stitt // NEGATE-LABEL: @structs 115295fe0bdSJustin Stitt // WHILE: handler.add_overflow 116295fe0bdSJustin Stitt // NEGATE: handler.add_overflow 117295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow 118295fe0bdSJustin Stitt void structs(void) { 119295fe0bdSJustin Stitt if (ms.base + ms.offset < ms.base) 120295fe0bdSJustin Stitt c = 9; 121295fe0bdSJustin Stitt } 122295fe0bdSJustin Stitt 123295fe0bdSJustin Stitt // ADD-LABEL: @nestedstructs 124295fe0bdSJustin Stitt // WHILE-LABEL: @nestedstructs 125295fe0bdSJustin Stitt // NEGATE-LABEL: @nestedstructs 126295fe0bdSJustin Stitt // WHILE: handler.add_overflow 127295fe0bdSJustin Stitt // NEGATE: handler.add_overflow 128295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow 129295fe0bdSJustin Stitt void nestedstructs(void) { 130295fe0bdSJustin Stitt if (ms.os.foo + ms.os.bar < ms.os.foo) 131295fe0bdSJustin Stitt c = 9; 132295fe0bdSJustin Stitt } 133295fe0bdSJustin Stitt 134295fe0bdSJustin Stitt // ADD-LABEL: @constants 135295fe0bdSJustin Stitt // WHILE-LABEL: @constants 136295fe0bdSJustin Stitt // NEGATE-LABEL: @constants 137295fe0bdSJustin Stitt // WHILE: handler.add_overflow 138295fe0bdSJustin Stitt // NEGATE: handler.add_overflow 139295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow 140295fe0bdSJustin Stitt // Normally, this would be folded into a simple call to the overflow handler 141295fe0bdSJustin Stitt // and a store. Excluding this pattern results in just a store. 142295fe0bdSJustin Stitt void constants(void) { 143295fe0bdSJustin Stitt unsigned base = 4294967295; 144295fe0bdSJustin Stitt unsigned offset = 1; 145295fe0bdSJustin Stitt if (base + offset < base) 146295fe0bdSJustin Stitt c = 9; 147295fe0bdSJustin Stitt } 148295fe0bdSJustin Stitt // ADD-LABEL: @common_while 149295fe0bdSJustin Stitt // NEGATE-LABEL: @common_while 150295fe0bdSJustin Stitt // WHILE-LABEL: @common_while 151295fe0bdSJustin Stitt // ADD: usub.with.overflow 152295fe0bdSJustin Stitt // NEGATE: usub.with.overflow 153295fe0bdSJustin Stitt // WHILE: %dec = add i32 %0, -1 154295fe0bdSJustin Stitt void common_while(unsigned i) { 155295fe0bdSJustin Stitt // This post-decrement usually causes overflow sanitizers to trip on the very 156295fe0bdSJustin Stitt // last operation. 157295fe0bdSJustin Stitt while (i--) { 158295fe0bdSJustin Stitt some(); 159295fe0bdSJustin Stitt } 160295fe0bdSJustin Stitt } 161295fe0bdSJustin Stitt 162295fe0bdSJustin Stitt // ADD-LABEL: @negation 163295fe0bdSJustin Stitt // NEGATE-LABEL: @negation 164295fe0bdSJustin Stitt // WHILE-LABEL @negation 165295fe0bdSJustin Stitt // ADD: negate_overflow 166295fe0bdSJustin Stitt // NEGATE-NOT: negate_overflow 167295fe0bdSJustin Stitt // WHILE: negate_overflow 168295fe0bdSJustin Stitt // Normally, these assignments would trip the unsigned overflow sanitizer. 169295fe0bdSJustin Stitt void negation(void) { 170295fe0bdSJustin Stitt #define SOME -1UL 171295fe0bdSJustin Stitt unsigned long A = -1UL; 172295fe0bdSJustin Stitt unsigned long B = -2UL; 173295fe0bdSJustin Stitt unsigned long C = -SOME; 174295fe0bdSJustin Stitt (void)A;(void)B;(void)C; 175295fe0bdSJustin Stitt } 176295fe0bdSJustin Stitt 177295fe0bdSJustin Stitt 178295fe0bdSJustin Stitt // ADD-LABEL: @function_call 179295fe0bdSJustin Stitt // WHILE-LABEL: @function_call 180295fe0bdSJustin Stitt // NEGATE-LABEL: @function_call 181295fe0bdSJustin Stitt // WHILE: handler.add_overflow 182295fe0bdSJustin Stitt // NEGATE: handler.add_overflow 183295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow 184295fe0bdSJustin Stitt void function_call(void) { 185295fe0bdSJustin Stitt if (b + some() < b) 186295fe0bdSJustin Stitt c = 9; 187295fe0bdSJustin Stitt } 188