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: stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14}}
13
14#include "cxxabi.h"
15#include <new>
16#include <cassert>
17
18void dummy_ctor(void*) { assert(false && "should not be called"); }
19void dummy_dtor(void*) { assert(false && "should not be called"); }
20
21void *dummy_alloc(size_t) { assert(false && "should not be called"); return nullptr; }
22void dummy_dealloc(void*) { assert(false && "should not be called"); }
23void dummy_dealloc_sized(void*, size_t) { assert(false && "should not be called"); }
24
25
26bool 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
33bool 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
41void 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(element_count: elem_count, element_size: elem_size, padding_size: padding, constructor: dummy_ctor,
49 destructor: 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(element_count: elem_count, element_size: elem_size, padding_size: padding, constructor: dummy_ctor,
59 destructor: dummy_dtor, alloc: &dummy_alloc, dealloc: &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(element_count: elem_count, element_size: elem_size, padding_size: padding, constructor: dummy_ctor,
69 destructor: dummy_dtor, alloc: &dummy_alloc, dealloc: &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
78void 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(element_count: elem_count, element_size: elem_size, padding_size: padding, constructor: dummy_ctor,
90 destructor: 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(element_count: elem_count, element_size: elem_size, padding_size: padding, constructor: dummy_ctor,
101 destructor: dummy_dtor, alloc: &dummy_alloc, dealloc: &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(element_count: elem_count, element_size: elem_size, padding_size: padding, constructor: dummy_ctor,
111 destructor: dummy_dtor, alloc: &dummy_alloc, dealloc: &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
120int main(int, char**) {
121 test_overflow_in_multiplication();
122 test_overflow_in_addition();
123
124 return 0;
125}
126

source code of libcxxabi/test/cxa_vec_new_overflow_PR41395.pass.cpp