mirror of
https://github.com/github/codeql.git
synced 2026-03-04 06:36:46 +01:00
298 lines
4.2 KiB
C++
298 lines
4.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;
|
|
}
|