QL code and tests for C#/C++/JavaScript.

This commit is contained in:
Pavel Avgustinov
2018-08-02 17:53:23 +01:00
commit b55526aa58
10684 changed files with 581163 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
| tst.c:1:12:1:18 | // lgtm | lgtm | lgtm | tst.c:1:1:1:18 | suppression range |
| tst.c:2:1:2:30 | // lgtm[js/debugger-statement] | lgtm[js/debugger-statement] | lgtm[js/debugger-statement] | tst.c:2:1:2:30 | suppression range |
| tst.c:3:1:3:61 | // lgtm[js/debugger-statement, js/invocation-of-non-function] | lgtm[js/debugger-statement, js/invocation-of-non-function] | lgtm[js/debugger-statement, js/invocation-of-non-function] | tst.c:3:1:3:61 | suppression range |
| tst.c:4:1:4:22 | // lgtm[@tag:nullness] | lgtm[@tag:nullness] | lgtm[@tag:nullness] | tst.c:4:1:4:22 | suppression range |
| tst.c:5:1:5:44 | // lgtm[@tag:nullness,js/debugger-statement] | lgtm[@tag:nullness,js/debugger-statement] | lgtm[@tag:nullness,js/debugger-statement] | tst.c:5:1:5:44 | suppression range |
| tst.c:6:1:6:28 | // lgtm[@expires:2017-06-11] | lgtm[@expires:2017-06-11] | lgtm[@expires:2017-06-11] | tst.c:6:1:6:28 | suppression range |
| tst.c:7:1:7:70 | // lgtm[js/invocation-of-non-function] because I know better than lgtm | lgtm[js/invocation-of-non-function] because I know better than lgtm | lgtm[js/invocation-of-non-function] | tst.c:7:1:7:70 | suppression range |
| tst.c:8:1:8:18 | // lgtm: blah blah | lgtm: blah blah | lgtm | tst.c:8:1:8:18 | suppression range |
| tst.c:9:1:9:32 | // lgtm blah blah #falsepositive | lgtm blah blah #falsepositive | lgtm | tst.c:9:1:9:32 | suppression range |
| tst.c:10:1:10:39 | //lgtm [js/invocation-of-non-function] | lgtm [js/invocation-of-non-function] | lgtm [js/invocation-of-non-function] | tst.c:10:1:10:39 | suppression range |
| tst.c:12:1:12:9 | // lgtm[] | lgtm[] | lgtm[] | tst.c:12:1:12:9 | suppression range |
| tst.c:14:1:14:6 | //lgtm | lgtm | lgtm | tst.c:14:1:14:6 | suppression range |
| tst.c:15:1:15:7 | //\tlgtm | \tlgtm | lgtm | tst.c:15:1:15:7 | suppression range |
| tst.c:16:1:16:31 | // lgtm\t[js/debugger-statement] | lgtm\t[js/debugger-statement] | lgtm\t[js/debugger-statement] | tst.c:16:1:16:31 | suppression range |
| tst.c:19:1:19:12 | // foo; lgtm | foo; lgtm | lgtm | tst.c:19:1:19:12 | suppression range |
| tst.c:20:1:20:35 | // foo; lgtm[js/debugger-statement] | foo; lgtm[js/debugger-statement] | lgtm[js/debugger-statement] | tst.c:20:1:20:35 | suppression range |
| tst.c:22:1:22:34 | // foo lgtm[js/debugger-statement] | foo lgtm[js/debugger-statement] | lgtm[js/debugger-statement] | tst.c:22:1:22:34 | suppression range |
| tst.c:24:1:24:38 | // foo lgtm[js/debugger-statement] bar | foo lgtm[js/debugger-statement] bar | lgtm[js/debugger-statement] | tst.c:24:1:24:38 | suppression range |
| tst.c:25:1:25:8 | // LGTM! | LGTM! | LGTM | tst.c:25:1:25:8 | suppression range |
| tst.c:26:1:26:30 | // LGTM[js/debugger-statement] | LGTM[js/debugger-statement] | LGTM[js/debugger-statement] | tst.c:26:1:26:30 | suppression range |
| tst.c:27:1:27:70 | // lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/debugger-statement] | tst.c:27:1:27:70 | suppression range |
| tst.c:27:1:27:70 | // lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/invocation-of-non-function] | tst.c:27:1:27:70 | suppression range |
| tst.c:28:1:28:36 | // lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement]; lgtm | lgtm | tst.c:28:1:28:36 | suppression range |
| tst.c:28:1:28:36 | // lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement] | tst.c:28:1:28:36 | suppression range |
| tstWindows.c:1:12:1:18 | // lgtm | lgtm | lgtm | tstWindows.c:1:1:1:18 | suppression range |
| tstWindows.c:2:1:2:30 | // lgtm[js/debugger-statement] | lgtm[js/debugger-statement] | lgtm[js/debugger-statement] | tstWindows.c:2:1:2:30 | suppression range |
| tstWindows.c:3:1:3:61 | // lgtm[js/debugger-statement, js/invocation-of-non-function] | lgtm[js/debugger-statement, js/invocation-of-non-function] | lgtm[js/debugger-statement, js/invocation-of-non-function] | tstWindows.c:3:1:3:61 | suppression range |
| tstWindows.c:4:1:4:22 | // lgtm[@tag:nullness] | lgtm[@tag:nullness] | lgtm[@tag:nullness] | tstWindows.c:4:1:4:22 | suppression range |
| tstWindows.c:5:1:5:44 | // lgtm[@tag:nullness,js/debugger-statement] | lgtm[@tag:nullness,js/debugger-statement] | lgtm[@tag:nullness,js/debugger-statement] | tstWindows.c:5:1:5:44 | suppression range |
| tstWindows.c:6:1:6:28 | // lgtm[@expires:2017-06-11] | lgtm[@expires:2017-06-11] | lgtm[@expires:2017-06-11] | tstWindows.c:6:1:6:28 | suppression range |
| tstWindows.c:7:1:7:70 | // lgtm[js/invocation-of-non-function] because I know better than lgtm | lgtm[js/invocation-of-non-function] because I know better than lgtm | lgtm[js/invocation-of-non-function] | tstWindows.c:7:1:7:70 | suppression range |
| tstWindows.c:8:1:8:18 | // lgtm: blah blah | lgtm: blah blah | lgtm | tstWindows.c:8:1:8:18 | suppression range |
| tstWindows.c:9:1:9:32 | // lgtm blah blah #falsepositive | lgtm blah blah #falsepositive | lgtm | tstWindows.c:9:1:9:32 | suppression range |
| tstWindows.c:10:1:10:39 | //lgtm [js/invocation-of-non-function] | lgtm [js/invocation-of-non-function] | lgtm [js/invocation-of-non-function] | tstWindows.c:10:1:10:39 | suppression range |
| tstWindows.c:12:1:12:9 | // lgtm[] | lgtm[] | lgtm[] | tstWindows.c:12:1:12:9 | suppression range |
| tstWindows.c:14:1:14:6 | //lgtm | lgtm | lgtm | tstWindows.c:14:1:14:6 | suppression range |
| tstWindows.c:15:1:15:7 | //\tlgtm | \tlgtm | lgtm | tstWindows.c:15:1:15:7 | suppression range |
| tstWindows.c:16:1:16:31 | // lgtm\t[js/debugger-statement] | lgtm\t[js/debugger-statement] | lgtm\t[js/debugger-statement] | tstWindows.c:16:1:16:31 | suppression range |
| tstWindows.c:19:1:19:12 | // foo; lgtm | foo; lgtm | lgtm | tstWindows.c:19:1:19:12 | suppression range |
| tstWindows.c:20:1:20:35 | // foo; lgtm[js/debugger-statement] | foo; lgtm[js/debugger-statement] | lgtm[js/debugger-statement] | tstWindows.c:20:1:20:35 | suppression range |
| tstWindows.c:22:1:22:34 | // foo lgtm[js/debugger-statement] | foo lgtm[js/debugger-statement] | lgtm[js/debugger-statement] | tstWindows.c:22:1:22:34 | suppression range |
| tstWindows.c:24:1:24:38 | // foo lgtm[js/debugger-statement] bar | foo lgtm[js/debugger-statement] bar | lgtm[js/debugger-statement] | tstWindows.c:24:1:24:38 | suppression range |
| tstWindows.c:25:1:25:8 | // LGTM! | LGTM! | LGTM | tstWindows.c:25:1:25:8 | suppression range |
| tstWindows.c:26:1:26:30 | // LGTM[js/debugger-statement] | LGTM[js/debugger-statement] | LGTM[js/debugger-statement] | tstWindows.c:26:1:26:30 | suppression range |
| tstWindows.c:27:1:27:70 | // lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/debugger-statement] | tstWindows.c:27:1:27:70 | suppression range |
| tstWindows.c:27:1:27:70 | // lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/invocation-of-non-function] | tstWindows.c:27:1:27:70 | suppression range |
| tstWindows.c:28:1:28:36 | // lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement]; lgtm | lgtm | tstWindows.c:28:1:28:36 | suppression range |
| tstWindows.c:28:1:28:36 | // lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement] | tstWindows.c:28:1:28:36 | suppression range |

View File

@@ -0,0 +1 @@
AlertSuppression.ql

View File

@@ -0,0 +1,28 @@
int x = 0; // lgtm
// lgtm[js/debugger-statement]
// lgtm[js/debugger-statement, js/invocation-of-non-function]
// lgtm[@tag:nullness]
// lgtm[@tag:nullness,js/debugger-statement]
// lgtm[@expires:2017-06-11]
// lgtm[js/invocation-of-non-function] because I know better than lgtm
// lgtm: blah blah
// lgtm blah blah #falsepositive
//lgtm [js/invocation-of-non-function]
/* lgtm */
// lgtm[]
// lgtmfoo
//lgtm
// lgtm
// lgtm [js/debugger-statement]
// foolgtm[js/debugger-statement]
// foolgtm
// foo; lgtm
// foo; lgtm[js/debugger-statement]
// foo lgtm
// foo lgtm[js/debugger-statement]
// foo lgtm bar
// foo lgtm[js/debugger-statement] bar
// LGTM!
// LGTM[js/debugger-statement]
// lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function]
// lgtm[js/debugger-statement]; lgtm

View File

@@ -0,0 +1,28 @@
int x = 0; // lgtm
// lgtm[js/debugger-statement]
// lgtm[js/debugger-statement, js/invocation-of-non-function]
// lgtm[@tag:nullness]
// lgtm[@tag:nullness,js/debugger-statement]
// lgtm[@expires:2017-06-11]
// lgtm[js/invocation-of-non-function] because I know better than lgtm
// lgtm: blah blah
// lgtm blah blah #falsepositive
//lgtm [js/invocation-of-non-function]
/* lgtm */
// lgtm[]
// lgtmfoo
//lgtm
// lgtm
// lgtm [js/debugger-statement]
// foolgtm[js/debugger-statement]
// foolgtm
// foo; lgtm
// foo; lgtm[js/debugger-statement]
// foo lgtm
// foo lgtm[js/debugger-statement]
// foo lgtm bar
// foo lgtm[js/debugger-statement] bar
// LGTM!
// LGTM[js/debugger-statement]
// lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function]
// lgtm[js/debugger-statement]; lgtm

View File

@@ -0,0 +1,3 @@
| a.cpp:10:6:10:7 | f1 | Function f1 could be moved to file $@ since it has 5 dependencies to that file, but 0 dependencies to its own file. | b.cpp:0:0:0:0 | b.cpp | b.cpp |
| a.cpp:18:6:18:7 | f2 | Function f2 could be moved to file $@ since it has 5 dependencies to that file, but only 1 dependency to its own file. | b.cpp:0:0:0:0 | b.cpp | b.cpp |
| a.cpp:48:6:48:7 | f5 | Function f5 could be moved to file $@ since it has 5 dependencies to that file, but 0 dependencies to its own file. | b.cpp:0:0:0:0 | b.cpp | b.cpp |

View File

@@ -0,0 +1 @@
Architecture/FeatureEnvy.ql

View File

@@ -0,0 +1,57 @@
#include "b.h"
void local1(void) { }
void local2(void) { }
void local3(void) { }
void local4(void) { }
void local5(void) { }
void f1(void) {
g();
h();
i();
j();
k();
}
void f2(void) {
local1();
g();
h();
i();
j();
k();
}
void f3(void) {
local1();
g();
local2();
h();
local3();
i();
local4();
j();
local5();
k();
}
void f4(void) {
local1();
g();
h();
i();
j();
}
void f5(void) {
MyClass m;
m.mg();
m.mh();
m.mi();
m.mj();
m.mk();
}

View File

@@ -0,0 +1,33 @@
#include "b.h"
void g(void) {
}
void h(void) {
}
void i(void) {
}
void j(void) {
}
void k(void) {
}
void MyClass::mg(void) {
}
void MyClass::mh(void) {
}
void MyClass::mi(void) {
}
void MyClass::mj(void) {
}
void MyClass::mk(void) {
}

View File

@@ -0,0 +1,16 @@
void g(void);
void h(void);
void i(void);
void j(void);
void k(void);
class MyClass {
public:
void mg(void);
void mh(void);
void mi(void);
void mj(void);
void mk(void);
};

View File

@@ -0,0 +1,2 @@
| a.c:0:0:0:0 | a.c | File is too closely tied to $@ (22 dependencies one way and 21 the other). | b.c:0:0:0:0 | b.c | b.c |
| c.cpp:0:0:0:0 | c.cpp | File is too closely tied to $@ (22 dependencies one way and 21 the other). | d.cpp:0:0:0:0 | d.cpp | d.cpp |

View File

@@ -0,0 +1 @@
Architecture/InappropriateIntimacy.ql

View File

@@ -0,0 +1,26 @@
#include "b.h"
void f1(void) { g1(); }
void f2(void) { g2(); }
void f3(void) { g3(); }
void f4(void) { g4(); }
void f5(void) { g5(); }
void f6(void) { g6(); }
void f7(void) { g7(); }
void f8(void) { g8(); }
void f9(void) { g9(); }
void f10(void) { g10(); }
void f11(void) { g11(); }
void f12(void) { g12(); }
void f13(void) { g13(); }
void f14(void) { g14(); }
void f15(void) { g15(); }
void f16(void) { g16(); }
void f17(void) { g17(); }
void f18(void) { g18(); }
void f19(void) { g19(); }
void f20(void) { g20(); }
void f21(void) { g21(); }
void f22(void) { g22(); }

View File

@@ -0,0 +1,23 @@
void f1(void);
void f2(void);
void f3(void);
void f4(void);
void f5(void);
void f6(void);
void f7(void);
void f8(void);
void f9(void);
void f10(void);
void f11(void);
void f12(void);
void f13(void);
void f14(void);
void f15(void);
void f16(void);
void f17(void);
void f18(void);
void f19(void);
void f20(void);
void f21(void);

View File

@@ -0,0 +1,26 @@
#include "a.h"
void g1(void) { f1(); }
void g2(void) { f2(); }
void g3(void) { f3(); }
void g4(void) { f4(); }
void g5(void) { f5(); }
void g6(void) { f6(); }
void g7(void) { f7(); }
void g8(void) { f8(); }
void g9(void) { f9(); }
void g10(void) { f10(); }
void g11(void) { f11(); }
void g12(void) { f12(); }
void g13(void) { f13(); }
void g14(void) { f14(); }
void g15(void) { f15(); }
void g16(void) { f16(); }
void g17(void) { f17(); }
void g18(void) { f18(); }
void g19(void) { f19(); }
void g20(void) { f20(); }
void g21(void) { f21(); }
void g22(void) { }

View File

@@ -0,0 +1,24 @@
void g1(void);
void g2(void);
void g3(void);
void g4(void);
void g5(void);
void g6(void);
void g7(void);
void g8(void);
void g9(void);
void g10(void);
void g11(void);
void g12(void);
void g13(void);
void g14(void);
void g15(void);
void g16(void);
void g17(void);
void g18(void);
void g19(void);
void g20(void);
void g21(void);
void g22(void);

View File

@@ -0,0 +1,27 @@
#include "c.h"
#include "d.h"
void C::f1() { d->g1(); }
void C::f2() { d->g2(); }
void C::f3() { d->g3(); }
void C::f4() { d->g4(); }
void C::f5() { d->g5(); }
void C::f6() { d->g6(); }
void C::f7() { d->g7(); }
void C::f8() { d->g8(); }
void C::f9() { d->g9(); }
void C::f10() { d->g10(); }
void C::f11() { d->g11(); }
void C::f12() { d->g12(); }
void C::f13() { d->g13(); }
void C::f14() { d->g14(); }
void C::f15() { d->g15(); }
void C::f16() { d->g16(); }
void C::f17() { d->g17(); }
void C::f18() { d->g18(); }
void C::f19() { d->g19(); }
void C::f20() { d->g20(); }
void C::f21() { d->g21(); }
void C::f22() { d->g22(); }

View File

@@ -0,0 +1,30 @@
class D;
class C {
D *d;
public:
void f1();
void f2();
void f3();
void f4();
void f5();
void f6();
void f7();
void f8();
void f9();
void f10();
void f11();
void f12();
void f13();
void f14();
void f15();
void f16();
void f17();
void f18();
void f19();
void f20();
void f21();
void f22();
};

View File

@@ -0,0 +1,27 @@
#include "c.h"
#include "d.h"
void D::g1() { c->f1(); }
void D::g2() { c->f2(); }
void D::g3() { c->f3(); }
void D::g4() { c->f4(); }
void D::g5() { c->f5(); }
void D::g6() { c->f6(); }
void D::g7() { c->f7(); }
void D::g8() { c->f8(); }
void D::g9() { c->f9(); }
void D::g10() { c->f10(); }
void D::g11() { c->f11(); }
void D::g12() { c->f12(); }
void D::g13() { c->f13(); }
void D::g14() { c->f14(); }
void D::g15() { c->f15(); }
void D::g16() { c->f16(); }
void D::g17() { c->f17(); }
void D::g18() { c->f18(); }
void D::g19() { c->f19(); }
void D::g20() { c->f20(); }
void D::g21() { c->f21(); }
void D::g22() { }

View File

@@ -0,0 +1,30 @@
class C;
class D {
C *c;
public:
void g1();
void g2();
void g3();
void g4();
void g5();
void g6();
void g7();
void g8();
void g9();
void g10();
void g11();
void g12();
void g13();
void g14();
void g15();
void g16();
void g17();
void g18();
void g19();
void g20();
void g21();
void g22();
};

View File

@@ -0,0 +1,58 @@
// semmle-extractor-options: --clang
#define TEN(X) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10)
#define int_f(n) int f##n;
#define int_g(n) int g##n;
struct aa {
TEN(int_f)
TEN(int_g)
};
class bb {
TEN(int_f)
TEN(int_g)
};
union cc_not_flagged_up_because_unions_are_not_classes_in_this_sense {
TEN(int_f)
TEN(int_g)
};
template <typename T>
struct dd {
TEN(int_f)
TEN(int_g)
};
template <typename U>
struct ee {
TEN(int_f)
TEN(int_g)
};
void instantiate() {
dd<float> d1;
dd<int> d2;
}
// from the qhelp (30 fields)
struct MyParticle {
bool isActive;
int priority;
float x, y, z;
float dx, dy, dz;
float ddx, ddy, ddz;
bool isCollider;
int age, maxAge;
float size1, size2;
bool hasColor;
unsigned char r1, g1, b1, a1;
unsigned char r2, g2, b2, a2;
class texture *tex;
float u1, v1, u2, v2;
};

View File

@@ -0,0 +1,7 @@
| cwmf.cpp:8:3:9:12 | aa | Struct aa has 20 fields, which is too many. | cwmf.cpp:8:3:9:12 | group of 20 fields here | group of 20 fields here |
| cwmf.cpp:13:3:14:12 | bb | Class bb has 20 fields, which is too many. | cwmf.cpp:13:3:14:12 | group of 20 fields here | group of 20 fields here |
| cwmf.cpp:24:3:25:12 | dd<T> | Template class dd<T> has 20 fields, which is too many. | cwmf.cpp:24:3:25:12 | group of 20 fields here | group of 20 fields here |
| cwmf.cpp:30:3:31:12 | ee<U> | Template class ee<U> has 20 fields, which is too many. | cwmf.cpp:30:3:31:12 | group of 20 fields here | group of 20 fields here |
| cwmf.cpp:41:8:57:22 | MyParticle | Struct MyParticle has 30 fields, which is too many. | cwmf.cpp:41:8:57:22 | group of 30 fields here | group of 30 fields here |
| different_types.h:15:15:33:10 | DifferentTypes2 | Class DifferentTypes2 has 18 fields, which is too many. | different_types.h:15:15:33:10 | group of 18 fields here | group of 18 fields here |
| different_types.h:15:15:33:10 | DifferentTypes2 | Class DifferentTypes2 has 18 fields, which is too many. | different_types.h:15:15:33:10 | group of 18 fields here | group of 18 fields here |

View File

@@ -0,0 +1 @@
Architecture/Refactoring Opportunities/ClassesWithManyFields.ql

View File

@@ -0,0 +1,35 @@
class DifferentTypes {
SOME_TYPE i1;
SOME_TYPE i2;
SOME_TYPE i3;
SOME_TYPE i4;
SOME_TYPE i5;
SOME_TYPE i6;
SOME_TYPE i7;
SOME_TYPE i8;
SOME_TYPE i9;
};
class DifferentTypes2 {
SOME_TYPE i1;
SOME_TYPE i2;
SOME_TYPE i3;
SOME_TYPE i4;
SOME_TYPE i5;
SOME_TYPE i6;
SOME_TYPE i7;
SOME_TYPE i8;
SOME_TYPE i9;
int j1;
int j2;
int j3;
int j4;
int j5;
int j6;
int j7;
int j8;
int j9;
};

View File

@@ -0,0 +1,4 @@
#define SOME_TYPE unsigned char
#include "different_types.h"

View File

@@ -0,0 +1,4 @@
#define SOME_TYPE signed char
#include "different_types.h"

View File

@@ -0,0 +1 @@
| complex.c:14:6:14:6 | h | This function makes too many calls (112) |

View File

@@ -0,0 +1 @@
Architecture/Refactoring Opportunities/ComplexFunctions.ql

View File

@@ -0,0 +1,24 @@
void f(void) { }
void g(void) {
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
}
void h(void) {
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
}

View File

@@ -0,0 +1,2 @@
| hiding.cpp:4:17:4:18 | ii | Local variable 'ii' hides a $@. | hiding.cpp:2:12:2:13 | definition of ii | parameter of the same name |
| hiding.cpp:15:15:15:16 | kk | Local variable 'kk' hides a $@. | hiding.cpp:12:25:12:26 | definition of kk | parameter of the same name |

View File

@@ -0,0 +1 @@
Best Practices/Hiding/DeclarationHidesParameter.ql

View File

@@ -0,0 +1,24 @@
void f(int ii) {
if (1) {
for(int ii = 1; ii < 10; ii++) {
;
}
}
}
namespace foo {
namespace bar {
void f2(int ii, int kk) {
try {
for (ii = 0; ii < 3; ii++) {
int kk;
}
}
catch (int ee) {
}
}
}
}

View File

@@ -0,0 +1,2 @@
| hiding.cpp:6:17:6:17 | i | Variable i hides another variable of the same name (on $@). | hiding.cpp:4:13:4:13 | i | line 4 |
| hiding.cpp:18:15:18:15 | k | Variable k hides another variable of the same name (on $@). | hiding.cpp:15:11:15:11 | k | line 15 |

View File

@@ -0,0 +1 @@
Best Practices/Hiding/DeclarationHidesVariable.ql

View File

@@ -0,0 +1,27 @@
void f(void) {
if (1) {
int i;
for(int i = 1; i < 10; i++) {
;
}
}
}
namespace foo {
namespace bar {
void f2(int i) {
int k;
try {
for (i = 0; i < 3; i++) {
int k;
}
}
catch (int e) {
}
}
}
}

View File

@@ -0,0 +1,3 @@
| Hiding.c:15:25:15:25 | i | Variable i hides another variable of the same name (on $@). | Hiding.c:7:9:7:9 | i | line 7 |
| Hiding.c:16:25:16:25 | j | Variable j hides another variable of the same name (on $@). | Hiding.c:10:13:10:13 | j | line 10 |
| Hiding.c:17:25:17:25 | k | Variable k hides another variable of the same name (on $@). | Hiding.c:13:21:13:21 | k | line 13 |

View File

@@ -0,0 +1 @@
Best Practices/Hiding/DeclarationHidesVariable.ql

View File

@@ -0,0 +1,40 @@
int gi;
extern int gj;
static int gk;
void f(void) {
int i;
if (1) {
int j;
if (1)
if(1) {
int k;
if(1) {
int i; // BAD (hides local)
int j; // BAD (hides local)
int k; // BAD (hides local)
int l;
int m;
int n;
int gi; // BAD (hides global)
int gj; // BAD (hides global)
int gk; // BAD (hides global)
}
int l; // GOOD (scopes do not overlap)
}
int m; // GOOD (scopes do not overlap)
}
int n; // GOOD (scopes do not overlap)
}
int g1, g2, g3, g4, g5;
void function1(int g1); // GOOD (the hiding name isn't associated with a code block)
extern void function2(int g2); // GOOD (the hiding name isn't associated with a code block)
void function3(int g3) {}; // BAD
void function4(int g4); // GOOD (the hiding name isn't associated with a code block)
void function4(int g5) {}; // BAD

View File

@@ -0,0 +1,5 @@
| Hiding.c:22:25:22:26 | definition of gi | Local variable gi hides $@ with the same name. | Hiding.c:2:5:2:6 | gi | a global variable |
| Hiding.c:23:25:23:26 | definition of gj | Local variable gj hides $@ with the same name. | Hiding.c:3:12:3:13 | gj | a global variable |
| Hiding.c:24:25:24:26 | definition of gk | Local variable gk hides $@ with the same name. | Hiding.c:4:12:4:13 | gk | a global variable |
| Hiding.c:37:20:37:21 | definition of g3 | Parameter g3 hides $@ with the same name. | Hiding.c:33:13:33:14 | g3 | a global variable |
| Hiding.c:40:20:40:21 | definition of g5 | Parameter g5 hides $@ with the same name. | Hiding.c:33:21:33:22 | g5 | a global variable |

View File

@@ -0,0 +1 @@
Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql

View File

@@ -0,0 +1,3 @@
| empty_block.cpp:7:10:7:11 | { ... } | Empty block without comment |
| empty_block.cpp:10:10:11:3 | { ... } | Empty block without comment |
| empty_block.cpp:18:10:19:3 | { ... } | Empty block without comment |

View File

@@ -0,0 +1 @@
Best Practices/Likely Errors/EmptyBlock.ql

View File

@@ -0,0 +1,51 @@
// GOOD:
void f() {
}
int f(int x) {
// BAD:
if (x) {}
// BAD:
if (x) {
}
if (x) {
// GOOD (has comment)
}
// BAD (comment comes after):
if (x) {
}
// comment
// GOOD (exception for loops with block on same line):
while (--x == 27) {}
// GOOD:
while (--x == 2) {
}
// GOOD:
do {
} while (--x == 2);
// GOOD:
if (x) {
#ifdef NOT_DEFINED
return 7;
#endif
}
#define EMPTY
// GOOD:
if (x) {
EMPTY
}
// GOOD (no block)
if (1) ;
// GOOD (no block)
for (;;) ;
}

View File

@@ -0,0 +1 @@
| test.cpp:13:3:13:9 | ... = ... | This assignment expression slices from type $@ to $@ | test.cpp:6:8:6:13 | Point3 | Point3 | test.cpp:1:8:1:13 | Point2 | Point2 |

View File

@@ -0,0 +1 @@
Best Practices/Likely Errors/Slicing.ql

View File

@@ -0,0 +1,20 @@
struct Point2 {
int x;
int y;
};
struct Point3 : Point2 {
int z;
};
void f() {
Point2 p2;
Point3 p3;
p2 = p3;
}
void g() {
Point2* p2 = 0;
Point3* p3 = 0;
p2 = p3;
}

View File

@@ -0,0 +1,18 @@
| a123.c:5:9:5:11 | 123 | Magic constant: literal '123' is repeated 33 times and should be encapsulated in a constant. |
| b123.c:3:14:3:16 | 123 | Magic constant: literal '123' is repeated 33 times and should be encapsulated in a constant. |
| case.c:4:10:4:12 | 123 | Magic constant: literal '123' is repeated 33 times and should be encapsulated in a constant. |
| case.c:4:18:4:20 | 129 | Magic constant: literal '129' is repeated 31 times and should be encapsulated in a constant. |
| constants.h:5:9:5:11 | 123 | Magic constant: literal '123' is repeated 33 times and should be encapsulated in a constant. |
| constants.h:5:9:5:11 | 123 | Magic constant: literal '123' is repeated 33 times and should be encapsulated in a constant. |
| constants.h:60:9:60:14 | 120 | Magic constant: literal '120' is repeated 30 times and should be encapsulated in a constant. |
| constants.h:60:9:60:14 | 120 | Magic constant: literal '120' is repeated 30 times and should be encapsulated in a constant. |
| constants.h:91:9:91:14 | 504 | Magic constant: literal '504' is repeated 30 times and should be encapsulated in a constant. |
| constants.h:91:9:91:14 | 504 | Magic constant: literal '504' is repeated 30 times and should be encapsulated in a constant. |
| constants.h:122:9:122:13 | 278 | Magic constant: literal '278' is repeated 30 times and should be encapsulated in a constant. |
| constants.h:122:9:122:13 | 278 | Magic constant: literal '278' is repeated 30 times and should be encapsulated in a constant. |
| constants.h:153:10:153:12 | 129 | Magic constant: literal '129' is repeated 31 times and should be encapsulated in a constant. |
| constants.h:153:10:153:12 | 129 | Magic constant: literal '129' is repeated 31 times and should be encapsulated in a constant. |
| functions.h:3:2:3:4 | 102 | Magic constant: literal '102' is repeated 21 times and should be encapsulated in a constant. |
| functions.h:3:8:3:10 | 102 | Magic constant: literal '102' is repeated 21 times and should be encapsulated in a constant. |
| functions.h:3:14:3:16 | 102 | Magic constant: literal '102' is repeated 21 times and should be encapsulated in a constant. |
| functions.h:12:11:12:13 | 103 | Magic constant: literal '103' is repeated 21 times and should be encapsulated in a constant. |

View File

@@ -0,0 +1 @@
Best Practices/Magic Constants/MagicConstantsNumbers.ql

View File

@@ -0,0 +1,7 @@
static void f(void) {
int i;
i = 123;
}

View File

@@ -0,0 +1,5 @@
static void f(void) {
char str[123];
}

View File

@@ -0,0 +1,7 @@
static void f(void) {
const int i = 120;
char str[i + 3];
}

View File

@@ -0,0 +1,8 @@
void f(int i) {
switch(i) {
case 123 ... 129:
break;
}
}

View File

@@ -0,0 +1,217 @@
void FUN(void) {
int i, j, k;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
i = 123;
j = 456;
j = 456;
j = 456;
j = 456;
j = 456;
j = 456;
j = 456;
j = 456;
j = 456;
j = 456;
j = 456;
j = 456;
j = 456;
j = 456;
j = 456;
k = 789;
k = 789;
k = 789;
k = 789;
k = 789;
k = 789;
k = 789;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x0078;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 0x01f8;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = 278UL;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
i = -129;
int a123 = 127;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
i = a123;
}

View File

@@ -0,0 +1,8 @@
static void f(void) {
const int i = 120;
const int j = i + 3;
char str[j];
}

View File

@@ -0,0 +1,9 @@
// GENERATED FILE
// ...
// it's not, it's a hand-written test, but we want to assume it is one.
static void f(void) {
int i;
i = 123;
}

View File

@@ -0,0 +1,33 @@
int myFunction1(int x =
102 + 102 + 102 +
102 + 102 + 102 +
102 + 102 + 102 +
102 + 102 + 102 +
102 + 102 + 102 +
102 + 102 + 102 +
102 + 102 + 102);
void myFunction2(
int p1 = 103,
int p2 = 103,
int p3 = 103,
int p4 = 103,
int p5 = 103,
int p6 = 103,
int p7 = 103,
int p8 = 103,
int p9 = 103,
int p10 = 103,
int p11 = 103,
int p12 = 103,
int p13 = 103,
int p14 = 103,
int p15 = 103,
int p16 = 103,
int p17 = 103,
int p18 = 103,
int p19 = 103,
int p20 = 103,
int p21 = 103
) {};

View File

@@ -0,0 +1,9 @@
#define FUN f
#include "constants.h"
#undef FUN
#define FUN g
#include "constants.h"
#undef FUN

View File

@@ -0,0 +1,14 @@
#include "functions.h"
int myFunction1(int x) {
return x;
}
void myCaller() {
myFunction1();
myFunction1();
myFunction1(104);
myFunction2(105);
myFunction2();
}

View File

@@ -0,0 +1,5 @@
| constants.h:5:9:5:19 | abcabcabc | Magic constant: literal 'abcabcabc' is repeated 30 times and should be encapsulated in a constant. |
| constants.h:5:9:5:19 | abcabcabc | Magic constant: literal 'abcabcabc' is repeated 30 times and should be encapsulated in a constant. |
| joining.cpp:39:5:39:18 | testrepo.git | Magic constant: literal 'testrepo.git' is repeated 21 times and should be encapsulated in a constant. |
| joining.cpp:107:8:107:28 | NO T_VOID CONSTRUCT | Magic constant: literal 'NO T_VOID CONSTRUCT' is repeated 21 times and should be encapsulated in a constant. |
| joining.cpp:173:8:173:47 | compiler error: no const of base type | Magic constant: literal 'compiler error: no const of base type ' is repeated 21 times and should be encapsulated in a constant. |

View File

@@ -0,0 +1 @@
Best Practices/Magic Constants/MagicConstantsString.ql

View File

@@ -0,0 +1,60 @@
void FUN(void) {
const char *s;
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "abcabcabc";
s = "defdefdef";
s = "defdefdef";
s = "defdefdef";
s = "defdefdef";
s = "defdefdef";
s = "defdefdef";
s = "defdefdef";
s = "defdefdef";
s = "defdefdef";
s = "defdefdef";
s = "defdefdef";
s = "defdefdef";
s = "defdefdef";
s = "defdefdef";
s = "defdefdef";
s = "ghighighi";
s = "ghighighi";
s = "ghighighi";
s = "ghighighi";
s = "ghighighi";
s = "ghighighi";
s = "ghighighi";
}

View File

@@ -0,0 +1,194 @@
// --- string ---
class string
{
public:
string(const char *str)
{
// ...
}
// ...
};
string operator+(const string &lhs, const string &rhs)
{
// ...
}
// --- ostream ---
class ostream
{
public:
// ...
};
ostream &operator<<(ostream &stream, const string &str)
{
// ...
}
// --- tests ---
void fn(const string &str1);
void joining_test(const string &x, const string &y) \
{
fn("testrepo.git"); // BAD: "testrepo.git"
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git");
fn("testrepo.git"); // (21 times)
fn(x + " extends " + y); // GOOD
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y);
fn(x + " extends " + y); // (21 times)
fn("type error: " + x + " has no field " + y); // GOOD
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y);
fn("type error: " + x + " has no field " + y); // (21 times)
ostream os;
os << "NO T_VOID CONSTRUCT"; // BAD: "NO T_VOID CONSTRUCT"
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT";
os << "NO T_VOID CONSTRUCT"; // (21 times)
os << "{" << x << "} else {" << y << "}"; // GOOD
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}";
os << "{" << x << "} else {" << y << "}"; // (21 times)
os << "writeString(" << x << ")"; // GOOD
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")";
os << "writeString(" << x << ")"; // (21 times)
os << "compiler error: no const of base type " + x; // BAD: "compiler error: no const of base type "
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x;
os << "compiler error: no const of base type " + x; // (21 times)
}

View File

@@ -0,0 +1,9 @@
#define FUN f
#include "constants.h"
#undef FUN
#define FUN g
#include "constants.h"
#undef FUN

View File

@@ -0,0 +1,313 @@
// NOT OK
struct CopyButNoAssign {
CopyButNoAssign() : n(0) {}
CopyButNoAssign(const CopyButNoAssign& copy_from) : n(copy_from.n) {}
int n;
};
// NOT OK
struct AssignButNoCopy {
AssignButNoCopy& operator=(const AssignButNoCopy& assign_from) { return *this; }
};
// OK: before C++11, marking a constructor as private was an
// acceptable way to delete it. The constructor still might get used by
// accident within the scope of the class and its friends, but we tolerate that
// in order to avoid false positives on such code.
struct NotCopyable {
NotCopyable() {}
private:
NotCopyable(const NotCopyable& cannot_copy) {}
};
// OK: C++11 version of NotCopyable
struct NotCopyable11 {
NotCopyable11(const NotCopyable11&) = delete;
};
// OK: both defined
struct HasBoth {
HasBoth() {}
HasBoth(const HasBoth& copy_from) {}
HasBoth& operator=(const HasBoth& assign_from) { return *this; }
};
// OK: both generated
struct HasGenerated {
HasBoth m_member;
};
// OK: this class gets a generated copy constructor but no copy
// assignment. We don't flag this as an error -- trying to copy-assign it will
// be a compilation error.
struct ConstMember {
const int x;
};
// OK: this class declares a copy constructor but no copy
// assignment. But because it has a const member, it does not get a
// compiler-defined copy assignment operator, so there is no potential
// memory safety problem.
struct ConstMemberAndCopy {
const int x;
ConstMemberAndCopy(): x(4) {}
ConstMemberAndCopy(const ConstMemberAndCopy& that): x(that.x) {}
};
// OK: Our class won't get a copy constructor.
struct NoAutoCopy {
NotCopyable x; // has no copy constructor but has copy assignment
NoAutoCopy& operator=(const NoAutoCopy& that) { x = that.x; return *this; }
};
// OK: When viewed in isolation, this class seems to use the pre-C++11 idiom of
// suppressing an auto-generated member by making it inaccessible.
struct CopyableByFriend {
friend struct MyClassFriend;
private:
CopyableByFriend(CopyableByFriend &) {} // OK: private
};
// OK: No auto-generated copy constructor
struct NotFriend {
CopyableByFriend x;
NotFriend& operator=(const NotFriend& that) { return *this; }
};
// NOT OK: Gets an auto-generated copy constructor because the class is a
// friend of CopyableByFriend.
struct MyClassFriend {
CopyableByFriend x;
MyClassFriend& operator=(const MyClassFriend& that) { return *this; }
};
// OK or NOT OK? An explicit default and an explicit implementation.
struct UsesDefault {
UsesDefault(UsesDefault&) = default;
UsesDefault& operator=(UsesDefault& ud) { return *this; }
};
// OK: copy constructor is user-defined, and there is no copy assignment.
struct DeletedAssign {
DeletedAssign(DeletedAssign&) {}
DeletedAssign& operator=(DeletedAssign& ud) = delete;
};
// OK: volatile instances can only be copied but not assigned, and that is
// not a correctness problem.
struct ProtectedVolatile {
protected:
ProtectedVolatile(const volatile ProtectedVolatile& that) {}
public:
ProtectedVolatile() {}
ProtectedVolatile(const ProtectedVolatile& that) {}
ProtectedVolatile& operator=(const ProtectedVolatile& that) {
return *this;
}
};
// OK: because `pv` is volatile, the compiler will try to generate a call to
// the protected copy constructor of ProtectedVolatile that takes a volatile
// argument. When access to this constructor fails, this class does not get an
// auto-generated copy constructor at all.
struct HasVPV {
volatile ProtectedVolatile vpv;
HasVPV& operator=(const HasVPV& that) {
return *this;
}
};
// FALSE NEGATIVE: the relevant copy constructor of ProtectedVolatile is
// accessible, so our class will get a generated copy constructor. Our query
// thinks the copy constructor is inaccessible because it picks up the other
// copy constructor. To fix this, our library should be changed to distinguish
// between copy constructors and resolve overloading properly instead of
// assuming that there is at most one.
struct HasPV {
ProtectedVolatile pv;
HasPV& operator=(const HasPV& that) {
return *this;
}
};
// OK: has explicit copy constructor and copy assignment operator.
struct ProtectedAssign {
ProtectedAssign() {}
ProtectedAssign(const ProtectedAssign& that) {}
protected:
ProtectedAssign& operator=(const ProtectedAssign& that) { return *this; }
};
// NOT OK: this class gets a copy assignment operator because it can access the
// (protected) copy assignment operator of its base class.
struct IsAProtectedAssign: public ProtectedAssign {
IsAProtectedAssign(const IsAProtectedAssign& that) {}
};
// OK: this class gets no copy assignment operator. It cannot access the
// (protected) copy assignment operator of its field even though it can access
// the same operator on its base class. For protected members, access is
// special when going through objects with the class of `this`.
struct HasAndIsAProtectedAssign: public ProtectedAssign {
ProtectedAssign fieldB;
HasAndIsAProtectedAssign(const HasAndIsAProtectedAssign& that) {}
};
// OK: has explicit copy constructor and copy assignment operator.
struct ProtectedCC {
ProtectedCC() {}
ProtectedCC& operator=(const ProtectedCC& that) { return *this; }
protected:
ProtectedCC(const ProtectedCC& that) {}
};
// NOT OK: this class gets a copy constructor because it can access the
// (protected) copy constructor of its base class.
struct IsAProtectedCC: public ProtectedCC {
IsAProtectedCC& operator=(const IsAProtectedCC& that) { return *this; }
};
// OK: this class gets no copy constructor. It cannot access the (protected)
// copy constructor of its field even though it can access the same operator on
// its base class. For protected members, access is special when going through
// objects with the class of `this`.
struct HasAndIsAProtectedCC: public ProtectedCC {
ProtectedCC fieldB;
HasAndIsAProtectedCC& operator=(const HasAndIsAProtectedCC& that) {
return *this;
}
};
// OK: defines both
struct DerivesVirtual: virtual public NotCopyable {
DerivesVirtual(const DerivesVirtual& that) {}
DerivesVirtual& operator=(const DerivesVirtual& that) { return *this; }
};
// OK: overrides only assignment but gets no auto-generated copy constructor
// because a virtual non-direct base class is not copyable.
struct DerivesDerivesVirtual: public DerivesVirtual {
DerivesDerivesVirtual& operator=(const DerivesDerivesVirtual& that) {
return *this;
}
};
// OK: templates and their instantiations are ignored, but this class would
// be correct anyway.
template<class T>
struct HasBoth_template {
T t_;
HasBoth_template() {}
HasBoth_template(const HasBoth_template<T>& copy_from)
: t_(copy_from.t_)
{}
HasBoth_template& operator=(const HasBoth_template<T>& assign_from) {
t_ = assign_from.t_;
return *this;
}
};
void use_copy_ctor(HasBoth_template<int> obj) {
HasBoth_template<int> copy = obj;
}
// NOT OK (FALSE NEGATIVE): because this template is never instantiated, it
// does not appear in the database and is not caught by the analysis.
template<class T>
struct CopyButNoAssign_template {
CopyButNoAssign_template() : n() {}
CopyButNoAssign_template(const CopyButNoAssign_template& copy_from) : n(copy_from.n) {}
T n;
};
// OK: copy assignment operator is uncallable because (a) it's private and (b)
// it has only a declaration but no definition, so the program would fail to
// link.
class UncallableCopyAssignment {
public:
UncallableCopyAssignment(const UncallableCopyAssignment& other) { }
UncallableCopyAssignment() { }
private:
void operator=(UncallableCopyAssignment const &);
};
// OK: both members are "default"
struct BothDefault {
BothDefault(BothDefault&) = default;
BothDefault& operator=(BothDefault& bd) = default;
};
// OK: template class _with_ initializer on extra argument of copy constructor.
// We do not extract initializers of template functions or of functions in
// template classes, so our definition of a copy constructor is conservative
// and assumes they are present, which is correct in this case (`x` has `= 0`).
template<typename T>
class TemplateWithInit {
public:
TemplateWithInit() {}
TemplateWithInit(const TemplateWithInit& rhs, int x = 0) {
*this = rhs;
}
TemplateWithInit& operator=(const TemplateWithInit& rhs) {
return *this;
}
};
void useGenericPointerAssign(TemplateWithInit<char> twi) {
TemplateWithInit<char> twi2;
twi2 = twi;
}
// NOT OK (FALSE NEGATIVE): template class _without_ initializer on extra
// argument of copy constructor. Like `TemplateWithInit` above but without `= 0`
// on `x`.
template<typename T>
class TemplateWithExtraArg {
public:
TemplateWithExtraArg() {}
TemplateWithExtraArg(const TemplateWithExtraArg& rhs, int x) {
*this = rhs;
}
TemplateWithExtraArg& operator=(const TemplateWithExtraArg& rhs) {
return *this;
}
};
void useTemplateWithExtraArgAssign(TemplateWithExtraArg<char> twaa) {
TemplateWithExtraArg<char> twaa2;
twaa2 = twaa;
}
// OK: no user-defined copy constructor or assignment.
struct R1_A {
R1_A() { }
// Note: user-declared move constructor means copy constructor and
// assignment are both implicitly deleted.
R1_A(R1_A&& a) { }
};
// OK: copy assignment implicitly deleted due to R1_A field.
class R1_B {
public:
R1_B(const R1_B& b) {}
R1_A t;
};
// NOT OK: copy constructor user-defined and public, but copy assignment
// is generated by the compiler and callable outside the class.
class R1_C {
public:
R1_C(const R1_C& c) {}
};

View File

@@ -0,0 +1,6 @@
| RuleOfTwo.cpp:4:3:4:17 | CopyButNoAssign | No matching copy assignment operator in class CopyButNoAssign. It is good practice to match a copy constructor with a copy assignment operator. |
| RuleOfTwo.cpp:10:20:10:28 | operator= | No matching copy constructor in class AssignButNoCopy. It is good practice to match a copy assignment operator with a copy constructor. |
| RuleOfTwo.cpp:81:18:81:26 | operator= | No matching copy constructor in class MyClassFriend. It is good practice to match a copy assignment operator with a copy constructor. |
| RuleOfTwo.cpp:144:3:144:20 | IsAProtectedAssign | No matching copy assignment operator in class IsAProtectedAssign. It is good practice to match a copy constructor with a copy assignment operator. |
| RuleOfTwo.cpp:167:19:167:27 | operator= | No matching copy constructor in class IsAProtectedCC. It is good practice to match a copy assignment operator with a copy constructor. |
| RuleOfTwo.cpp:312:5:312:8 | R1_C | No matching copy assignment operator in class R1_C. It is good practice to match a copy constructor with a copy assignment operator. |

View File

@@ -0,0 +1 @@
Best Practices/RuleOfTwo.ql

View File

@@ -0,0 +1,2 @@
| main.cpp:3:5:3:5 | x | Poor global variable name 'x'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo). |
| main.cpp:4:5:4:6 | ys | Poor global variable name 'ys'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo). |

View File

@@ -0,0 +1 @@
Best Practices/SloppyGlobal.ql

View File

@@ -0,0 +1,7 @@
// main.cpp
int x; // BAD: too short
int ys[1000000]; // BAD: too short
int descriptive_name; // GOOD: sufficient
static int z; // GOOD: not a global

View File

@@ -0,0 +1,3 @@
// a.h
int my_func_a();

View File

@@ -0,0 +1,3 @@
// b.h
int my_func_b();

View File

@@ -0,0 +1,3 @@
// c.h
extern int my_var_c;

View File

@@ -0,0 +1,3 @@
// d.hpp
class class_d;

View File

@@ -0,0 +1,3 @@
// e.hpp
class class_e;

View File

@@ -0,0 +1,3 @@
// f.fwd.hpp
class class_f;

View File

@@ -0,0 +1,13 @@
// unusedIncludes.cpp
#include "a.h" // unused
#include "b.h"
#include "c.h"
#include "d.hpp"
#include "e.hpp" // unused
#include "f.fwd.hpp" // unused
#include "g" // unused
int val_b = my_func_b();
int *my_c_ptr = &my_var_c;
class_d *my_d_ptr;

View File

@@ -0,0 +1,4 @@
| unusedIncludes.cpp:3:1:3:14 | #include "a.h" | Redundant include, this file does not require $@. | a.h:0:0:0:0 | a.h | a.h |
| unusedIncludes.cpp:7:1:7:16 | #include "e.hpp" | Redundant include, this file does not require $@. | e.hpp:0:0:0:0 | e.hpp | e.hpp |
| unusedIncludes.cpp:8:1:8:20 | #include "f.fwd.hpp" | Redundant include, this file does not require $@. | f.fwd.hpp:0:0:0:0 | f.fwd.hpp | f.fwd.hpp |
| unusedIncludes.cpp:9:1:9:12 | #include "g" | Redundant include, this file does not require $@. | g:0:0:0:0 | g | g |

View File

@@ -0,0 +1 @@
Best Practices/Unused Entities/UnusedIncludes.ql

View File

@@ -0,0 +1,24 @@
| code2.cpp:4:6:4:7 | v1 | Variable v1 is not used |
| code2.cpp:6:6:6:7 | v3 | Variable v3 is not used |
| code2.cpp:10:16:10:17 | v7 | Variable v7 is not used |
| code2.cpp:25:16:25:17 | v1 | Variable v1 is not used |
| code2.cpp:26:16:26:17 | v2 | Variable v2 is not used |
| code2.cpp:41:11:41:16 | myVar1 | Variable myVar1 is not used |
| code2.cpp:63:7:63:8 | v3 | Variable v3 is not used |
| code.c:10:18:10:18 | y | Variable y is not used |
| code.c:11:18:11:18 | z | Variable z is not used |
| code.c:18:7:18:7 | x | Variable x is not used |
| code.c:19:10:19:10 | y | Variable y is not used |
| code.c:30:45:30:45 | n | Variable n is not used |
| code.c:46:6:46:6 | x | Variable x is not used |
| code.c:52:8:52:8 | x | Variable x is not used |
| code.c:67:6:67:9 | arr5 | Variable arr5 is not used |
| code.cpp:17:18:17:18 | e | Variable e is not used |
| code.cpp:32:11:32:16 | mc_ptr | Variable mc_ptr is not used |
| code.cpp:33:11:33:16 | mc_ref | Variable mc_ref is not used |
| code.cpp:104:16:104:24 | my_static | Variable my_static is not used |
| code.cpp:104:16:104:24 | my_static | Variable my_static is not used |
| code.cpp:104:16:104:24 | my_static | Variable my_static is not used |
| code.cpp:132:17:132:25 | my_static | Variable my_static is not used |
| code.cpp:248:16:248:18 | mmc | Variable mmc is not used |
| errors.c:10:9:10:9 | x | Variable x is not used |

View File

@@ -0,0 +1 @@
Best Practices/Unused Entities/UnusedLocals.ql

View File

@@ -0,0 +1,75 @@
void f1(unsigned int x) {
unsigned int y = x + 1;
unsigned int z = x + 2; // BAD: 'z' is unused [NOT DETECTED - due to ASM code]
asm volatile("decl %[cnt];" : [cnt] "+r" (y));
}
void f2(unsigned int x) {
unsigned int y = x + 1; // BAD: 'y' is unused
unsigned int z = x + 2; // BAD: 'z' is unused
}
#define my_int int
#define COMPLEX_MACRO do { int z = 3; } while(0)
void f3() {
int x = 1; // BAD: 'x' is unused
my_int y = 2; // BAD: 'y' is unused
COMPLEX_MACRO; // GOOD: unused locals declared in macros are considered OK.
}
void write_ptr(int *ptr) {
ptr = 1;
}
#define ZERO(x) x = 0
int f4() {
int a, b, c, d, e, f, g, h, i, j, k, l, m, n; // BAD: 'n' is unused
a = b;
c++;
if (d) {
int *ptr = &e;
ptr = &f;
}
write_ptr(&g);
h = (i) ? (j) : (k);
ZERO(l);
return m;
}
void f5() {
int x; // BAD: 'x' is unused
{
int x;
{
int x; // BAD: 'x' is unused
}
x = 12;
}
}
typedef unsigned int size_t;
void *memset(void *ptr, int value, size_t num);
void f6() {
int arr1[10];
int arr2[10];
int arr3[10];
int arr4[10];
int arr5[10]; // BAD: 'arr5' is unused
int *ptr;
int x;
x = 6;
arr1[5] = arr2[x];
ptr = arr3;
memset(arr4, 0, sizeof(arr4));
}

View File

@@ -0,0 +1,252 @@
void write_ref(int &ref) {
ref = 1;
}
class MyClass {
public:
MyClass();
~MyClass();
private:
int val;
};
MyClass :: MyClass()
{
int a, b, c, d, e; // BAD: 'e' is unused
int &f = d;
write_ref(a);
val = b + f;
throw c;
}
MyClass :: ~MyClass()
{
}
void test()
{
MyClass mc; // GOOD: constructor and destructor may have side-effects
MyClass *mc_ptr; // BAD: 'mc_ptr' is unused
MyClass &mc_ref = mc; // BAD: 'mc_ref' is unused
}
// ---
template<class T> class container {
public:
T t;
};
// static int variable in non-instantiated template function
template<typename T> void *templateFunction()
{
static int my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// static template parameter variable in non-instantiated template function
template<typename T> void *templateFunction2()
{
static T my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// static template derived variable in non-instantiated template function
template<typename T> void *templateFunction3()
{
static container<T *> *my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// static unused int variable in non-instantiated template function
template<typename T> void *templateFunction4()
{
static int my_static; // BAD
static void* my_ptr = 0;
return my_ptr;
}
// static int variable in twice instantiated template function
template<typename T> void *instantiatedTemplateFunction()
{
static int my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// static template parameter variable in twice instantiated template function
template<typename T> void *instantiatedTemplateFunction2()
{
static T my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// static template derived variable in twice instantiated template function
template<typename T> void *instantiatedTemplateFunction3()
{
static container<T *> *my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// static unused int variable in twice instantiated template function
template<typename T> void *instantiatedTemplateFunction4()
{
static int my_static; // BAD
static void* my_ptr = 0;
return my_ptr;
}
void caller()
{
instantiatedTemplateFunction<int>();
instantiatedTemplateFunction<float>();
instantiatedTemplateFunction2<int>();
instantiatedTemplateFunction2<float>();
instantiatedTemplateFunction3<int>();
instantiatedTemplateFunction3<float>();
instantiatedTemplateFunction4<int>();
instantiatedTemplateFunction4<float>();
}
// This is a non-template version of the above.
void *nonTemplateFunction()
{
static int *my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// This is a non-template version of the above.
void *nonTemplateFunction2()
{
static int *my_static; // BAD
static void* my_ptr = 0;
return my_ptr;
}
// non-static int variable in non-instantiated template function
template<typename T> void *templateFunction5()
{
int my_local; // GOOD
void* my_ptr = &my_local;
return my_ptr;
}
// non-static template parameter variable in non-instantiated template function
template<typename T> void *templateFunction6()
{
T my_local; // GOOD
void* my_ptr = &my_local;
return my_ptr;
}
// non-static template derived variable in non-instantiated template function
template<typename T> void *templateFunction7()
{
container<T *> *my_local; // GOOD
void* my_ptr = &my_local;
return my_ptr;
}
// non-static unused int variable in non-instantiated template function
template<typename T> void *templateFunction8()
{
int my_local; // BAD
void* my_ptr = 0;
return my_ptr;
}
template<typename T> class templateClass
{
public:
// static int variable in class template method
void *templateClassMethod()
{
static int my_static; // GOOD
void* my_ptr = &my_static;
return my_ptr;
}
// static template parameter variable in class template method
void *templateClassMethod2()
{
static T my_static; // GOOD
void* my_ptr = &my_static;
return my_ptr;
}
// static template derived variable in class template method
void *templateClassMethod3()
{
static container<T *> *my_static; // GOOD
void* my_ptr = &my_static;
return my_ptr;
}
// static unused int variable in class template method
void *templateClassMethod4()
{
static int my_static; // BAD
void* my_ptr = 0;
return my_ptr;
}
};
templateClass<int> tc_i;
template<typename T> class MyTemplateClass2
{
public:
void method()
{
static T *a; // BAD
static T b; // GOOD - T could have a constructor / destructor
static container<T> *c; // BAD
static container<T *> d; // BAD [NOT DETECTED - due to type container<T *> depending on type container<T>, which *could* have a constructor, though as used here it can't]
static container<T> e; // GOOD - T could have a constructor / destructor
}
};
// ---
int myGlobal;
class MyMethodClass
{
public:
void MyMethod() {myGlobal++;} // side-effect
};
class MyConstructorClass
{
public:
MyConstructorClass() {myGlobal++;} // side-effect
};
class MyDerivedClass : public MyConstructorClass
{
};
class MyContainingClass
{
private:
MyConstructorClass mcc;
};
void testFunction()
{
MyMethodClass mmc; // BAD: unused
MyConstructorClass mcc; // GOOD
MyDerivedClass mdc; // GOOD
MyContainingClass mcc2; // GOOD
}

View File

@@ -0,0 +1,78 @@
int test_const_init()
{
int v1; // BAD: unused
int v2; // GOOD
int v3 = 0; // BAD: unused
int v4 = 0; // GOOD
const int v5 = 0; // BAD: unused [NOT DETECTED]
const int v6 = 0; // GOOD
constexpr int v7 = 0; // BAD: unused
constexpr int v8 = 0; // GOOD
return v2 + v4 + v6 + v8;
}
// ---
template<int i>
void myFunction()
{
}
void test_template_parameter()
{
constexpr int v1 = 0; // BAD: unused
constexpr int v2 = 0; // GOOD: used as a template parameter below [FALSE POSITIVE]
myFunction<v2>();
}
// ---
class MyBuffer
{
public:
unsigned char buffer[40];
};
void test_unused()
{
MyBuffer myVar1; // BAD: unused
MyBuffer myVar2; // GOOD: used in deliberate void cast below
MyBuffer myVar3 __attribute((__unused__)); // GOOD: unused but acknowledged
(void)myVar2;
}
// ---
#define likely(x) __builtin_expect ((x), 1)
#define unlikely(x) __builtin_expect ((x), 0)
static int getter() {}
void test_expect()
{
int i;
for (i = 0; i < 100000; i++)
{
int v1 = getter(); // GOOD: v1 is used
int v2 = getter(); // GOOD: v2 is used
int v3 = getter(); // BAD: unused
if (unlikely(v1 < 0))
{
int a = i;
int b = a;
a += b;
b = -1;
break;
}
if (__builtin_expect(v2, 0))
{
break;
}
}
}

View File

@@ -0,0 +1,14 @@
// semmle-extractor-options: --expect_errors
void f_error(void) {
int x, z;
// There is an error in here, so we don't see the use of x. But we
// still don't want to report it as unused.
z = y + x;
}
void g_error(void) {
int x, y, z;
// This one should be reported despite the error in another function.
z = y + y;
}

View File

@@ -0,0 +1,6 @@
| unused_static_functions.cpp:19:13:19:14 | f2 | Static function f2 is unreachable | unused_static_functions.cpp:19:13:19:14 | f2 | f2 |
| unused_static_functions.cpp:33:13:33:14 | f5 | Static function f5 is unreachable ($@ must be removed at the same time) | unused_static_functions.cpp:34:13:34:14 | f6 | f6 |
| unused_static_functions.cpp:34:13:34:14 | f6 | Static function f6 is unreachable ($@ must be removed at the same time) | unused_static_functions.cpp:33:13:33:14 | f5 | f5 |
| used_by_var_ref.c:8:13:8:13 | g | Static function g is unreachable ($@ must be removed at the same time) | used_by_var_ref.c:13:16:13:17 | n2 | n2 |
| used_by_var_ref.c:10:13:10:13 | i | Static function i is unreachable ($@ must be removed at the same time) | used_by_var_ref.c:20:13:20:13 | k | k |
| used_by_var_ref.c:20:13:20:13 | k | Static function k is unreachable | used_by_var_ref.c:20:13:20:13 | k | k |

View File

@@ -0,0 +1 @@
Best Practices/Unused Entities/UnusedStaticFunctions.ql

View File

@@ -0,0 +1,35 @@
// f1 is reachable via fs
static void f1(void) { }
struct funstr {
void (*someFun)(void);
};
class myClass {
public:
static const funstr fs[];
};
const funstr myClass::fs[] = {
{ f1 },
};
// f2 is unreachable
static void f2(void) { }
// f3 is reachable via f4/pf3
static void f3(void) { }
// f4 is reachable due to not being static
void f4(void) {
static void (*pf3)(void);
pf3 = f3;
}
// f5 and f6 are mutually recursive unreachable static functions
static void f6(void);
static void f5(void) { f6(); }
static void f6(void) { f5(); }

View File

@@ -0,0 +1,24 @@
typedef struct _num_fun {
int num;
void (*fun)(void);
} num_fun;
static void f(void) {} // Used, via n1
static void g(void) {} // Not used (n2 is static)
static void h(void) {} // Used, via n3, via j
static void i(void) {} // Not used (k is static)
num_fun n1 = {1, f};
static num_fun n2 = {1, g};
static num_fun n3 = {1, h};
void j(void) { // Used (not static)
num_fun n = n3;
}
static void k(void) { // Not used (static)
num_fun n = {1, i};
n1.fun = i;
}

View File

@@ -0,0 +1 @@
| test.cpp:5:13:5:18 | unused | Dead Code: this function is never called. |

View File

@@ -0,0 +1 @@
Critical/DeadCodeFunction.ql

View File

@@ -0,0 +1,32 @@
static void usedByUnused() {
}
static void unused() {
usedByUnused();
}
class Base {
virtual void f() { }
public:
Base() { }
void process() {
f();
}
};
class Derived : public Base {
virtual void f() { }
public:
Derived() { }
};
void caller() {
Base b;
Derived d;
b.process();
d.process();
}

View File

@@ -0,0 +1,3 @@
| file.c:8:15:8:19 | call to fopen | The file opened here may not be closed at $@. | file.c:12:13:12:19 | return ... | this exit point |
| file.c:18:15:18:19 | call to fopen | The file opened here may not be closed at $@. | file.c:22:13:22:24 | return ... | this exit point |
| file.c:66:5:66:34 | ... = ... | The file opened here may not be closed at $@. | file.c:74:5:74:13 | return ... | this exit point |

View File

@@ -0,0 +1 @@
Critical/FileMayNotBeClosed.ql

View File

@@ -0,0 +1 @@
| file.c:34:15:34:19 | call to fopen | The file is never closed |

View File

@@ -0,0 +1 @@
Critical/FileNeverClosed.ql

View File

@@ -0,0 +1,98 @@
typedef void FILE;
FILE *fopen(const char *path, const char *mode);
int fclose(FILE *fp);
#define NULL ((FILE *)0)
void f1(int i) {
FILE *f = fopen("somefile.txt", "r");
if (!f) return;
if (!i) return; // Not closed here
fclose(f);
}
FILE *f2(int i) {
FILE *f = fopen("somefile.txt", "r");
if (!f) return NULL;
if (!i) return NULL; // Not closed here
return f;
}
void g2(int i) {
FILE *f = f2(i);
fclose(f); // This makes the final return in f2 count as closed
}
void f3(int i) {
FILE *f = fopen("somefile.txt", "r"); // Never closed
if (!f) return;
if (!i) return;
}
void f4(void) {
FILE *f = fopen("somefile.txt", "r"); // Always closed
if (!f) return;
fclose(f);
}
FILE *f5(void) {
FILE *f = fopen("somefile.txt", "r"); // Always closed, by g5
if (!f) return NULL;
return f;
}
void g5(void) {
FILE *f = f5();
fclose(f);
}
int f6(int b) {
FILE *f;
f = fopen("somefile.txt", "r"); // Not always closed
if (f) {
if (b) {
fclose(f);
}
}
return 0;
}
int f7(void) {
FILE *f;
f = fopen("somefile.txt", "r"); // Always closed
if (f) {
fclose(f);
}
return 0;
}
int f8(void) {
FILE *f;
if (f = fopen("somefile.txt", "r")) { // Always closed
fclose(f);
}
return 0;
}

View File

@@ -0,0 +1,3 @@
| test.cpp:16:13:16:14 | _t | This parameter of type $@ is 4096 bytes - consider passing a pointer/reference instead. | test.cpp:6:8:6:20 | myLargeStruct | myLargeStruct |
| test.cpp:24:44:24:48 | mtc_t | This parameter of type $@ is 4096 bytes - consider passing a pointer/reference instead. | test.cpp:11:7:11:21 | myTemplateClass<myLargeStruct> | myTemplateClass<myLargeStruct> |
| test.cpp:28:49:28:49 | b | This parameter of type $@ is 4096 bytes - consider passing a pointer/reference instead. | test.cpp:6:8:6:20 | myLargeStruct | myLargeStruct |

View File

@@ -0,0 +1 @@
Critical/LargeParameter.ql

View File

@@ -0,0 +1,46 @@
struct mySmallStruct {
char data[4];
};
struct myLargeStruct {
char data[4096];
};
template <class T>
class myTemplateClass
{
public:
myTemplateClass() {}
void set(T _t) { // BAD: T can be myLargeStruct, which is large
t = _t;
}
T t;
};
template<class T>
void myTemplateFunction(myTemplateClass<T> mtc_t) // BAD: T can be myLargeStruct, which is large
{
}
void myFunction1(mySmallStruct a, myLargeStruct b) // BAD: b is large
{
myTemplateClass<mySmallStruct> mtc_a;
myTemplateClass<myLargeStruct> mtc_b;
mtc_a.set(a);
mtc_b.set(b);
myTemplateFunction(mtc_a);
myTemplateFunction(mtc_b);
}
void myFunction2(mySmallStruct *a, myLargeStruct *b) // GOOD
{
}
void myFunction3(mySmallStruct &a, myLargeStruct &b) // GOOD
{
}

View File

@@ -0,0 +1,31 @@
| my_auto_ptr.cpp:20:26:20:28 | ptr |
| my_auto_ptr.cpp:20:26:20:28 | ptr |
| my_auto_ptr.cpp:20:26:20:28 | ptr |
| my_auto_ptr.cpp:20:26:20:28 | ptr |
| my_auto_ptr.cpp:20:26:20:28 | ptr |
| my_auto_ptr.cpp:20:26:20:28 | ptr |
| my_auto_ptr.cpp:20:26:20:28 | ptr |
| my_auto_ptr.cpp:26:12:26:14 | ptr |
| my_auto_ptr.cpp:26:12:26:14 | ptr |
| test.cpp:28:7:28:12 | array1 |
| test.cpp:33:7:33:12 | array2 |
| test.cpp:34:7:34:12 | array7 |
| test.cpp:44:7:44:12 | array3 |
| test.cpp:45:7:45:12 | array5 |
| test.cpp:50:7:50:12 | array6 |
| test.cpp:75:7:75:12 | array1 |
| test.cpp:80:7:80:12 | array2 |
| test.cpp:81:7:81:12 | array7 |
| test.cpp:91:7:91:12 | array3 |
| test.cpp:92:7:92:12 | array5 |
| test.cpp:97:7:97:12 | array6 |
| test.cpp:115:10:115:12 | mc2 |
| test.cpp:125:8:125:9 | v1 |
| test.cpp:126:8:126:9 | i2 |
| test.cpp:127:8:127:9 | i3 |
| test.cpp:128:15:128:16 | v4 |
| virtual.cpp:18:10:18:10 | a |
| virtual.cpp:19:10:19:10 | c |
| virtual.cpp:38:10:38:10 | b |
| virtual.cpp:39:10:39:10 | d |
| virtual.cpp:46:9:46:9 | c |

Some files were not shown because too many files have changed in this diff Show More