Просмотр исходного кода

Merge branch 'contrib/github_pr_9517' into 'master'

fix malloc(0) and heap_caps_alloc_failed() (GitHub PR)

Closes IDFGH-8007

See merge request espressif/esp-idf!19421
Omar Chebib 3 лет назад
Родитель
Сommit
d622bcfd46
2 измененных файлов с 41 добавлено и 11 удалено
  1. 19 11
      components/heap/heap_caps.c
  2. 22 0
      components/heap/test/test_malloc.c

+ 19 - 11
components/heap/heap_caps.c

@@ -62,9 +62,9 @@ static void heap_caps_alloc_failed(size_t requested_size, uint32_t caps, const c
         alloc_failed_callback(requested_size, caps, function_name);
     }
 
-    #ifdef CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS
+#ifdef CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS
     esp_system_abort("Memory allocation failed");
-    #endif
+#endif
 }
 
 esp_err_t heap_caps_register_failed_alloc_callback(esp_alloc_failed_hook_t callback)
@@ -92,6 +92,10 @@ IRAM_ATTR static void *heap_caps_malloc_base( size_t size, uint32_t caps)
 {
     void *ret = NULL;
 
+    if (size == 0) {
+        return NULL;
+    }
+
     if (size > HEAP_SIZE_MAX) {
         // Avoids int overflow when adding small numbers to size, or
         // calculating 'end' from start+size, by limiting 'size' to the possible range
@@ -161,7 +165,7 @@ IRAM_ATTR void *heap_caps_malloc( size_t size, uint32_t caps){
 
     void* ptr = heap_caps_malloc_base(size, caps);
 
-    if (!ptr){
+    if (!ptr && size > 0){
         heap_caps_alloc_failed(size, caps, __func__);
     }
 
@@ -196,13 +200,13 @@ IRAM_ATTR void *heap_caps_malloc_default( size_t size )
         } else {
             r=heap_caps_malloc_base( size, MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM );
         }
-        if (r==NULL) {
+        if (r==NULL && size > 0) {
             //try again while being less picky
             r=heap_caps_malloc_base( size, MALLOC_CAP_DEFAULT );
         }
 
         // allocation failure?
-        if (r==NULL){
+        if (r==NULL && size > 0){
             heap_caps_alloc_failed(size, MALLOC_CAP_DEFAULT, __func__);
         }
 
@@ -255,11 +259,11 @@ IRAM_ATTR void *heap_caps_malloc_prefer( size_t size, size_t num, ... )
     while (num--) {
         caps = va_arg( argp, uint32_t );
         r = heap_caps_malloc_base( size, caps );
-        if (r != NULL) {
+        if (r != NULL || size == 0) {
             break;
         }
     }
-    if (r == NULL){
+    if (r == NULL && size > 0){
         heap_caps_alloc_failed(size, caps, __func__);
     }
     va_end( argp );
@@ -282,7 +286,7 @@ IRAM_ATTR void *heap_caps_realloc_prefer( void *ptr, size_t size, size_t num, ..
             break;
         }
     }
-    if (r == NULL){
+    if (r == NULL && size > 0){
         heap_caps_alloc_failed(size, caps, __func__);
     }
     va_end( argp );
@@ -301,11 +305,11 @@ IRAM_ATTR void *heap_caps_calloc_prefer( size_t n, size_t size, size_t num, ...
     while (num--) {
         caps = va_arg( argp, uint32_t );
         r = heap_caps_calloc_base( n, size, caps );
-        if (r != NULL){
+        if (r != NULL || size == 0){
             break;
         }
     }
-    if (r == NULL){
+    if (r == NULL && size > 0){
         heap_caps_alloc_failed(size, caps, __func__);
     }
     va_end( argp );
@@ -462,7 +466,7 @@ IRAM_ATTR void *heap_caps_calloc( size_t n, size_t size, uint32_t caps)
 {
     void* ptr = heap_caps_calloc_base(n, size, caps);
 
-    if (!ptr){
+    if (!ptr && size > 0){
         heap_caps_alloc_failed(size, caps, __func__);
     }
 
@@ -624,6 +628,10 @@ IRAM_ATTR void *heap_caps_aligned_alloc(size_t alignment, size_t size, uint32_t
         return NULL;
     }
 
+    if (size == 0) {
+        return NULL;
+    }
+
     if (size > HEAP_SIZE_MAX) {
         // Avoids int overflow when adding small numbers to size, or
         // calculating 'end' from start+size, by limiting 'size' to the possible range

+ 22 - 0
components/heap/test/test_malloc.c

@@ -132,3 +132,25 @@ TEST_CASE("malloc(0) should return a NULL pointer", "[heap]")
     p = malloc(0);
     TEST_ASSERT(p == NULL);
 }
+
+static bool failure_occured = false;
+
+static void test_alloc_failure_callback(size_t size, uint32_t caps, const char * function_name)
+{
+    failure_occured = true;
+}
+
+TEST_CASE("malloc/calloc(0) should not call failure callback", "[heap]")
+{
+    void* ptr = NULL;
+    esp_err_t ret = heap_caps_register_failed_alloc_callback(test_alloc_failure_callback);
+    TEST_ASSERT(ret == ESP_OK);
+    ptr = malloc(0);
+    TEST_ASSERT_NULL(ptr);
+    /* Check that our callback was NOT called */
+    TEST_ASSERT_FALSE(failure_occured);
+    /* Do the same thing for calloc */
+    ptr = calloc(0, 0);
+    TEST_ASSERT_NULL(ptr);
+    TEST_ASSERT_FALSE(failure_occured);
+}