1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: no-exceptions
10 
11 // PR41395 isn't fixed until the dylib shipped with macOS 10.15
12 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14}}
13 
14 #include "cxxabi.h"
15 #include <new>
16 #include <cassert>
17 
dummy_ctor(void *)18 void dummy_ctor(void*) { assert(false && "should not be called"); }
dummy_dtor(void *)19 void dummy_dtor(void*) { assert(false && "should not be called"); }
20 
dummy_alloc(size_t)21 void *dummy_alloc(size_t) { assert(false && "should not be called"); }
dummy_dealloc(void *)22 void dummy_dealloc(void*) { assert(false && "should not be called"); }
dummy_dealloc_sized(void *,size_t)23 void dummy_dealloc_sized(void*, size_t) { assert(false && "should not be called"); }
24 
25 
check_mul_overflows(size_t x,size_t y)26 bool check_mul_overflows(size_t x, size_t y) {
27   size_t tmp = x * y;
28   if (tmp / x != y)
29     return true;
30   return false;
31 }
32 
check_add_overflows(size_t x,size_t y)33 bool check_add_overflows(size_t x, size_t y) {
34   size_t tmp = x + y;
35   if (tmp < x)
36     return true;
37 
38   return false;
39 }
40 
test_overflow_in_multiplication()41 void test_overflow_in_multiplication() {
42   const size_t elem_count = std::size_t(1) << (sizeof(std::size_t) * 8 - 2);
43   const size_t elem_size = 8;
44   const size_t padding = 0;
45   assert(check_mul_overflows(elem_count, elem_size));
46 
47   try {
48     __cxxabiv1::__cxa_vec_new(elem_count, elem_size, padding, dummy_ctor,
49                               dummy_dtor);
50     assert(false && "allocation should fail");
51   } catch (std::bad_array_new_length const&) {
52     // OK
53   } catch (...) {
54     assert(false && "unexpected exception");
55   }
56 
57   try {
58     __cxxabiv1::__cxa_vec_new2(elem_count, elem_size, padding, dummy_ctor,
59                               dummy_dtor, &dummy_alloc, &dummy_dealloc);
60     assert(false && "allocation should fail");
61   } catch (std::bad_array_new_length const&) {
62     // OK
63   } catch (...) {
64     assert(false && "unexpected exception");
65   }
66 
67   try {
68     __cxxabiv1::__cxa_vec_new3(elem_count, elem_size, padding, dummy_ctor,
69                                dummy_dtor, &dummy_alloc, &dummy_dealloc_sized);
70     assert(false && "allocation should fail");
71   } catch (std::bad_array_new_length const&) {
72     // OK
73   } catch (...) {
74     assert(false && "unexpected exception");
75   }
76 }
77 
test_overflow_in_addition()78 void test_overflow_in_addition() {
79   const size_t elem_size = 4;
80   const size_t elem_count = static_cast<size_t>(-1) / 4u;
81 #if defined(_LIBCXXABI_ARM_EHABI)
82   const size_t padding = 8;
83 #else
84   const size_t padding = sizeof(std::size_t);
85 #endif
86   assert(!check_mul_overflows(elem_count, elem_size));
87   assert(check_add_overflows(elem_count * elem_size, padding));
88   try {
89     __cxxabiv1::__cxa_vec_new(elem_count, elem_size, padding, dummy_ctor,
90                               dummy_dtor);
91     assert(false && "allocation should fail");
92   } catch (std::bad_array_new_length const&) {
93     // OK
94   } catch (...) {
95     assert(false && "unexpected exception");
96   }
97 
98 
99   try {
100     __cxxabiv1::__cxa_vec_new2(elem_count, elem_size, padding, dummy_ctor,
101                                dummy_dtor, &dummy_alloc, &dummy_dealloc);
102     assert(false && "allocation should fail");
103   } catch (std::bad_array_new_length const&) {
104     // OK
105   } catch (...) {
106     assert(false && "unexpected exception");
107   }
108 
109   try {
110     __cxxabiv1::__cxa_vec_new3(elem_count, elem_size, padding, dummy_ctor,
111                                dummy_dtor, &dummy_alloc, &dummy_dealloc_sized);
112     assert(false && "allocation should fail");
113   } catch (std::bad_array_new_length const&) {
114     // OK
115   } catch (...) {
116     assert(false && "unexpected exception");
117   }
118 }
119 
main(int,char **)120 int main(int, char**) {
121   test_overflow_in_multiplication();
122   test_overflow_in_addition();
123 
124   return 0;
125 }
126