/* * Copyright (c) 2017-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ class my_class { int idx; int arr[10]; void set_a(int n) { idx = n; } int id(int n) { return n; } public: int access_Bad() { set_a(10); return arr[idx]; } int access2_Bad() { int n = 10; return arr[id(n)]; } int access_nth(int n) { return arr[n]; } }; void access_after_new_Good() { my_class* x = new my_class(); x->access_nth(5); } void access_after_new_Bad() { my_class* x = new my_class(); x->access_nth(15); } #include class my_class2 { public: int a[5]; }; void array_member_malloc_Good() { my_class2* x = (my_class2*)malloc(sizeof(my_class2)); x->a[0] = 0; } void array_member_malloc_Bad() { my_class2* x = (my_class2*)malloc(sizeof(my_class2)); x->a[10] = 0; } class my_class3 { public: my_class2 b; }; void array_member_malloc2_Bad() { my_class3* x = (my_class3*)malloc(sizeof(my_class3)); x->b.a[10] = 0; } #include void new_nothrow_Good() { my_class2* x = new (std::nothrow) my_class2(); x->a[0] = 0; } void new_nothrow_Bad() { my_class2* x = new (std::nothrow) my_class2(); x->a[10] = 0; } void placement_new_Good() { char* mem = (char*)malloc(sizeof(my_class2)); my_class2* x = new (mem) my_class2(); x->a[0] = 0; } void placement_new_Bad() { char* mem = (char*)malloc(sizeof(my_class2)); my_class2* x = new (mem) my_class2(); x->a[10] = 0; } enum class DummyClass {}; inline void* operator new(std::size_t, DummyClass, void* p) { return p; } inline void* operator new(std::size_t, void* p, DummyClass) { return p; } void placement_new_overload1_Good() { char* mem = (char*)malloc(sizeof(my_class2)); my_class2* x = new (DummyClass{}, mem) my_class2(); x->a[0] = 0; } void placement_new_overload1_Bad() { char* mem = (char*)malloc(sizeof(my_class2)); my_class2* x = new (DummyClass{}, mem) my_class2(); x->a[10] = 0; } void placement_new_overload2_Good() { char* mem = (char*)malloc(sizeof(my_class2)); my_class2* x = new (mem, DummyClass{}) my_class2(); x->a[0] = 0; } void placement_new_overload2_Bad() { char* mem = (char*)malloc(sizeof(my_class2)); my_class2* x = new (mem, DummyClass{}) my_class2(); x->a[10] = 0; } struct DummyStruct {}; inline void* operator new(std::size_t, DummyStruct, void* p) { return p; } inline void* operator new(std::size_t, void* p, DummyStruct) { return p; } void placement_new_overload3_Good() { char* mem = (char*)malloc(sizeof(my_class2)); my_class2* x = new (DummyStruct{}, mem) my_class2(); x->a[0] = 0; } void placement_new_overload4_Good() { char* mem = (char*)malloc(sizeof(my_class2)); my_class2* x = new (mem, DummyStruct{}) my_class2(); x->a[0] = 0; } struct Allocator { void* allocate(std::size_t size) { return malloc(size); } }; void* operator new(std::size_t size, Allocator& allocator) { return allocator.allocate(size); } void user_defined_new_Bad_FN() { Allocator allocator; my_class2* x = new (allocator) my_class2(); x->a[10] = 0; } class my_class4 { public: int a[3]; int c[3]; int b[1]; }; void flexible_array1_Good() { char* mem = (char*)malloc(sizeof(my_class4) + 4 * sizeof(int)); my_class4* x = new (mem) my_class4(); x->b[4] = 0; } void flexible_array1_Bad() { char* mem = (char*)malloc(sizeof(my_class4) + 4 * sizeof(int)); my_class4* x = new (mem) my_class4(); x->b[5] = 0; } void flexible_array2_Bad_FN() { char* mem = (char*)malloc(4 * sizeof(int) + sizeof(my_class4)); my_class4* x = new (mem) my_class4(); x->b[5] = 0; } void flexible_array3_Bad_FN() { char* mem = (char*)malloc(sizeof(my_class4) + sizeof(int) * 4); my_class4* x = new (mem) my_class4(); x->b[5] = 0; } void* operator new(std::size_t s1, std::size_t s2) { return malloc(s1 + s2); } void* operator new(std::size_t s1, std::size_t s2, bool) { return malloc(s1 + s2); } void flexible_array_new_overload1_Good() { my_class4* x = new (5 * sizeof(int)) my_class4(); x->b[5] = 0; } void flexible_array_new_overload1_Bad() { my_class4* x = new (5 * sizeof(int)) my_class4(); x->b[10] = 0; } void flexible_array_new_overload2_Good() { my_class4* x = new (5 * sizeof(int), true) my_class4(); x->b[5] = 0; } void flexible_array_new_overload2_Bad() { my_class4* x = new (5 * sizeof(int), true) my_class4(); x->b[10] = 0; } class my_class5 { public: int d[3]; int f[3]; my_class4 e; }; void flexible_array4_Good() { char* mem = (char*)malloc(sizeof(my_class5) + 4 * sizeof(int)); my_class5* x = new (mem) my_class5(); x->e.b[4] = 0; } void flexible_array4_Bad() { char* mem = (char*)malloc(sizeof(my_class5) + 4 * sizeof(int)); my_class5* x = new (mem) my_class5(); x->e.b[5] = 0; } class Tree { private: unsigned int children_num; Tree(unsigned int children_num) : children_num(children_num) {} public: void set_child(Tree* child, unsigned int nth) { children[nth] = child; } static Tree* NewNode(unsigned int children_num) { char* mem = (char*)malloc(sizeof(Tree) + (children_num - 1) * sizeof(Tree*)); return new (mem) Tree(children_num); } static Tree* NewLeaf() { return new Tree(0); } private: Tree* children[1]; }; void flexible_array5_Good() { Tree* t = Tree::NewNode(3); t->set_child(Tree::NewLeaf(), 0); t->set_child(Tree::NewLeaf(), 1); t->set_child(Tree::NewLeaf(), 2); } void flexible_array5_Bad() { Tree* t = Tree::NewNode(3); t->set_child(Tree::NewLeaf(), 5); } void flexible_array_param_access(my_class4* x) { x->b[3] = 0; } void flexible_array_param_Good() { my_class4* x = (my_class4*)malloc(sizeof(my_class4) + 4 * sizeof(int)); flexible_array_param_access(x); } void flexible_array_param_Bad() { my_class4* x = (my_class4*)malloc(sizeof(my_class4) + 2 * sizeof(int)); flexible_array_param_access(x); } char* my_malloc() { return (char*)malloc(sizeof(my_class4) + 4 * sizeof(int)); } void return_class_Good() { my_class4* x = (my_class4*)my_malloc(); x->b[3] = 0; } void return_class_Bad() { my_class4* x = (my_class4*)my_malloc(); x->b[5] = 0; } struct S { static constexpr unsigned int x = 32; }; void use_global_Good() { int a[50]; a[S::x] = 0; } void use_global_Bad() { int a[30]; a[S::x] = 0; }