brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.0 KiB · d9c4b77 Raw
254 lines · cpp
1// RUN: %clang_analyze_cc1 -verify -analyzer-output=text %s \2// RUN:   -analyzer-checker=core \3// RUN:   -analyzer-checker=cplusplus \4// RUN:   -analyzer-checker=unix \5// RUN:   -analyzer-config \6// RUN:     unix.DynamicMemoryModeling:AddNoOwnershipChangeNotes=false7 8// RUN: %clang_analyze_cc1 -verify=expected,ownership -analyzer-output=text %s \9// RUN:   -analyzer-checker=core \10// RUN:   -analyzer-checker=cplusplus \11// RUN:   -analyzer-checker=unix \12// RUN:   -analyzer-config \13// RUN:     unix.DynamicMemoryModeling:AddNoOwnershipChangeNotes=true14 15#include "Inputs/system-header-simulator-for-malloc.h"16// For the tests in namespace protobuf_leak:17#include "Inputs/system-header-simulator-for-protobuf.h"18 19//===----------------------------------------------------------------------===//20// Report for which we expect NoOwnershipChangeVisitor to add a new note.21//===----------------------------------------------------------------------===//22 23bool coin();24 25// TODO: AST analysis of sink would reveal that it doesn't intent to free the26// allocated memory, but in this instance, its also the only function with27// the ability to do so, we should see a note here.28namespace memory_allocated_in_fn_call {29 30void sink(int *P) {31}32 33void foo() {34  sink(new int(5)); // expected-note {{Memory is allocated}}35} // expected-warning {{Potential memory leak [cplusplus.NewDeleteLeaks]}}36// expected-note@-1 {{Potential memory leak}}37 38} // namespace memory_allocated_in_fn_call39 40// Realize that sink() intends to deallocate memory, assume that it should've41// taken care of the leaked object as well.42namespace memory_passed_to_fn_call_delete {43 44void sink(int *P) {45  if (coin()) // ownership-note {{Assuming the condition is false}}46              // ownership-note@-1 {{Taking false branch}}47    delete P;48} // ownership-note {{Returning without deallocating memory or storing the pointer for later deallocation}}49 50void foo() {51  int *ptr = new int(5); // expected-note {{Memory is allocated}}52  sink(ptr);             // ownership-note {{Calling 'sink'}}53                         // ownership-note@-1 {{Returning from 'sink'}}54} // expected-warning {{Potential leak of memory pointed to by 'ptr' [cplusplus.NewDeleteLeaks]}}55// expected-note@-1 {{Potential leak}}56 57} // namespace memory_passed_to_fn_call_delete58 59namespace memory_passed_to_fn_call_free {60 61void sink(int *P) {62  if (coin()) // ownership-note {{Assuming the condition is false}}63              // ownership-note@-1 {{Taking false branch}}64    free(P);65} // ownership-note {{Returning without deallocating memory or storing the pointer for later deallocation}}66 67void foo() {68  int *ptr = (int *)malloc(sizeof(int)); // expected-note {{Memory is allocated}}69  sink(ptr);                             // ownership-note {{Calling 'sink'}}70                                         // ownership-note@-1 {{Returning from 'sink'}}71} // expected-warning {{Potential leak of memory pointed to by 'ptr' [unix.Malloc]}}72// expected-note@-1 {{Potential leak}}73 74} // namespace memory_passed_to_fn_call_free75 76// Function pointers cannot be resolved syntactically.77namespace memory_passed_to_fn_call_free_through_fn_ptr {78void (*freeFn)(void *) = free;79 80void sink(int *P) {81  if (coin())82    freeFn(P);83}84 85void foo() {86  int *ptr = (int *)malloc(sizeof(int)); // expected-note {{Memory is allocated}}87  sink(ptr);88} // expected-warning {{Potential leak of memory pointed to by 'ptr' [unix.Malloc]}}89// expected-note@-1 {{Potential leak}}90 91} // namespace memory_passed_to_fn_call_free_through_fn_ptr92 93namespace memory_shared_with_ptr_of_shorter_lifetime {94 95void sink(int *P) {96  int *Q = P;97  if (coin()) // ownership-note {{Assuming the condition is false}}98              // ownership-note@-1 {{Taking false branch}}99    delete P;100  (void)Q;101} // ownership-note {{Returning without deallocating memory or storing the pointer for later deallocation}}102 103void foo() {104  int *ptr = new int(5); // expected-note {{Memory is allocated}}105  sink(ptr);             // ownership-note {{Calling 'sink'}}106                         // ownership-note@-1 {{Returning from 'sink'}}107} // expected-warning {{Potential leak of memory pointed to by 'ptr' [cplusplus.NewDeleteLeaks]}}108// expected-note@-1 {{Potential leak}}109 110} // namespace memory_shared_with_ptr_of_shorter_lifetime111 112//===----------------------------------------------------------------------===//113// Report for which we *do not* expect NoOwnershipChangeVisitor add a new note,114// nor do we want it to.115//===----------------------------------------------------------------------===//116 117namespace memory_not_passed_to_fn_call {118 119void sink(int *P) {120  if (coin())121    delete P;122}123 124void foo() {125  int *ptr = new int(5); // expected-note {{Memory is allocated}}126  int *q = nullptr;127  sink(q);128  (void)ptr;129} // expected-warning {{Potential leak of memory pointed to by 'ptr' [cplusplus.NewDeleteLeaks]}}130// expected-note@-1 {{Potential leak}}131 132} // namespace memory_not_passed_to_fn_call133 134namespace memory_shared_with_ptr_of_same_lifetime {135 136void sink(int *P, int **Q) {137  // NOTE: Not a job of NoOwnershipChangeVisitor, but maybe this could be138  // highlighted still?139  *Q = P;140}141 142void foo() {143  int *ptr = new int(5); // expected-note {{Memory is allocated}}144  int *q = nullptr;145  sink(ptr, &q);146} // expected-warning {{Potential leak of memory pointed to by 'q' [cplusplus.NewDeleteLeaks]}}147// expected-note@-1 {{Potential leak}}148 149} // namespace memory_shared_with_ptr_of_same_lifetime150 151namespace memory_passed_into_fn_that_doesnt_intend_to_free {152 153void sink(int *P) {154}155 156void foo() {157  int *ptr = new int(5); // expected-note {{Memory is allocated}}158  sink(ptr);159} // expected-warning {{Potential leak of memory pointed to by 'ptr' [cplusplus.NewDeleteLeaks]}}160// expected-note@-1 {{Potential leak}}161 162} // namespace memory_passed_into_fn_that_doesnt_intend_to_free163 164namespace memory_passed_into_fn_that_doesnt_intend_to_free2 {165 166void bar();167 168void sink(int *P) {169  // Correctly realize that calling bar() doesn't mean that this function would170  // like to deallocate anything.171  bar();172}173 174void foo() {175  int *ptr = new int(5); // expected-note {{Memory is allocated}}176  sink(ptr);177} // expected-warning {{Potential leak of memory pointed to by 'ptr' [cplusplus.NewDeleteLeaks]}}178// expected-note@-1 {{Potential leak}}179 180} // namespace memory_passed_into_fn_that_doesnt_intend_to_free2181 182namespace refkind_from_unoallocated_to_allocated {183 184// RefKind of the symbol changed from nothing to Allocated. We don't want to185// emit notes when the RefKind changes in the stack frame.186static char *malloc_wrapper_ret() {187  return (char *)malloc(12); // expected-note {{Memory is allocated}}188}189void use_ret() {190  char *v;191  v = malloc_wrapper_ret(); // expected-note {{Calling 'malloc_wrapper_ret'}}192                            // expected-note@-1 {{Returned allocated memory}}193} // expected-warning {{Potential leak of memory pointed to by 'v' [unix.Malloc]}}194// expected-note@-1 {{Potential leak of memory pointed to by 'v'}}195 196} // namespace refkind_from_unoallocated_to_allocated197 198// Check that memory leak is reported against a symbol if the last place it's199// mentioned is a base region of a lazy compound value, as the program cannot200// possibly free that memory.201namespace symbol_reaper_lifetime {202struct Nested {203  int buf[2];204};205struct Wrapping {206  Nested data;207};208 209Nested allocateWrappingAndReturnNested() {210  // expected-note@+1 {{Memory is allocated}}211  Wrapping const* p = new Wrapping();212  // expected-warning@+2 {{Potential leak of memory pointed to by 'p'}}213  // expected-note@+1    {{Potential leak of memory pointed to by 'p'}}214  return p->data;215}216 217void caller() {218  // expected-note@+1 {{Calling 'allocateWrappingAndReturnNested'}}219  Nested n = allocateWrappingAndReturnNested();220  (void)n;221} // no-warning: No potential memory leak here, because that's been already reported.222} // namespace symbol_reaper_lifetime223 224// Check that we do not report false positives in automatically generated225// protobuf code that passes dynamically allocated memory to a certain function226// named GetOwnedMessageInternal.227namespace protobuf_leak {228Arena *some_arena, *some_submessage_arena;229 230MessageLite *protobuf_leak() {231  MessageLite *p = new MessageLite(); // Real protobuf code instantiates a232                                      // subclass of MessageLite, but that's233                                      // not relevant for the bug.234  MessageLite *q = GetOwnedMessageInternal(some_arena, p, some_submessage_arena);235  return q;236  // No leak at end of function -- the pointer escapes in GetOwnedMessageInternal.237}238 239void validate_system_header() {240  // The case protobuf_leak would also pass if GetOwnedMessageInternal wasn't241  // declared in a system header. This test verifies that another function242  // declared in the same header behaves differently (doesn't escape memory) to243  // demonstrate that GetOwnedMessageInternal is indeed explicitly recognized244  // by the analyzer.245 246  // expected-note@+1 {{Memory is allocated}}247  MessageLite *p = new MessageLite();248  SomeOtherFunction(p);249  // expected-warning@+2 {{Potential leak of memory pointed to by 'p'}}250  // expected-note@+1    {{Potential leak of memory pointed to by 'p'}}251}252 253} // namespace protobuf_leak254