mirror of
https://github.com/github/codeql.git
synced 2025-12-17 09:13:20 +01:00
448 lines
6.2 KiB
C++
448 lines
6.2 KiB
C++
// semmle-extractor-options: --microsoft --edg --target --edg linux_x86_64
|
|
typedef unsigned __int64 size_t;
|
|
void *malloc(size_t size);
|
|
void free(void *ptr);
|
|
|
|
// placement new
|
|
void* operator new(size_t _Size, void *_Where)
|
|
{
|
|
// ...
|
|
}
|
|
|
|
// ---
|
|
|
|
class myClass
|
|
{
|
|
public:
|
|
int x, y;
|
|
};
|
|
|
|
myClass *global_p1, *global_p2;
|
|
|
|
void f1()
|
|
{
|
|
myClass *p1, *p2;
|
|
|
|
p1 = new myClass;
|
|
p2 = (myClass *)malloc(sizeof(myClass));
|
|
|
|
global_p1 = p1;
|
|
global_p2 = p2;
|
|
}
|
|
|
|
void f2()
|
|
{
|
|
delete global_p1; // GOOD
|
|
delete global_p2; // BAD: malloc -> delete
|
|
}
|
|
|
|
void f3()
|
|
{
|
|
free(global_p1); // BAD: new -> delete
|
|
free(global_p2); // GOOD
|
|
}
|
|
|
|
void *my_malloc(size_t size)
|
|
{
|
|
return malloc(size);
|
|
}
|
|
|
|
template<class T> void my_delete(T *t)
|
|
{
|
|
if (t != 0)
|
|
{
|
|
delete t;
|
|
}
|
|
}
|
|
|
|
int main()
|
|
{
|
|
// straightforward cases
|
|
{
|
|
myClass *p1 = new myClass;
|
|
myClass *p2 = new myClass[10];
|
|
myClass *p3 = (myClass *)malloc(sizeof(myClass));
|
|
|
|
delete p1; // GOOD
|
|
delete [] p2; // GOOD
|
|
delete p3; // BAD: malloc -> delete
|
|
}
|
|
{
|
|
myClass *p1 = new myClass;
|
|
myClass *p2 = new myClass[10];
|
|
myClass *p3 = (myClass *)malloc(sizeof(myClass));
|
|
|
|
free(p1); // BAD: new -> free
|
|
free(p2); // BAD: new[] -> free
|
|
free(p3); // GOOD
|
|
}
|
|
|
|
// more complex flow
|
|
f1();
|
|
f2();
|
|
f1();
|
|
f3();
|
|
|
|
// wrapped malloc / delete
|
|
{
|
|
myClass *p1 = (myClass *)my_malloc(sizeof(myClass));
|
|
myClass *p2 = (myClass *)my_malloc(sizeof(myClass));
|
|
|
|
delete p1; // BAD: malloc -> delete
|
|
free(p2); // GOOD
|
|
}
|
|
{
|
|
myClass *p1 = new myClass;
|
|
myClass *p2 = (myClass *)malloc(sizeof(myClass));
|
|
|
|
my_delete(p1); // GOOD
|
|
my_delete(p2); // BAD: malloc -> delete
|
|
}
|
|
|
|
// overwritten
|
|
{
|
|
myClass *p1 = new myClass;
|
|
|
|
delete p1; // GOOD
|
|
p1 = (myClass *)malloc(sizeof(myClass));
|
|
|
|
free(p1); // GOOD
|
|
}
|
|
|
|
// placement new
|
|
{
|
|
void *v1 = malloc(sizeof(myClass));
|
|
// ... check alignment of v1 ...
|
|
myClass *p1 = new (v1) myClass();
|
|
|
|
p1->~myClass();
|
|
free(p1); // GOOD
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void *my_malloc_2(size_t size)
|
|
{
|
|
void *alloc = malloc(size);
|
|
|
|
return alloc;
|
|
}
|
|
|
|
void test2()
|
|
{
|
|
void *a = my_malloc_2(10);
|
|
void *b = my_malloc_2(10);
|
|
|
|
free(a); // GOOD
|
|
delete b; // BAD: malloc -> delete
|
|
}
|
|
|
|
void *my_malloc_3(size_t size)
|
|
{
|
|
void *alloc = malloc(size);
|
|
void *mid = alloc;
|
|
|
|
return mid;
|
|
}
|
|
|
|
void test3()
|
|
{
|
|
void *a = my_malloc_3(10);
|
|
void *b = my_malloc_3(10);
|
|
|
|
free(a); // GOOD
|
|
delete b; // BAD: malloc -> delete
|
|
}
|
|
|
|
void test4(bool do_array_delete)
|
|
{
|
|
myClass *mc = new myClass;
|
|
myClass *mc_array = new myClass[1024];
|
|
|
|
if (do_array_delete)
|
|
{
|
|
delete [] mc; // BAD
|
|
delete [] mc_array; // GOOD
|
|
} else {
|
|
delete mc; // GOOD
|
|
delete mc_array; // BAD
|
|
}
|
|
}
|
|
|
|
void test5(bool do_array_delete)
|
|
{
|
|
char *c_array = new char[32];
|
|
char *c_array_ptr_2 = c_array;
|
|
|
|
if (do_array_delete)
|
|
{
|
|
delete [] c_array_ptr_2; // GOOD
|
|
} else {
|
|
delete c_array_ptr_2; // BAD
|
|
}
|
|
}
|
|
|
|
void test6(bool do_array_delete)
|
|
{
|
|
char *c_ptr_array[10] = {0};
|
|
c_ptr_array[5] = new char;
|
|
|
|
if (do_array_delete)
|
|
{
|
|
delete [] c_ptr_array[5]; // BAD [NOT DETECTED]
|
|
} else {
|
|
delete c_ptr_array[5]; // GOOD
|
|
}
|
|
}
|
|
|
|
myClass *global_mc = 0;
|
|
|
|
void test7(bool do_array_delete)
|
|
{
|
|
// alloc
|
|
if (global_mc == 0)
|
|
{
|
|
global_mc = new myClass;
|
|
}
|
|
|
|
// free
|
|
if (global_mc != 0)
|
|
{
|
|
if (do_array_delete)
|
|
{
|
|
delete [] global_mc; // BAD
|
|
} else {
|
|
delete global_mc; // GOOD
|
|
}
|
|
}
|
|
}
|
|
|
|
void test8(bool cond)
|
|
{
|
|
void *a = 0, *b = 0, *c = 0;
|
|
|
|
if (cond) {
|
|
a = malloc(64);
|
|
b = new int;
|
|
c = new int[10];
|
|
}
|
|
|
|
free(a); // GOOD
|
|
delete a; // BAD: malloc -> delete
|
|
delete [] a; // BAD: malloc -> delete[]
|
|
|
|
free(b); // BAD: new -> free
|
|
delete b; // GOOD
|
|
delete [] b; // BAD: new -> delete[]
|
|
|
|
free(c); // BAD: new[] -> free
|
|
delete c; // BAD: new[] -> delete
|
|
delete [] c; // GOOD
|
|
}
|
|
|
|
void test9()
|
|
{
|
|
void *ptr;
|
|
|
|
ptr = new int;
|
|
delete ptr; // GOOD
|
|
|
|
ptr = new int[10];
|
|
delete [] ptr; // GOOD
|
|
|
|
ptr = malloc(sizeof(int));
|
|
free(ptr); // GOOD
|
|
}
|
|
|
|
class ClassWithMembers
|
|
{
|
|
public:
|
|
ClassWithMembers()
|
|
{
|
|
a = new int;
|
|
b = new int;
|
|
c = new int;
|
|
}
|
|
|
|
~ClassWithMembers()
|
|
{
|
|
delete a; // GOOD
|
|
delete [] b; // BAD: new -> delete[]
|
|
free(c); // BAD: new -> free
|
|
}
|
|
|
|
private:
|
|
int *a, *b, *c;
|
|
};
|
|
|
|
// ---
|
|
|
|
struct map_cell
|
|
{
|
|
char ch;
|
|
int col;
|
|
};
|
|
map_cell *map;
|
|
|
|
static void map_init()
|
|
{
|
|
map = new map_cell[30 * 30];
|
|
}
|
|
|
|
static void map_shutdown()
|
|
{
|
|
delete map; // BAD: new[] -> delete
|
|
map = 0;
|
|
}
|
|
|
|
// ---
|
|
|
|
class Test10
|
|
{
|
|
public:
|
|
Test10() : data(new char[10])
|
|
{
|
|
}
|
|
|
|
~Test10()
|
|
{
|
|
delete data; // BAD: new[] -> delete
|
|
}
|
|
|
|
char *data;
|
|
};
|
|
|
|
class Test11
|
|
{
|
|
public:
|
|
Test11()
|
|
{
|
|
data = new char[10];
|
|
}
|
|
|
|
void resize(int size)
|
|
{
|
|
if (size > 0)
|
|
{
|
|
delete [] data; // GOOD
|
|
data = new char[size];
|
|
}
|
|
}
|
|
|
|
~Test11()
|
|
{
|
|
delete data; // BAD: new[] -> delete
|
|
}
|
|
|
|
char *data;
|
|
};
|
|
|
|
// ---
|
|
|
|
int *z;
|
|
|
|
void test12(bool cond)
|
|
{
|
|
int *x, *y;
|
|
|
|
x = new int();
|
|
delete x; // GOOD
|
|
x = (int *)malloc(sizeof(int));
|
|
free(x); // GOOD
|
|
|
|
if (cond)
|
|
{
|
|
y = new int();
|
|
z = new int();
|
|
} else {
|
|
y = (int *)malloc(sizeof(int));
|
|
z = (int *)malloc(sizeof(int));
|
|
}
|
|
|
|
// ...
|
|
|
|
if (cond)
|
|
{
|
|
delete y; // GOOD
|
|
delete z; // GOOD
|
|
} else {
|
|
free(y); // GOOD
|
|
free(z); // GOOD
|
|
}
|
|
}
|
|
|
|
// ---
|
|
|
|
class MyBuffer13
|
|
{
|
|
public:
|
|
MyBuffer13(int size)
|
|
{
|
|
buffer = (char *)malloc(size * sizeof(char));
|
|
}
|
|
|
|
~MyBuffer13()
|
|
{
|
|
free(buffer); // GOOD
|
|
}
|
|
|
|
char *getBuffer() // note: this should not be considered an allocation function
|
|
{
|
|
return buffer;
|
|
}
|
|
|
|
private:
|
|
char *buffer;
|
|
};
|
|
|
|
class MyPointer13
|
|
{
|
|
public:
|
|
MyPointer13(char *_pointer) : pointer(_pointer)
|
|
{
|
|
}
|
|
|
|
MyPointer13(MyBuffer13 &buffer) : pointer(buffer.getBuffer())
|
|
{
|
|
}
|
|
|
|
char *getPointer() // note: this should not be considered an allocation function
|
|
{
|
|
return pointer;
|
|
}
|
|
|
|
private:
|
|
char *pointer;
|
|
};
|
|
|
|
void test13()
|
|
{
|
|
MyBuffer13 myBuffer(100);
|
|
MyPointer13 myPointer2(myBuffer);
|
|
MyPointer13 myPointer3(new char[100]);
|
|
|
|
delete myPointer3.getPointer(); // GOOD
|
|
}
|
|
|
|
char *strdup(const char *s1);
|
|
char *strndup(const char *s1, size_t n);
|
|
wchar_t* wcsdup(const wchar_t* s1);
|
|
|
|
void test14()
|
|
{
|
|
char *s1 = strdup("string");
|
|
char *s2 = strdup("string");
|
|
char *s3 = strndup("string", 3);
|
|
char *s4 = strndup("string", 3);
|
|
wchar_t *s5 = wcsdup(L"string");
|
|
wchar_t *s6 = wcsdup(L"string");
|
|
|
|
delete s1; // BAD: strdup -> delete
|
|
free(s2); // GOOD
|
|
delete s3; // BAD: strndup -> delete
|
|
free(s4); // GOOD
|
|
delete s5; // BAD: wcsdup -> delete
|
|
free(s6); // GOOD
|
|
}
|