mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
419 lines
6.1 KiB
C++
419 lines
6.1 KiB
C++
class X
|
|
{
|
|
public:
|
|
void set();
|
|
};
|
|
|
|
class Y
|
|
{
|
|
public:
|
|
Y* f();
|
|
|
|
const X* get() const { return 0; }
|
|
X* get() { return 0; }
|
|
};
|
|
|
|
Y* Y::f()
|
|
{
|
|
if ( get() )
|
|
get()->set();
|
|
return 0;
|
|
}
|
|
|
|
class Error {
|
|
public:
|
|
Error() {}
|
|
};
|
|
|
|
bool getABool();
|
|
|
|
void doSomething(int x) {
|
|
if (x == -1) {
|
|
throw new Error();
|
|
}
|
|
}
|
|
|
|
void doSomethingElse(int x);
|
|
|
|
bool testWithCatch0(int v)
|
|
{
|
|
try
|
|
{
|
|
if( getABool() )
|
|
{
|
|
doSomething(v);
|
|
return true;
|
|
}
|
|
}
|
|
catch(Error &e)
|
|
{
|
|
doSomethingElse(v);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void use1(int);
|
|
void use2(int);
|
|
void use3(int);
|
|
|
|
void test_switches_simple(int i) {
|
|
switch(i) {
|
|
case 0:
|
|
use1(i);
|
|
break;
|
|
case 1:
|
|
use2(i);
|
|
/* NOTE: fallthrough */
|
|
case 2:
|
|
use3(i);
|
|
}
|
|
}
|
|
|
|
void test_switches_range(int i) {
|
|
switch(i) {
|
|
case 0 ... 10:
|
|
use1(i);
|
|
break;
|
|
case 11 ... 20:
|
|
use2(i);
|
|
}
|
|
}
|
|
|
|
void test_switches_default(int i) {
|
|
switch(i) {
|
|
default:
|
|
use1(i);
|
|
}
|
|
}
|
|
|
|
void use(...);
|
|
|
|
void pointer_comparison(char* c) {
|
|
if(c) {
|
|
use(c);
|
|
}
|
|
}
|
|
|
|
void implicit_float_comparison(float f) {
|
|
if(f) {
|
|
use(f);
|
|
}
|
|
}
|
|
|
|
void explicit_float_comparison(float f) {
|
|
if(f != 0.0f) {
|
|
use(f);
|
|
}
|
|
}
|
|
|
|
void int_float_comparison(int i) {
|
|
if(i != 0.0f) {
|
|
use(i);
|
|
}
|
|
}
|
|
|
|
int source();
|
|
bool safe(int);
|
|
|
|
void test(bool b)
|
|
{
|
|
int x;
|
|
if (b)
|
|
{
|
|
x = source();
|
|
if (!safe(x)) return;
|
|
}
|
|
use(x);
|
|
}
|
|
|
|
void binary_test_builtin_expected(int a, int b) {
|
|
if(__builtin_expect(a == b + 42, 0)) {
|
|
use(a);
|
|
}
|
|
|
|
if(__builtin_expect(a != b + 42, 0)) {
|
|
use(a);
|
|
}
|
|
}
|
|
|
|
void unary_test_builtin_expected(int a) {
|
|
if(__builtin_expect(a == 42, 0)) {
|
|
use(a);
|
|
}
|
|
|
|
if(__builtin_expect(a != 42, 0)) {
|
|
use(a);
|
|
}
|
|
}
|
|
|
|
void test_with_reference(bool& b, int a) {
|
|
b = a < 10;
|
|
if(!b) {
|
|
use(a);
|
|
}
|
|
}
|
|
|
|
void test_with_negated_binary_equality(int a, int b) {
|
|
bool c = a != b;
|
|
|
|
if (!c) {
|
|
|
|
}
|
|
}
|
|
|
|
void test_with_negated_unary_relational(int a) {
|
|
bool b = a > 10;
|
|
|
|
if (!b) {
|
|
|
|
}
|
|
}
|
|
|
|
void test_with_negated_binary_relational(int a, int b) {
|
|
bool c = a > b;
|
|
|
|
if (!c) {
|
|
|
|
}
|
|
}
|
|
|
|
void test_logical_and(bool b1, bool b2) {
|
|
if(!(b1 && b2)) {
|
|
use(b1);
|
|
use(b2);
|
|
} else {
|
|
// b1 = true and b2 = true
|
|
use(b1);
|
|
use(b2);
|
|
}
|
|
}
|
|
|
|
void test_logical_or(bool b1, bool b2) {
|
|
if(!(b1 || b2)) {
|
|
// b1 = false and b2 = false
|
|
use(b1);
|
|
use(b2);
|
|
} else {
|
|
use(b1);
|
|
use(b2);
|
|
}
|
|
}
|
|
|
|
struct Mystruct {
|
|
int i;
|
|
float f;
|
|
};
|
|
|
|
int test_types(signed char sc, unsigned long ul, float f, double d, bool b, Mystruct &ms) {
|
|
int ctr = 0;
|
|
|
|
if (sc == 0) {
|
|
ctr++;
|
|
}
|
|
if (sc == 0x0) {
|
|
ctr++;
|
|
}
|
|
if (ul == 0) {
|
|
ctr++;
|
|
}
|
|
if (f == 0) {
|
|
ctr++;
|
|
}
|
|
if (f == 0.0) {
|
|
ctr++;
|
|
}
|
|
if (d == 0) {
|
|
ctr++;
|
|
}
|
|
if (b == 0) {
|
|
ctr++;
|
|
}
|
|
if (b == false) {
|
|
ctr++;
|
|
}
|
|
if (ms.i == 0) {
|
|
ctr++;
|
|
}
|
|
if (ms.f == 0) {
|
|
ctr++;
|
|
}
|
|
if (ms.i == 0 && ms.f == 0 && ms.i == 0) {
|
|
ctr++;
|
|
}
|
|
}
|
|
|
|
void test_cmp_implies(int a, int b) {
|
|
if((a == b) == 0) {
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
if((a == b) != 0) {
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
|
|
if((a != b) == 0) {
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
if((a != b) != 0) {
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
|
|
if((a < b) == 0) {
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
if((a < b) != 0) {
|
|
|
|
} else {
|
|
|
|
}
|
|
}
|
|
|
|
void test_cmp_implies_unary(int a) {
|
|
if((a == 42) == 0) {
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
if((a == 42) != 0) {
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
|
|
if((a != 42) == 0) {
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
if((a != 42) != 0) {
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
if((a < 42) == 0) {
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
if((a < 42) != 0) {
|
|
|
|
} else {
|
|
|
|
}
|
|
}
|
|
|
|
int foo();
|
|
|
|
void test_constant_value_and_case_range(bool b)
|
|
{
|
|
int x = foo();
|
|
if (b)
|
|
{
|
|
x = 42;
|
|
}
|
|
switch (x)
|
|
{
|
|
case 40 ... 50:
|
|
// should not be guarded by `foo() = 40..50`
|
|
use(x);
|
|
}
|
|
}
|
|
|
|
void chk();
|
|
|
|
bool testNotNull1(void* input) {
|
|
return input != nullptr;
|
|
}
|
|
|
|
void test_ternary(void* y) {
|
|
int x = testNotNull1(y) ? 42 : 0;
|
|
if (x != 0) {
|
|
chk(); // $ guarded='... ? ... : ...:not 0' guarded='42:not 0' guarded='call to testNotNull1:true' guarded='x != 0:true' guarded='x:not 0' guarded='y:not null'
|
|
}
|
|
}
|
|
|
|
bool testNotNull2(void* input) {
|
|
if (input == nullptr) return false;
|
|
return true;
|
|
}
|
|
|
|
int getNumOrDefault(int* number) {
|
|
return number == nullptr ? 0 : *number;
|
|
}
|
|
|
|
char returnAIfNoneAreNull(char* s1, char* s2) {
|
|
if (!s1 || !s2) return '\0';
|
|
return 'a';
|
|
}
|
|
|
|
enum class Status { SUCCESS = 1, FAILURE = 2 };
|
|
|
|
Status testEnumWrapper(bool flag) {
|
|
return flag ? Status::SUCCESS : Status::FAILURE;
|
|
}
|
|
|
|
void testWrappers(void* p, int* i, char* s, bool b) {
|
|
if (testNotNull1(p)) {
|
|
chk(); // $ guarded='p:not null' guarded='call to testNotNull1:true'
|
|
} else {
|
|
chk(); // $ guarded=p:null guarded='call to testNotNull1:false'
|
|
}
|
|
|
|
if (testNotNull2(p)) {
|
|
chk(); // $ guarded='call to testNotNull2:true' MISSING: guarded='p:not null'
|
|
} else {
|
|
chk(); // $ guarded='call to testNotNull2:false'
|
|
}
|
|
|
|
if (0 == getNumOrDefault(i)) {
|
|
chk(); // $ guarded='0 == call to getNumOrDefault:true' guarded='call to getNumOrDefault:0'
|
|
} else {
|
|
chk(); // $ guarded='0 == call to getNumOrDefault:false' guarded='call to getNumOrDefault:not 0' guarded='i:not null'
|
|
}
|
|
|
|
if ('\0' == returnAIfNoneAreNull(s, "suffix")) {
|
|
chk(); // $ guarded='0 == call to returnAIfNoneAreNull:true' guarded='call to returnAIfNoneAreNull:0'
|
|
} else {
|
|
chk(); // $ guarded='0 == call to returnAIfNoneAreNull:false' guarded='call to returnAIfNoneAreNull:not 0' MISSING: guarded='s:not null'
|
|
}
|
|
|
|
switch (testEnumWrapper(b)) {
|
|
case Status::SUCCESS:
|
|
chk(); // $ guarded='call to testEnumWrapper=SUCCESS:true' guarded='call to testEnumWrapper:1' guarded=b:true
|
|
break;
|
|
case Status::FAILURE:
|
|
chk(); // $ guarded='call to testEnumWrapper=FAILURE:true' guarded='call to testEnumWrapper:2' guarded=b:false
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ensureNotNull(void* o) {
|
|
if (!o) throw 42;
|
|
}
|
|
|
|
void testExceptionWrapper(void* s) {
|
|
chk(); // nothing guards here
|
|
ensureNotNull(s);
|
|
chk(); // $ MISSING: guarded='call to ensureNotNull:no exception' guarded='s:not null'
|
|
}
|