mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-03 19:32:35 +00:00
e37ab50a6e
This fixes a few cases where we'd emit path notes like this: +---+ 1| v p = malloc(len); ^ |2 +---+ In general this should make path notes more consistent and more correct, especially in cases where the leak happens on the false branch of an if that jumps directly to the end of the function. There are a couple places where the leak is reported farther away from the cause; these are usually cases where there are several levels of nested braces before the end of the function. This still matches our current behavior for when there /is/ a statement after all the braces, though. llvm-svn: 168070
103 lines
2.3 KiB
C
103 lines
2.3 KiB
C
// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -analyzer-max-loop 4 -verify %s
|
|
#include "Inputs/system-header-simulator.h"
|
|
|
|
typedef __typeof(sizeof(int)) size_t;
|
|
void *malloc(size_t);
|
|
|
|
static int another_function(int *y) {
|
|
if (*y > 0)
|
|
return *y;
|
|
return 0;
|
|
}
|
|
|
|
static void function_which_doesnt_give_up(int **x) {
|
|
*x = 0;
|
|
}
|
|
|
|
static void function_which_gives_up(int *x) {
|
|
for (int i = 0; i < 5; ++i)
|
|
(*x)++;
|
|
}
|
|
|
|
static void function_which_gives_up_nested(int *x) {
|
|
function_which_gives_up(x);
|
|
for (int i = 0; i < 5; ++i)
|
|
(*x)++;
|
|
}
|
|
|
|
static void function_which_doesnt_give_up_nested(int *x, int *y) {
|
|
*y = another_function(x);
|
|
function_which_gives_up(x);
|
|
}
|
|
|
|
void coverage1(int *x) {
|
|
function_which_gives_up(x);
|
|
char *m = (char*)malloc(12);
|
|
} // expected-warning {{potential leak}}
|
|
|
|
void coverage2(int *x) {
|
|
if (x) {
|
|
function_which_gives_up(x);
|
|
char *m = (char*)malloc(12);
|
|
}
|
|
} // expected-warning {{potential leak}}
|
|
|
|
void coverage3(int *x) {
|
|
x++;
|
|
function_which_gives_up(x);
|
|
char *m = (char*)malloc(12);
|
|
} // expected-warning {{potential leak}}
|
|
|
|
void coverage4(int *x) {
|
|
*x += another_function(x);
|
|
function_which_gives_up(x);
|
|
char *m = (char*)malloc(12);
|
|
} // expected-warning {{potential leak}}
|
|
|
|
void coverage5(int *x) {
|
|
for (int i = 0; i<7; ++i)
|
|
function_which_gives_up(x);
|
|
// The root function gives up here.
|
|
char *m = (char*)malloc(12); // no-warning
|
|
}
|
|
|
|
void coverage6(int *x) {
|
|
for (int i = 0; i<3; ++i) {
|
|
function_which_gives_up(x);
|
|
}
|
|
char *m = (char*)malloc(12);
|
|
} // expected-warning {{potential leak}}
|
|
|
|
int coverage7_inline(int *i) {
|
|
function_which_doesnt_give_up(&i);
|
|
return *i; // expected-warning {{Dereference}}
|
|
}
|
|
|
|
void coverage8(int *x) {
|
|
int y;
|
|
function_which_doesnt_give_up_nested(x, &y);
|
|
y = (*x)/y; // expected-warning {{Division by zero}}
|
|
char *m = (char*)malloc(12);
|
|
} // expected-warning {{potential leak}}
|
|
|
|
void function_which_gives_up_settonull(int **x) {
|
|
*x = 0;
|
|
int y = 0;
|
|
for (int i = 0; i < 5; ++i)
|
|
y++;
|
|
}
|
|
|
|
void coverage9(int *x) {
|
|
int y = 5;
|
|
function_which_gives_up_settonull(&x);
|
|
y = (*x); // no warning
|
|
}
|
|
|
|
static void empty_function(){
|
|
}
|
|
int use_empty_function(int x) {
|
|
x = 0;
|
|
empty_function();
|
|
return 5/x; //expected-warning {{Division by zero}}
|
|
}
|