2021-05-18 19:06:02 +08:00
|
|
|
// RUN: %clang_analyze_cc1 -w -verify %s \
|
|
|
|
// RUN: -analyzer-checker=core \
|
|
|
|
// RUN: -analyzer-checker=alpha.deadcode.UnreachableCode \
|
|
|
|
// RUN: -analyzer-checker=alpha.core.CastSize \
|
|
|
|
// RUN: -analyzer-checker=unix.Malloc \
|
|
|
|
// RUN: -analyzer-checker=cplusplus.NewDelete
|
|
|
|
|
|
|
|
// RUN: %clang_analyze_cc1 -w -verify %s \
|
|
|
|
// RUN: -triple i386-unknown-linux-gnu \
|
|
|
|
// RUN: -analyzer-checker=core \
|
|
|
|
// RUN: -analyzer-checker=alpha.deadcode.UnreachableCode \
|
|
|
|
// RUN: -analyzer-checker=alpha.core.CastSize \
|
|
|
|
// RUN: -analyzer-checker=unix.Malloc \
|
|
|
|
// RUN: -analyzer-checker=cplusplus.NewDelete
|
|
|
|
|
|
|
|
// RUN: %clang_analyze_cc1 -w -verify %s -DTEST_INLINABLE_ALLOCATORS \
|
|
|
|
// RUN: -analyzer-checker=core \
|
|
|
|
// RUN: -analyzer-checker=alpha.deadcode.UnreachableCode \
|
|
|
|
// RUN: -analyzer-checker=alpha.core.CastSize \
|
|
|
|
// RUN: -analyzer-checker=unix.Malloc \
|
|
|
|
// RUN: -analyzer-checker=cplusplus.NewDelete
|
|
|
|
|
|
|
|
// RUN: %clang_analyze_cc1 -w -verify %s -DTEST_INLINABLE_ALLOCATORS \
|
|
|
|
// RUN: -triple i386-unknown-linux-gnu \
|
|
|
|
// RUN: -analyzer-checker=core \
|
|
|
|
// RUN: -analyzer-checker=alpha.deadcode.UnreachableCode \
|
|
|
|
// RUN: -analyzer-checker=alpha.core.CastSize \
|
|
|
|
// RUN: -analyzer-checker=unix.Malloc \
|
|
|
|
// RUN: -analyzer-checker=cplusplus.NewDelete
|
2012-03-30 07:26:54 +08:00
|
|
|
|
2016-12-16 06:55:18 +08:00
|
|
|
#include "Inputs/system-header-simulator-cxx.h"
|
|
|
|
|
2012-03-30 07:26:54 +08:00
|
|
|
typedef __typeof(sizeof(int)) size_t;
|
|
|
|
void *malloc(size_t);
|
|
|
|
void free(void *);
|
|
|
|
void *realloc(void *ptr, size_t size);
|
|
|
|
void *calloc(size_t nmemb, size_t size);
|
2013-04-02 09:28:24 +08:00
|
|
|
char *strdup(const char *s);
|
[analyzer] Always include destructors in the analysis CFG.
While destructors will continue to not be inlined (unless the analyzer
config option 'c++-inlining' is set to 'destructors'), leaving them out
of the CFG is an incomplete model of the behavior of an object, and
can cause false positive warnings (like PR13751, now working).
Destructors for temporaries are still not on by default, since
(a) we haven't actually checked this code to be sure it's fully correct
(in particular, we probably need to be very careful with regard to
lifetime-extension when a temporary is bound to a reference,
C++11 [class.temporary]p5), and
(b) ExprEngine doesn't actually do anything when it sees a temporary
destructor in the CFG -- not even invalidate the object region.
To enable temporary destructors, set the 'cfg-temporary-dtors' analyzer
config option to '1'. The old -cfg-add-implicit-dtors cc1 option, which
controlled all implicit destructors, has been removed.
llvm-svn: 163264
2012-09-06 06:55:23 +08:00
|
|
|
|
|
|
|
void checkThatMallocCheckerIsRunning() {
|
2012-11-16 03:11:43 +08:00
|
|
|
malloc(4);
|
|
|
|
} // expected-warning{{leak}}
|
[analyzer] Always include destructors in the analysis CFG.
While destructors will continue to not be inlined (unless the analyzer
config option 'c++-inlining' is set to 'destructors'), leaving them out
of the CFG is an incomplete model of the behavior of an object, and
can cause false positive warnings (like PR13751, now working).
Destructors for temporaries are still not on by default, since
(a) we haven't actually checked this code to be sure it's fully correct
(in particular, we probably need to be very careful with regard to
lifetime-extension when a temporary is bound to a reference,
C++11 [class.temporary]p5), and
(b) ExprEngine doesn't actually do anything when it sees a temporary
destructor in the CFG -- not even invalidate the object region.
To enable temporary destructors, set the 'cfg-temporary-dtors' analyzer
config option to '1'. The old -cfg-add-implicit-dtors cc1 option, which
controlled all implicit destructors, has been removed.
llvm-svn: 163264
2012-09-06 06:55:23 +08:00
|
|
|
|
2012-03-30 07:26:54 +08:00
|
|
|
// Test for radar://11110132.
|
|
|
|
struct Foo {
|
|
|
|
mutable void* m_data;
|
|
|
|
Foo(void* data) : m_data(data) {}
|
|
|
|
};
|
|
|
|
Foo aFunction() {
|
|
|
|
return malloc(10);
|
|
|
|
}
|
2012-05-04 07:50:28 +08:00
|
|
|
|
|
|
|
// Assume that functions which take a function pointer can free memory even if
|
|
|
|
// they are defined in system headers and take the const pointer to the
|
|
|
|
// allocated memory. (radar://11160612)
|
|
|
|
// Test default parameter.
|
[analyzer] Consolidate constant evaluation logic in SValBuilder.
Previously, this was scattered across Environment (literal expressions),
ExprEngine (default arguments), and RegionStore (global constants). The
former special-cased several kinds of simple constant expressions, while
the latter two deferred to the AST's constant evaluator.
Now, these are all unified as SValBuilder::getConstantVal(). To keep
Environment fast, the special cases for simple constant expressions have
been left in, but the main benefits are that (a) unusual constants like
ObjCStringLiterals now work as default arguments and global constant
initializers, and (b) we're not duplicating code between ExprEngine and
RegionStore.
This actually caught a bug in our test suite, which is awesome: we stop
tracking allocated memory if it's passed as an argument along with some
kind of callback, but not if the callback is 0. We were testing this in
a case where the callback parameter had a default value, but that value
was 0. After this change, the analyzer now (correctly) flags that as a
leak!
<rdar://problem/13773117>
llvm-svn: 180894
2013-05-02 07:10:44 +08:00
|
|
|
int const_ptr_and_callback_def_param(int, const char*, int n, void(*)(void*) = free);
|
2012-05-04 07:50:28 +08:00
|
|
|
void r11160612_3() {
|
|
|
|
char *x = (char*)malloc(12);
|
|
|
|
const_ptr_and_callback_def_param(0, x, 12);
|
|
|
|
}
|
2012-05-05 06:18:36 +08:00
|
|
|
|
[analyzer] Consolidate constant evaluation logic in SValBuilder.
Previously, this was scattered across Environment (literal expressions),
ExprEngine (default arguments), and RegionStore (global constants). The
former special-cased several kinds of simple constant expressions, while
the latter two deferred to the AST's constant evaluator.
Now, these are all unified as SValBuilder::getConstantVal(). To keep
Environment fast, the special cases for simple constant expressions have
been left in, but the main benefits are that (a) unusual constants like
ObjCStringLiterals now work as default arguments and global constant
initializers, and (b) we're not duplicating code between ExprEngine and
RegionStore.
This actually caught a bug in our test suite, which is awesome: we stop
tracking allocated memory if it's passed as an argument along with some
kind of callback, but not if the callback is 0. We were testing this in
a case where the callback parameter had a default value, but that value
was 0. After this change, the analyzer now (correctly) flags that as a
leak!
<rdar://problem/13773117>
llvm-svn: 180894
2013-05-02 07:10:44 +08:00
|
|
|
int const_ptr_and_callback_def_param_null(int, const char*, int n, void(*)(void*) = 0);
|
|
|
|
void r11160612_no_callback() {
|
|
|
|
char *x = (char*)malloc(12);
|
|
|
|
const_ptr_and_callback_def_param_null(0, x, 12);
|
|
|
|
} // expected-warning{{leak}}
|
|
|
|
|
2012-05-05 06:18:36 +08:00
|
|
|
// Test member function pointer.
|
|
|
|
struct CanFreeMemory {
|
|
|
|
static void myFree(void*);
|
|
|
|
};
|
|
|
|
//This is handled because we look at the type of the parameter(not argument).
|
|
|
|
void r11160612_3(CanFreeMemory* p) {
|
|
|
|
char *x = (char*)malloc(12);
|
|
|
|
const_ptr_and_callback_def_param(0, x, 12, p->myFree);
|
|
|
|
}
|
|
|
|
|
[analyzer] Always include destructors in the analysis CFG.
While destructors will continue to not be inlined (unless the analyzer
config option 'c++-inlining' is set to 'destructors'), leaving them out
of the CFG is an incomplete model of the behavior of an object, and
can cause false positive warnings (like PR13751, now working).
Destructors for temporaries are still not on by default, since
(a) we haven't actually checked this code to be sure it's fully correct
(in particular, we probably need to be very careful with regard to
lifetime-extension when a temporary is bound to a reference,
C++11 [class.temporary]p5), and
(b) ExprEngine doesn't actually do anything when it sees a temporary
destructor in the CFG -- not even invalidate the object region.
To enable temporary destructors, set the 'cfg-temporary-dtors' analyzer
config option to '1'. The old -cfg-add-implicit-dtors cc1 option, which
controlled all implicit destructors, has been removed.
llvm-svn: 163264
2012-09-06 06:55:23 +08:00
|
|
|
|
|
|
|
namespace PR13751 {
|
|
|
|
class OwningVector {
|
|
|
|
void **storage;
|
|
|
|
size_t length;
|
|
|
|
public:
|
|
|
|
OwningVector();
|
|
|
|
~OwningVector();
|
|
|
|
void push_back(void *Item) {
|
|
|
|
storage[length++] = Item;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void testDestructors() {
|
|
|
|
OwningVector v;
|
|
|
|
v.push_back(malloc(4));
|
|
|
|
// no leak warning; freed in destructor
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-06 08:01:14 +08:00
|
|
|
struct X { void *a; };
|
|
|
|
|
|
|
|
struct X get() {
|
|
|
|
struct X result;
|
|
|
|
result.a = malloc(4);
|
|
|
|
return result; // no-warning
|
|
|
|
}
|
2013-04-02 09:28:24 +08:00
|
|
|
|
|
|
|
// Ensure that regions accessible through a LazyCompoundVal trigger region escape.
|
|
|
|
// Malloc checker used to report leaks for the following two test cases.
|
|
|
|
struct Property {
|
|
|
|
char* getterName;
|
|
|
|
Property(char* n)
|
|
|
|
: getterName(n) {}
|
|
|
|
|
|
|
|
};
|
|
|
|
void append(Property x);
|
|
|
|
|
|
|
|
void appendWrapper(char *getterName) {
|
|
|
|
append(Property(getterName));
|
|
|
|
}
|
|
|
|
void foo(const char* name) {
|
|
|
|
char* getterName = strdup(name);
|
|
|
|
appendWrapper(getterName); // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
struct NestedProperty {
|
|
|
|
Property prop;
|
|
|
|
NestedProperty(Property p)
|
|
|
|
: prop(p) {}
|
|
|
|
};
|
|
|
|
void appendNested(NestedProperty x);
|
|
|
|
|
|
|
|
void appendWrapperNested(char *getterName) {
|
|
|
|
appendNested(NestedProperty(Property(getterName)));
|
|
|
|
}
|
|
|
|
void fooNested(const char* name) {
|
|
|
|
char* getterName = strdup(name);
|
|
|
|
appendWrapperNested(getterName); // no-warning
|
2016-12-08 00:12:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace PR31226 {
|
|
|
|
struct b2 {
|
|
|
|
int f;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct b1 : virtual b2 {
|
|
|
|
void m();
|
|
|
|
};
|
|
|
|
|
|
|
|
struct d : b1, b2 {
|
|
|
|
};
|
|
|
|
|
|
|
|
void f() {
|
|
|
|
d *p = new d();
|
|
|
|
p->m(); // no-crash // no-warning
|
|
|
|
}
|
|
|
|
}
|
2016-12-16 06:55:18 +08:00
|
|
|
|
|
|
|
// Allow __cxa_demangle to escape.
|
|
|
|
char* test_cxa_demangle(const char* sym) {
|
|
|
|
size_t funcnamesize = 256;
|
|
|
|
char* funcname = (char*)malloc(funcnamesize);
|
|
|
|
int status;
|
|
|
|
char* ret = abi::__cxa_demangle(sym, funcname, &funcnamesize, &status);
|
|
|
|
if (status == 0) {
|
|
|
|
funcname = ret;
|
|
|
|
}
|
|
|
|
return funcname; // no-warning
|
|
|
|
}
|
2019-04-13 10:01:45 +08:00
|
|
|
|
|
|
|
namespace argument_leak {
|
|
|
|
class A {
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
public:
|
|
|
|
char *getName() {
|
|
|
|
if (!name) {
|
|
|
|
name = static_cast<char *>(malloc(10));
|
|
|
|
}
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
~A() {
|
|
|
|
if (name) {
|
|
|
|
delete[] name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void test(A a) {
|
|
|
|
(void)a.getName();
|
|
|
|
}
|
|
|
|
} // namespace argument_leak
|
[Analyzer][MallocChecker] No warning for kfree of ZERO_SIZE_PTR.
Summary:
The kernel kmalloc function may return a constant value ZERO_SIZE_PTR
if a zero-sized block is allocated. This special value is allowed to
be passed to kfree and should produce no warning.
This is a simple version but should be no problem. The macro is always
detected independent of if this is a kernel source code or any other
code.
Reviewers: Szelethus, martong
Reviewed By: Szelethus, martong
Subscribers: rnkovacs, xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, gamesh411, Charusso, martong, ASDenysPetrov, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D76830
2020-03-30 15:23:07 +08:00
|
|
|
|
|
|
|
#define ZERO_SIZE_PTR ((void *)16)
|
|
|
|
|
|
|
|
void test_delete_ZERO_SIZE_PTR() {
|
|
|
|
int *Ptr = (int *)ZERO_SIZE_PTR;
|
|
|
|
// ZERO_SIZE_PTR is specially handled but only for malloc family
|
|
|
|
delete Ptr; // expected-warning{{Argument to 'delete' is a constant address (16)}}
|
|
|
|
}
|
2020-06-13 00:15:20 +08:00
|
|
|
|
|
|
|
namespace pr46253_class {
|
|
|
|
class a {
|
|
|
|
void *realloc(int, bool = false) { realloc(1); } // no-crash
|
|
|
|
};
|
|
|
|
} // namespace pr46253_class
|
|
|
|
|
|
|
|
namespace pr46253_retty{
|
|
|
|
void realloc(void *ptr, size_t size) { realloc(ptr, size); } // no-crash
|
|
|
|
} // namespace pr46253_retty
|
|
|
|
|
|
|
|
namespace pr46253_paramty{
|
|
|
|
void *realloc(void **ptr, size_t size) { realloc(ptr, size); } // no-crash
|
|
|
|
} // namespace pr46253_paramty
|
|
|
|
|
|
|
|
namespace pr46253_paramty2{
|
|
|
|
void *realloc(void *ptr, int size) { realloc(ptr, size); } // no-crash
|
|
|
|
} // namespace pr46253_paramty2
|