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