From 3fe37e36faa6c76dd0e4b5051a9a59ec6a0bc140 Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen@gmail.com>
Date: Sun, 26 Mar 2023 08:33:30 +0100
Subject: [PATCH] reallocarray introduction available on glibc 2.26. allocates
 an array of m*n elements but checking for overflow.

---
 src/header/stdlib/mod.rs                       | 16 ++++++++++++++++
 tests/expected/bins_static/stdlib/alloc.stdout |  2 ++
 tests/stdlib/alloc.c                           | 16 ++++++++++++++++
 3 files changed, 34 insertions(+)

diff --git a/src/header/stdlib/mod.rs b/src/header/stdlib/mod.rs
index ee39ae05..59d6de50 100644
--- a/src/header/stdlib/mod.rs
+++ b/src/header/stdlib/mod.rs
@@ -812,6 +812,22 @@ pub unsafe extern "C" fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void
     new_ptr
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn reallocarray(ptr: *mut c_void, m: size_t, n: size_t) -> *mut c_void {
+    //Handle possible integer overflow in size calculation
+    match m.checked_mul(n) {
+        Some(size) => {
+            realloc(ptr, size)
+        }
+        None => {
+            // For overflowing multiplication, we have to set errno here
+            platform::errno = ENOMEM;
+            ptr::null_mut()
+
+        }
+    }
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn realpath(pathname: *const c_char, resolved: *mut c_char) -> *mut c_char {
     let ptr = if resolved.is_null() {
diff --git a/tests/expected/bins_static/stdlib/alloc.stdout b/tests/expected/bins_static/stdlib/alloc.stdout
index e59a48d0..02ecd201 100644
--- a/tests/expected/bins_static/stdlib/alloc.stdout
+++ b/tests/expected/bins_static/stdlib/alloc.stdout
@@ -7,6 +7,8 @@ calloc (overflowing): pointer: (nil), error value: 12 = Out of memory
 realloc (size 0): (OK)
 realloc: pointer: (not NULL), error value: 0 = Success
 realloc (SIZE_MAX): pointer: (nil), error value: 12 = Out of memory
+reallocarray: pointer: (not NULL), error value: 0 = Success
+reallocarray (SIZE_MAX): pointer: (nil), error value: 12 = Out of memory
 memalign (size 0): (OK)
 memalign: pointer: (alignment OK), error value: 0 = Success
 memalign (SIZE_MAX): pointer: (nil), error value: 12 = Out of memory
diff --git a/tests/stdlib/alloc.c b/tests/stdlib/alloc.c
index 36660363..f15149b5 100644
--- a/tests/stdlib/alloc.c
+++ b/tests/stdlib/alloc.c
@@ -165,6 +165,22 @@ int main(void) {
     printf("realloc (SIZE_MAX): ");
     test_cannot_alloc(ptr_realloc_maxsize, realloc_maxsize_errno);
     free(ptr_realloc_maxsize);
+
+    errno = 0;
+    char * ptr_reallocarray_maxsize = (char *)malloc(sample_alloc_size);
+    ptr_reallocarray_maxsize = (char *)reallocarray(ptr_reallocarray_maxsize, 2, sample_alloc_size);
+    int reallocarray_errno = errno;
+    printf("reallocarray: ");
+    test_non_null(ptr_reallocarray_maxsize, reallocarray_errno);
+    for(i = 0; i < sample_realloc_size; i++) {
+        ptr_realloc[i] = (char)i;
+    }
+    errno = 0;
+    ptr_reallocarray_maxsize = (char *)reallocarray(ptr_reallocarray_maxsize, 2, max_size);
+    reallocarray_errno = errno;
+    printf("reallocarray (SIZE_MAX): ");
+    test_cannot_alloc(ptr_reallocarray_maxsize, reallocarray_errno);
+    free(ptr_reallocarray_maxsize);
     
     errno = 0;
     char * ptr_memalign_size0 = (char *)memalign(aligned_alloc_alignment, zero_size);
-- 
GitLab