mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
C++: Add a new query 'cpp/type-confusion' for detecting type confusion vulnerabilities.
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
edges
|
||||
| test.cpp:27:13:27:18 | new | test.cpp:28:25:28:55 | p | provenance | |
|
||||
| test.cpp:32:13:32:30 | new | test.cpp:33:12:33:30 | p | provenance | |
|
||||
| test.cpp:66:15:66:21 | new | test.cpp:67:12:67:31 | a | provenance | |
|
||||
| test.cpp:85:9:85:15 | new | test.cpp:88:14:88:33 | a | provenance | |
|
||||
| test.cpp:127:12:127:17 | new | test.cpp:128:24:128:59 | s2 | provenance | |
|
||||
| test.cpp:143:14:143:19 | new | test.cpp:145:28:145:68 | s1_2 | provenance | |
|
||||
nodes
|
||||
| test.cpp:27:13:27:18 | new | semmle.label | new |
|
||||
| test.cpp:28:25:28:55 | p | semmle.label | p |
|
||||
| test.cpp:32:13:32:30 | new | semmle.label | new |
|
||||
| test.cpp:33:12:33:30 | p | semmle.label | p |
|
||||
| test.cpp:66:15:66:21 | new | semmle.label | new |
|
||||
| test.cpp:67:12:67:31 | a | semmle.label | a |
|
||||
| test.cpp:85:9:85:15 | new | semmle.label | new |
|
||||
| test.cpp:88:14:88:33 | a | semmle.label | a |
|
||||
| test.cpp:127:12:127:17 | new | semmle.label | new |
|
||||
| test.cpp:128:24:128:59 | s2 | semmle.label | s2 |
|
||||
| test.cpp:143:14:143:19 | new | semmle.label | new |
|
||||
| test.cpp:145:28:145:68 | s1_2 | semmle.label | s1_2 |
|
||||
subpaths
|
||||
#select
|
||||
| test.cpp:28:25:28:55 | p | test.cpp:27:13:27:18 | new | test.cpp:28:25:28:55 | p | Conversion from $@ to $@ is invalid. | test.cpp:1:8:1:9 | S1 | S1 | test.cpp:11:8:11:21 | Not_S1_wrapper | Not_S1_wrapper |
|
||||
| test.cpp:33:12:33:30 | p | test.cpp:32:13:32:30 | new | test.cpp:33:12:33:30 | p | Conversion from $@ to $@ is invalid. | test.cpp:11:8:11:21 | Not_S1_wrapper | Not_S1_wrapper | test.cpp:1:8:1:9 | S1 | S1 |
|
||||
| test.cpp:67:12:67:31 | a | test.cpp:66:15:66:21 | new | test.cpp:67:12:67:31 | a | Conversion from $@ to $@ is invalid. | test.cpp:55:8:55:10 | Cat | Cat | test.cpp:60:8:60:10 | Dog | Dog |
|
||||
| test.cpp:128:24:128:59 | s2 | test.cpp:127:12:127:17 | new | test.cpp:128:24:128:59 | s2 | Conversion from $@ to $@ is invalid. | test.cpp:102:8:102:9 | S2 | S2 | test.cpp:119:8:119:20 | Not_S2_prefix | Not_S2_prefix |
|
||||
| test.cpp:145:28:145:68 | s1_2 | test.cpp:143:14:143:19 | new | test.cpp:145:28:145:68 | s1_2 | Conversion from $@ to $@ is invalid. | test.cpp:1:8:1:9 | S1 | S1 | test.cpp:131:8:131:23 | HasSomeBitFields | HasSomeBitFields |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-843/TypeConfusion.ql
|
||||
146
cpp/ql/test/query-tests/Security/CWE/CWE-843/test.cpp
Normal file
146
cpp/ql/test/query-tests/Security/CWE/CWE-843/test.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
struct S1 {
|
||||
int a;
|
||||
void* b;
|
||||
unsigned char c;
|
||||
};
|
||||
|
||||
struct S1_wrapper {
|
||||
S1 s1;
|
||||
};
|
||||
|
||||
struct Not_S1_wrapper {
|
||||
unsigned char x;
|
||||
S1 s1;
|
||||
};
|
||||
|
||||
void test1() {
|
||||
void* p = new S1;
|
||||
S1_wrapper* s1w = static_cast<S1_wrapper*>(p); // GOOD
|
||||
}
|
||||
|
||||
void test2() {
|
||||
void* p = new S1_wrapper;
|
||||
S1* s1 = static_cast<S1*>(p); // GOOD
|
||||
}
|
||||
|
||||
void test3() {
|
||||
void* p = new S1;
|
||||
Not_S1_wrapper* s1w = static_cast<Not_S1_wrapper*>(p); // BAD
|
||||
}
|
||||
|
||||
void test4() {
|
||||
void* p = new Not_S1_wrapper;
|
||||
S1* s1 = static_cast<S1*>(p); // BAD
|
||||
}
|
||||
|
||||
struct HasBitFields {
|
||||
int x : 16;
|
||||
int y : 16;
|
||||
int z : 32;
|
||||
};
|
||||
|
||||
struct BufferStruct {
|
||||
unsigned char buffer[sizeof(HasBitFields)];
|
||||
};
|
||||
|
||||
void test5() {
|
||||
HasBitFields* p = new HasBitFields;
|
||||
BufferStruct* bs = reinterpret_cast<BufferStruct*>(p); // GOOD
|
||||
}
|
||||
|
||||
struct Animal {
|
||||
virtual ~Animal();
|
||||
};
|
||||
|
||||
struct Cat : public Animal {
|
||||
Cat();
|
||||
~Cat();
|
||||
};
|
||||
|
||||
struct Dog : public Animal {
|
||||
Dog();
|
||||
~Dog();
|
||||
};
|
||||
|
||||
void test6() {
|
||||
Animal* a = new Cat;
|
||||
Dog* d = static_cast<Dog*>(a); // BAD
|
||||
}
|
||||
|
||||
void test7() {
|
||||
Animal* a = new Cat;
|
||||
Dog* d = dynamic_cast<Dog*>(a); // GOOD
|
||||
}
|
||||
|
||||
void test8() {
|
||||
Animal* a = new Cat;
|
||||
Cat* d = static_cast<Cat*>(a); // GOOD
|
||||
}
|
||||
|
||||
void test9(bool b) {
|
||||
Animal* a;
|
||||
if(b) {
|
||||
a = new Cat;
|
||||
} else {
|
||||
a = new Dog;
|
||||
}
|
||||
if(b) {
|
||||
Cat* d = static_cast<Cat*>(a); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The layout of S2 is:
|
||||
* 0: int
|
||||
* 8: void*
|
||||
* 16: unsigned char
|
||||
* 16 + pad: unsigned char
|
||||
* 32 + pad: int
|
||||
* 40 + pad: void*
|
||||
* 48 + pad: unsigned char
|
||||
*/
|
||||
struct S2 {
|
||||
S1 s1;
|
||||
unsigned char buffer[16];
|
||||
S1 s1_2;
|
||||
};
|
||||
|
||||
struct S2_prefix {
|
||||
int a;
|
||||
void* p;
|
||||
unsigned char c;
|
||||
};
|
||||
|
||||
void test10() {
|
||||
S2* s2 = new S2;
|
||||
S2_prefix* s2p = reinterpret_cast<S2_prefix*>(s2); // GOOD
|
||||
}
|
||||
|
||||
struct Not_S2_prefix {
|
||||
int a;
|
||||
void* p;
|
||||
void* p2;
|
||||
unsigned char c;
|
||||
};
|
||||
|
||||
void test11() {
|
||||
S2* s2 = new S2;
|
||||
Not_S2_prefix* s2p = reinterpret_cast<Not_S2_prefix*>(s2); // BAD
|
||||
}
|
||||
|
||||
struct HasSomeBitFields {
|
||||
int x : 16;
|
||||
int y;
|
||||
int z : 32;
|
||||
};
|
||||
|
||||
void test12() {
|
||||
// This has doesn't have any non-bitfield member, so we don't detect
|
||||
// the problem here since the query currently ignores bitfields.
|
||||
S1* s1 = new S1;
|
||||
HasBitFields* hbf = reinterpret_cast<HasBitFields*>(s1); // BAD [NOT DETECTED]
|
||||
|
||||
S1* s1_2 = new S1;
|
||||
// This one has a non-bitfield members. So we detect the problem
|
||||
HasSomeBitFields* hbf2 = reinterpret_cast<HasSomeBitFields*>(s1_2); // BAD
|
||||
}
|
||||
Reference in New Issue
Block a user