mirror of
https://github.com/github/codeql.git
synced 2026-05-02 20:25:13 +02:00
Updated query to look for Microsoft-specific '_alloca' and '_malloca' entry points. Added sundry positive and negative test cases.
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
| AllocaInLoop1.cpp:25:18:25:23 | call to __builtin_alloca | Stack allocation is inside a $@ and could lead to stack overflow. | AllocaInLoop1.cpp:16:2:33:2 | for(...;...;...) ... | for(...;...;...) ... |
|
||||
| AllocaInLoop1.cpp:49:19:49:24 | call to __builtin_alloca | Stack allocation is inside a $@ and could lead to stack overflow. | AllocaInLoop1.cpp:39:2:58:2 | for(...;...;...) ... | for(...;...;...) ... |
|
||||
| AllocaInLoop1.cpp:74:19:74:24 | call to __builtin_alloca | Stack allocation is inside a $@ and could lead to stack overflow. | AllocaInLoop1.cpp:65:3:82:3 | for(...;...;...) ... | for(...;...;...) ... |
|
||||
| AllocaInLoop1ms.cpp:22:18:22:24 | call to _alloca | Stack allocation is inside a $@ and could lead to stack overflow. | AllocaInLoop1ms.cpp:13:2:30:2 | for(...;...;...) ... | for(...;...;...) ... |
|
||||
| AllocaInLoop1ms.cpp:46:19:46:26 | call to _malloca | Stack allocation is inside a $@ and could lead to stack overflow. | AllocaInLoop1ms.cpp:36:2:57:2 | for(...;...;...) ... | for(...;...;...) ... |
|
||||
| AllocaInLoop1ms.cpp:73:19:73:25 | call to _alloca | Stack allocation is inside a $@ and could lead to stack overflow. | AllocaInLoop1ms.cpp:64:3:81:3 | for(...;...;...) ... | for(...;...;...) ... |
|
||||
| AllocaInLoop2.c:39:30:39:35 | call to __builtin_alloca | Stack allocation is inside a $@ and could lead to stack overflow. | AllocaInLoop2.c:29:5:48:19 | do (...) ... | do (...) ... |
|
||||
| AllocaInLoop3.cpp:38:23:38:28 | call to __builtin_alloca | Stack allocation is inside a $@ and could lead to stack overflow. | AllocaInLoop3.cpp:36:2:42:19 | do (...) ... | do (...) ... |
|
||||
@@ -0,0 +1 @@
|
||||
Likely Bugs/Memory Management/AllocaInLoop.ql
|
||||
@@ -0,0 +1,84 @@
|
||||
// semmle-extractor-options: --clang
|
||||
struct vtype {
|
||||
int i1, i2;
|
||||
};
|
||||
extern int w1, w2;
|
||||
|
||||
void *__builtin_alloca(int sz);
|
||||
#define alloca __builtin_alloca
|
||||
typedef unsigned long size_t;
|
||||
|
||||
int printf(const char *format, ...);
|
||||
void *memcpy(void *dst, const void *src, size_t len);
|
||||
|
||||
// case 1: alloca directly contained in an unbounded loop
|
||||
void foo(const struct vtype* vec, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
const vtype* v = vec + i;
|
||||
char *b1 = 0;
|
||||
if (b1 == nullptr) {
|
||||
if (w1 > w2) {
|
||||
// Allocate the buffer on heap
|
||||
b1 = new char[w1];
|
||||
} else {
|
||||
// Allocate the buffer on stack
|
||||
b1 = (char*) alloca(w1); // [FLAG]
|
||||
}
|
||||
}
|
||||
memcpy(b1, v, w1);
|
||||
printf("%s\n", b1);
|
||||
if (w1 > w2) {
|
||||
delete b1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// case 2: alloca contained in a do-while(0) that is in turn contained
|
||||
// in an unbounded loop
|
||||
void bar(const struct vtype* vec, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
const vtype* v = vec + i;
|
||||
char *b1 = 0;
|
||||
do {
|
||||
if (b1 == nullptr) {
|
||||
if (w1 > w2) {
|
||||
// Allocate the buffer on heap
|
||||
b1 = new char[w1];
|
||||
} else {
|
||||
// Allocate the buffer on stack
|
||||
b1 = (char*) alloca(w1); // [FLAG]
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
memcpy(b1, v, w1);
|
||||
printf("%s\n", b1);
|
||||
if (w1 > w2) {
|
||||
delete b1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// case 3: alloca contained in an unbounded loop that is in turn contained
|
||||
// in a do-while(0)
|
||||
void baz(const struct vtype* vec, int count) {
|
||||
do {
|
||||
for (int i = 0; i < count; i++) {
|
||||
const vtype* v = vec + i;
|
||||
char *b1 = 0;
|
||||
if (b1 == nullptr) {
|
||||
if (w1 > w2) {
|
||||
// Allocate the buffer on heap
|
||||
b1 = new char[w1];
|
||||
} else {
|
||||
// Allocate the buffer on stack
|
||||
b1 = (char*) alloca(w1); // [FLAG]
|
||||
}
|
||||
}
|
||||
memcpy(b1, v, w1);
|
||||
printf("%s\n", b1);
|
||||
if (w1 > w2) {
|
||||
delete b1;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
// semmle-extractor-options: --clang
|
||||
#include "malloc.h"
|
||||
struct vtype {
|
||||
int i1, i2;
|
||||
};
|
||||
extern int w1, w2;
|
||||
|
||||
int printf(const char *format, ...);
|
||||
void *memcpy(void *dst, const void *src, size_t len);
|
||||
|
||||
// case 1: _alloca directly contained in an unbounded loop
|
||||
void foo(const struct vtype* vec, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
const vtype* v = vec + i;
|
||||
char *b1 = 0;
|
||||
if (b1 == nullptr) {
|
||||
if (w1 > w2) {
|
||||
// Allocate the buffer on heap
|
||||
b1 = new char[w1];
|
||||
} else {
|
||||
// Allocate the buffer on stack
|
||||
b1 = (char*) _alloca(w1); // [FLAG]
|
||||
}
|
||||
}
|
||||
memcpy(b1, v, w1);
|
||||
printf("%s\n", b1);
|
||||
if (w1 > w2) {
|
||||
delete b1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// case 2: _malloca contained in a do-while(0) that is in turn contained
|
||||
// in an unbounded loop
|
||||
void bar(const struct vtype* vec, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
const vtype* v = vec + i;
|
||||
char *b1 = 0;
|
||||
do {
|
||||
if (b1 == nullptr) {
|
||||
if (w1 > w2) {
|
||||
// Allocate the buffer on heap
|
||||
b1 = new char[w1];
|
||||
} else {
|
||||
// Allocate the buffer on stack
|
||||
b1 = (char*) _malloca(w1); // [FLAG]
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
memcpy(b1, v, w1);
|
||||
printf("%s\n", b1);
|
||||
if (w1 > w2) {
|
||||
delete b1;
|
||||
} else {
|
||||
_freea(b1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// case 3: _alloca contained in an unbounded loop that is in turn contained
|
||||
// in a do-while(0)
|
||||
void baz(const struct vtype* vec, int count) {
|
||||
do {
|
||||
for (int i = 0; i < count; i++) {
|
||||
const vtype* v = vec + i;
|
||||
char *b1 = 0;
|
||||
if (b1 == nullptr) {
|
||||
if (w1 > w2) {
|
||||
// Allocate the buffer on heap
|
||||
b1 = new char[w1];
|
||||
} else {
|
||||
// Allocate the buffer on stack
|
||||
b1 = (char*) _alloca(w1); // [FLAG]
|
||||
}
|
||||
}
|
||||
memcpy(b1, v, w1);
|
||||
printf("%s\n", b1);
|
||||
if (w1 > w2) {
|
||||
delete b1;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
// semmle-extractor-options: --clang
|
||||
int printf(const char *restrict format, ...);
|
||||
int sprintf(char *restrict buf, const char *restrict format, ...);
|
||||
typedef unsigned long size_t;
|
||||
void *memcpy(void *restrict dst, const void *restrict src, size_t len);
|
||||
void *malloc(size_t sz);
|
||||
void free(void *ptr);
|
||||
|
||||
struct vtype { int i1, i2; };
|
||||
extern int w1, w2;
|
||||
|
||||
void *_builtin_alloca(int sz);
|
||||
#define alloca __builtin_alloca
|
||||
|
||||
// We forward-declare the Microsoft routines
|
||||
//_alloca and _malloca here. Since they do not
|
||||
// originate from the <malloc.h> header, they
|
||||
// should not be flagged by our queries
|
||||
void *_alloca(size_t sz);
|
||||
void *_malloca(size_t sz);
|
||||
void _freea(void *ptr);
|
||||
|
||||
#define NULL (void *)0
|
||||
|
||||
// case 1: alloca called within a provably infinite loop
|
||||
void foo(const struct vtype* vec, int count) {
|
||||
char iter;
|
||||
|
||||
do {
|
||||
const struct vtype* v = vec + 2;
|
||||
char *b1 = 0;
|
||||
iter = 0;
|
||||
if (b1 == NULL) {
|
||||
if (w1 > w2) {
|
||||
// Allocate the buffer on heap
|
||||
b1 = (char *)malloc(w1);
|
||||
} else {
|
||||
// Allocate the buffer on stack
|
||||
b1 = (char*) alloca(w1); // [FLAG]
|
||||
iter = 1;
|
||||
}
|
||||
}
|
||||
memcpy(b1, v, w1);
|
||||
printf("%s\n", b1);
|
||||
if (w1 > w2) {
|
||||
free(b1);
|
||||
}
|
||||
} while (iter);
|
||||
}
|
||||
|
||||
// case 2: alloca called within nested do-while(0) loops
|
||||
void bar(const struct vtype* vec, int count) {
|
||||
|
||||
do {
|
||||
const struct vtype* v = vec + 2;
|
||||
char *b1 = 0;
|
||||
do {
|
||||
if (b1 == NULL) {
|
||||
if (w1 > w2) {
|
||||
// Allocate the buffer on heap
|
||||
b1 = (char *)malloc(w1);
|
||||
} else {
|
||||
// Allocate the buffer on stack
|
||||
b1 = (char*) alloca(w1); // [DO NOT FLAG]
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
memcpy(b1, v, w1);
|
||||
printf("%s\n", b1);
|
||||
if (w1 > w2) {
|
||||
free(b1);
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
|
||||
// case 3: alloca called outside any loops
|
||||
void baz(int count) {
|
||||
|
||||
char *buf = (char *)alloca(32); // [DO NOT FLAG]
|
||||
sprintf(buf, "Value is %d\n", count);
|
||||
printf("%s", buf);
|
||||
}
|
||||
|
||||
////// Negative Microsoft test cases
|
||||
|
||||
// case 4: _alloca directly contained in an unbounded loop
|
||||
void foo_ms(const struct vtype* vec, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
const struct vtype* v = vec + i;
|
||||
char *b1 = 0;
|
||||
if (b1 == NULL) {
|
||||
if (w1 > w2) {
|
||||
// Allocate the buffer on heap
|
||||
(char *)malloc(w1);
|
||||
} else {
|
||||
// Allocate the buffer on stack
|
||||
b1 = (char*) _alloca(w1); // [DO NOT FLAG]
|
||||
}
|
||||
}
|
||||
memcpy(b1, v, w1);
|
||||
printf("%s\n", b1);
|
||||
if (w1 > w2) {
|
||||
free(b1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// case 5: _malloca contained in a do-while(0) that is in turn contained
|
||||
// in an unbounded loop
|
||||
void bar_ms(const struct vtype* vec, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
const struct vtype* v = vec + i;
|
||||
char *b1 = 0;
|
||||
do {
|
||||
if (b1 == NULL) {
|
||||
if (w1 > w2) {
|
||||
// Allocate the buffer on heap
|
||||
b1 = (char *)malloc(w1);
|
||||
} else {
|
||||
// Allocate the buffer on stack
|
||||
b1 = (char*) _malloca(w1); // [DO NOT FLAG]
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
memcpy(b1, v, w1);
|
||||
printf("%s\n", b1);
|
||||
if (w1 > w2) {
|
||||
free(b1);
|
||||
} else {
|
||||
_freea(b1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// case 6: _alloca contained in an unbounded loop that is in turn contained
|
||||
// in a do-while(0)
|
||||
void baz_ms(const struct vtype* vec, int count) {
|
||||
do {
|
||||
for (int i = 0; i < count; i++) {
|
||||
const struct vtype* v = vec + i;
|
||||
char *b1 = 0;
|
||||
if (b1 == NULL) {
|
||||
if (w1 > w2) {
|
||||
// Allocate the buffer on heap
|
||||
b1 = (char *)malloc(w1);
|
||||
} else {
|
||||
// Allocate the buffer on stack
|
||||
b1 = (char*) _alloca(w1); // [DO NOT FLAG]
|
||||
}
|
||||
}
|
||||
memcpy(b1, v, w1);
|
||||
printf("%s\n", b1);
|
||||
if (w1 > w2) {
|
||||
free(b1);
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// semmle-extractor-options: --clang
|
||||
int sprintf(char *buf, const char *format, ...);
|
||||
char * strdup(const char *str1);
|
||||
|
||||
void *__builtin_alloca(int sz);
|
||||
#define alloca __builtin_alloca
|
||||
|
||||
// case 1: a GNU c/c++ lambda with an alloca in it
|
||||
char *foo(int count) {
|
||||
char *buf = ({
|
||||
char *b = (char *)alloca(32); // [DO NOT FLAG]
|
||||
sprintf(b, "Value is %d\n", count);
|
||||
b;
|
||||
});
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
// case 1: a GNU expression statement with an alloca in it
|
||||
// nested inside a do-while(0)
|
||||
char *bar(int count) {
|
||||
char *buf;
|
||||
do {
|
||||
buf = ({
|
||||
char *b = (char *)alloca(32); // [DO NOT FLAG]
|
||||
sprintf(b, "Value is %d\n", count);
|
||||
b;
|
||||
});
|
||||
} while (0);
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
// case 2: a GNU expression statement with an alloca in it
|
||||
// nested inside an unbounded loop
|
||||
char *baz(int count) {
|
||||
char *buf;
|
||||
do {
|
||||
buf = ({
|
||||
char *b = (char *)alloca(32); // [FLAG]
|
||||
sprintf(b, "Value is %d\n", count);
|
||||
b;
|
||||
});
|
||||
} while (count++);
|
||||
return strdup(buf);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
typedef unsigned long size_t;
|
||||
// These are Microsoft routines for stack allocation
|
||||
// but should only be treated as such if they are declared
|
||||
// in the <malloc.h> header (i.e., this file)
|
||||
void *_alloca(size_t sz);
|
||||
void *_malloca(size_t sz);
|
||||
void _freea(void *ptr);
|
||||
Reference in New Issue
Block a user