Files
codeql/cpp/ql/test/query-tests/Critical/NewFree/test.cpp
2020-12-14 13:50:11 +00:00

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
}