brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.8 KiB · 8e5c6c4 Raw
329 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -std=c++11 -verify -analyzer-config eagerly-assume=false %s2// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify -analyzer-config eagerly-assume=false %s3#include "Inputs/system-header-simulator-cxx.h"4 5void clang_analyzer_eval(bool);6void clang_analyzer_warnIfReached();7 8typedef __typeof__(sizeof(int)) size_t;9extern "C" void *malloc(size_t);10extern "C" void free(void *);11 12int someGlobal;13 14class SomeClass {15public:16  void f(int *p);17};18 19void testImplicitlyDeclaredGlobalNew() {20  if (someGlobal != 0)21    return;22 23  // This used to crash because the global operator new is being implicitly24  // declared and it does not have a valid source location. (PR13090)25  void *x = ::operator new(0);26  ::operator delete(x);27 28  // Check that the new/delete did not invalidate someGlobal;29  clang_analyzer_eval(someGlobal == 0); // expected-warning{{TRUE}}30}31 32void *testPlacementNew() {33  int *x = (int *)malloc(sizeof(int));34  *x = 1;35  clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};36 37  void *y = new (x) int;38  clang_analyzer_eval(x == y); // expected-warning{{TRUE}};39  clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};40 41  return y;42}43 44void *operator new(size_t, size_t, int *);45void *testCustomNew() {46  int x[1] = {1};47  clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};48 49  void *y = new (0, x) int;50  clang_analyzer_eval(*x == 1); // expected-warning{{UNKNOWN}};51 52  return y; // no-warning53}54 55void *operator new(size_t, void *, void *);56void *testCustomNewMalloc() {57  int *x = (int *)malloc(sizeof(int));58 59  // Should be no-warning (the custom allocator could have freed x).60  void *y = new (0, x) int; // no-warning61 62  return y;63}64 65void testScalarInitialization() {66  int *n = new int(3);67  clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}}68 69  new (n) int();70  clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}}71 72  new (n) int{3};73  clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}}74 75  new (n) int{};76  clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}}77}78 79struct PtrWrapper {80  int *x;81 82  PtrWrapper(int *input) : x(input) {}83};84 85PtrWrapper *testNewInvalidation() {86  // Ensure that we don't consider this a leak.87  return new PtrWrapper(static_cast<int *>(malloc(4))); // no-warning88}89 90void testNewInvalidationPlacement(PtrWrapper *w) {91  // Ensure that we don't consider this a leak.92  new (w) PtrWrapper(static_cast<int *>(malloc(4))); // no-warning93}94 95int **testNewInvalidationScalar() {96  // Ensure that we don't consider this a leak.97  return new (int *)(static_cast<int *>(malloc(4))); // no-warning98}99 100void testNewInvalidationScalarPlacement(int **p) {101  // Ensure that we don't consider this a leak.102  new (p) (int *)(static_cast<int *>(malloc(4))); // no-warning103}104 105void testCacheOut(PtrWrapper w) {106  extern bool coin();107  if (coin())108    w.x = 0;109  new (&w.x) (int*)(0); // we cache out here; don't crash110}111 112void testUseAfter(int *p) {113  SomeClass *c = new SomeClass;114  free(p);115  c->f(p); // expected-warning{{Use of memory after it is released}}116  delete c;117}118 119// new/delete oparators are subjects of cplusplus.NewDelete.120void testNewDeleteNoWarn() {121  int i;122  delete &i; // no-warning123 124  int *p1 = new int;125  delete ++p1; // no-warning126 127  int *p2 = new int;128  delete p2;129  delete p2; // no-warning130 131  int *p3 = new int; // no-warning132}133 134void testDeleteMallocked() {135  int *x = (int *)malloc(sizeof(int));136  // unix.MismatchedDeallocator would catch this, but we're not testing it here.137  delete x;138}139 140void testDeleteOpAfterFree() {141  int *p = (int *)malloc(sizeof(int));142  free(p);143  operator delete(p); // expected-warning{{Use of memory after it is released}}144}145 146void testDeleteAfterFree() {147  int *p = (int *)malloc(sizeof(int));148  free(p);149  delete p; // expected-warning{{Use of memory after it is released}}150}151 152void testStandardPlacementNewAfterFree() {153  int *p = (int *)malloc(sizeof(int));154  free(p);155  p = new(p) int; // expected-warning{{Use of memory after it is released}}156}157 158void testCustomPlacementNewAfterFree() {159  int *p = (int *)malloc(sizeof(int));160  free(p);161  p = new(0, p) int; // expected-warning{{Use of memory after it is released}}162}163 164void testUsingThisAfterDelete() {165  SomeClass *c = new SomeClass;166  delete c;167  c->f(0); // no-warning168}169 170void testAggregateNew() {171  struct Point { int x, y; };172  new Point{1, 2}; // no crash173 174  Point p;175  new (&p) Point{1, 2}; // no crash176  clang_analyzer_eval(p.x == 1); // expected-warning{{TRUE}}177  clang_analyzer_eval(p.y == 2); // expected-warning{{TRUE}}178}179 180int testNoInitialization() {181  int *n = new int;182 183  if (*n) { // expected-warning{{Branch condition evaluates to a garbage value [core.uninitialized.Branch]}}184    delete n;185    return 0;186  }187  delete n;188  return 1;189}190 191//===----------------------------------------------------------------------===//192// Incorrectly-modelled behavior.193//===----------------------------------------------------------------------===//194 195int testNoInitializationPlacement() {196  int n;197  new (&n) int;198 199  if (n) { // expected-warning{{Branch condition evaluates to a garbage value}}200    return 0;201  }202  return 1;203}204 205// Test modelling destructor call on call to delete206class IntPair{207public:208  int x;209  int y;210  IntPair() {};211  ~IntPair() {x = x/y;}; //expected-warning {{Division by zero}}212};213 214void testCallToDestructor() {215  IntPair *b = new IntPair();216  b->x = 1;217  b->y = 0;218  delete b; // This results in divide by zero in destructor219}220 221// Test Deleting a value that's passed as an argument.222class DerefClass{223public:224  int *x;225  DerefClass() {};226  ~DerefClass() {*x = 1;}; //expected-warning {{Dereference of null pointer (loaded from field 'x')}}227};228 229void testDestCall(DerefClass *arg) {230  delete arg;231}232 233void test_delete_dtor_Arg() {234  DerefClass *pair = new DerefClass();235  pair->x = 0;236  testDestCall(pair);237}238 239//Deleting the address of a local variable, null pointer240void abort(void) __attribute__((noreturn));241 242class NoReturnDtor {243public:244  NoReturnDtor() {}245  ~NoReturnDtor() {abort();}246};247 248void test_delete_dtor_LocalVar() {249  NoReturnDtor test;250  delete &test; // no warn or crash251}252 253class DerivedNoReturn:public NoReturnDtor {254public:255  DerivedNoReturn() {};256  ~DerivedNoReturn() {};257};258 259void testNullDtorDerived() {260  DerivedNoReturn *p = new DerivedNoReturn();261  delete p; // Calls the base destructor which aborts, checked below262  clang_analyzer_eval(true); // no warn263}264 265//Deleting a non-class pointer should not crash/warn266void test_var_delete() {267  int *v = new int;268  delete v;  // no crash/warn269  clang_analyzer_eval(true); // expected-warning{{TRUE}}270}271 272void test_array_delete() {273  class C {274  public:275    ~C() {}276  };277 278  auto c1 = new C[2][3];279  delete[] c1; // no-crash // no-warning280 281  C c2[4];282  // FIXME: Should warn.283  delete[] &c2; // no-crash284 285  C c3[7][6];286  // FIXME: Should warn.287  delete[] &c3; // no-crash288}289 290void testDeleteNull() {291  NoReturnDtor *foo = 0;292  delete foo; // should not call destructor, checked below293  clang_analyzer_eval(true); // expected-warning{{TRUE}}294}295 296void testNullAssigneddtor() {297  NoReturnDtor *p = 0;298  NoReturnDtor *s = p;299  delete s; // should not call destructor, checked below300  clang_analyzer_eval(true); // expected-warning{{TRUE}}301}302 303void deleteArg(NoReturnDtor *test) {304  delete test;305}306 307void testNulldtorArg() {308  NoReturnDtor *p = 0;309  deleteArg(p);310  clang_analyzer_eval(true); // expected-warning{{TRUE}}311}312 313void testDeleteUnknown(NoReturnDtor *foo) {314  delete foo; // should assume non-null and call noreturn destructor315  clang_analyzer_eval(true); // no-warning316}317 318void testArrayNull() {319  NoReturnDtor *fooArray = 0;320  delete[] fooArray; // should not call destructor, checked below321  clang_analyzer_eval(true); // expected-warning{{TRUE}}322}323 324void testArrayDestr() {325  NoReturnDtor *p = new NoReturnDtor[2];326  delete[] p;327  clang_analyzer_warnIfReached(); // no-warning328}329