Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/llvm/llvm-project.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2019-04-05 23:38:43 +0300
committerEric Fiselier <eric@efcs.ca>2019-04-05 23:38:43 +0300
commitc4225e124f9e11bb8411c4d8be70a01b449ffc12 (patch)
tree6d8ace3c5424987420613a77273b1e2c3f83bc5d /libcxxabi/src/cxa_vector.cpp
parent944c20c05b83796bc4c847e7a0a18ebd8e955501 (diff)
Fix PR41395 - __cxa_vec_new may overflow in allocation size calculation.
llvm-svn: 357814
Diffstat (limited to 'libcxxabi/src/cxa_vector.cpp')
-rw-r--r--libcxxabi/src/cxa_vector.cpp56
1 files changed, 43 insertions, 13 deletions
diff --git a/libcxxabi/src/cxa_vector.cpp b/libcxxabi/src/cxa_vector.cpp
index 2d89787f4edd..418b40226cad 100644
--- a/libcxxabi/src/cxa_vector.cpp
+++ b/libcxxabi/src/cxa_vector.cpp
@@ -13,6 +13,9 @@
#include "cxxabi.h"
#include <exception> // for std::terminate
+#include <new> // for std::bad_alloc
+
+#include "abort_message.h"
namespace __cxxabiv1 {
@@ -107,6 +110,32 @@ namespace {
#pragma mark --Externally visible routines--
#endif
+namespace {
+_LIBCXXABI_NORETURN
+void throw_bad_array_new_length() {
+#ifndef _LIBCXXABI_NO_EXCEPTIONS
+ throw std::bad_array_new_length();
+#else
+ abort_message("__cxa_vec_new failed to allocate memory");
+#endif
+}
+
+size_t calculate_allocation_size_or_throw(size_t element_count,
+ size_t element_size,
+ size_t padding_size) {
+ const size_t element_heap_size = element_count * element_size;
+ if (element_heap_size / element_count != element_size)
+ throw_bad_array_new_length();
+
+ const size_t allocation_size = element_heap_size + padding_size;
+ if (allocation_size < element_heap_size)
+ throw_bad_array_new_length();
+
+ return allocation_size;
+}
+
+} // namespace
+
extern "C" {
// Equivalent to
@@ -121,7 +150,6 @@ __cxa_vec_new(size_t element_count, size_t element_size, size_t padding_size,
}
-
// Given the number and size of elements for an array and the non-negative
// size of prefix padding for a cookie, allocate space (using alloc) for
// the array preceded by the specified padding, initialize the cookie if
@@ -142,12 +170,13 @@ _LIBCXXABI_FUNC_VIS void *
__cxa_vec_new2(size_t element_count, size_t element_size, size_t padding_size,
void (*constructor)(void *), void (*destructor)(void *),
void *(*alloc)(size_t), void (*dealloc)(void *)) {
- const size_t heap_size = element_count * element_size + padding_size;
- char * const heap_block = static_cast<char *> ( alloc ( heap_size ));
- char *vec_base = heap_block;
-
- if ( NULL != vec_base ) {
- st_heap_block2 heap ( dealloc, heap_block );
+ const size_t heap_size = calculate_allocation_size_or_throw(
+ element_count, element_size, padding_size);
+ char* const heap_block = static_cast<char*>(alloc(heap_size));
+ char* vec_base = heap_block;
+
+ if (NULL != vec_base) {
+ st_heap_block2 heap(dealloc, heap_block);
// put the padding before the array elements
if ( 0 != padding_size ) {
@@ -170,12 +199,13 @@ _LIBCXXABI_FUNC_VIS void *
__cxa_vec_new3(size_t element_count, size_t element_size, size_t padding_size,
void (*constructor)(void *), void (*destructor)(void *),
void *(*alloc)(size_t), void (*dealloc)(void *, size_t)) {
- const size_t heap_size = element_count * element_size + padding_size;
- char * const heap_block = static_cast<char *> ( alloc ( heap_size ));
- char *vec_base = heap_block;
-
- if ( NULL != vec_base ) {
- st_heap_block3 heap ( dealloc, heap_block, heap_size );
+ const size_t heap_size = calculate_allocation_size_or_throw(
+ element_count, element_size, padding_size);
+ char* const heap_block = static_cast<char*>(alloc(heap_size));
+ char* vec_base = heap_block;
+
+ if (NULL != vec_base) {
+ st_heap_block3 heap(dealloc, heap_block, heap_size);
// put the padding before the array elements
if ( 0 != padding_size ) {