浏览代码

reallocarray introduction available on glibc 2.26. allocates an array of m*n elements but checking for overflow.

David Carlier 2 年之前
父节点
当前提交
3fe37e36fa
共有 3 个文件被更改,包括 34 次插入0 次删除
  1. 16 0
      src/header/stdlib/mod.rs
  2. 2 0
      tests/expected/bins_static/stdlib/alloc.stdout
  3. 16 0
      tests/stdlib/alloc.c

+ 16 - 0
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() {

+ 2 - 0
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

+ 16 - 0
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);