Improve zero-size allocation with safe_malloc, etc.
authorXing Xue <xingxue@outlook.com>
Tue, 25 Jun 2019 15:08:28 +0000 (15:08 +0000)
committerXing Xue <xingxue@outlook.com>
Tue, 25 Jun 2019 15:08:28 +0000 (15:08 +0000)
Summary:
The current implementations of the memory allocation functions mistake a nullptr returned from std::malloc, std::calloc, or std::realloc as a failure. The behaviour for each of std::malloc, std::calloc, and std::realloc when the size is 0 is implementation defined (ISO/IEC 9899:2018 7.22.3), and may return a nullptr.

This patch checks if space requested is zero when a nullptr is returned, retry requesting non-zero if it is.

Authored By: andusy

Reviewers: hubert.reinterpretcast, xingxue, jasonliu

Reviewed By: hubert.reinterpretcast, xingxue, abrachet

Subscribers: abrachet, jsji, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D63668

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@364322 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/MemAlloc.h

index ed076ffa52d6012c42f7fbf487aae59571ba7693..0e5869141fd3d9b7f34464197e52f446917d1dc0 100644 (file)
@@ -24,23 +24,41 @@ namespace llvm {
 
 LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_malloc(size_t Sz) {
   void *Result = std::malloc(Sz);
-  if (Result == nullptr)
+  if (Result == nullptr) {
+    // It is implementation-defined whether allocation occurs if the space
+    // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting
+    // non-zero, if the space requested was zero.
+    if (Sz == 0)
+      return safe_malloc(1);
     report_bad_alloc_error("Allocation failed");
+  }
   return Result;
 }
 
 LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_calloc(size_t Count,
                                                         size_t Sz) {
   void *Result = std::calloc(Count, Sz);
-  if (Result == nullptr)
+  if (Result == nullptr) {
+    // It is implementation-defined whether allocation occurs if the space
+    // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting
+    // non-zero, if the space requested was zero.
+    if (Count == 0 || Sz == 0)
+      return safe_malloc(1);
     report_bad_alloc_error("Allocation failed");
+  }
   return Result;
 }
 
 LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_realloc(void *Ptr, size_t Sz) {
   void *Result = std::realloc(Ptr, Sz);
-  if (Result == nullptr)
+  if (Result == nullptr) {
+    // It is implementation-defined whether allocation occurs if the space
+    // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting
+    // non-zero, if the space requested was zero.
+    if (Sz == 0)
+      return safe_malloc(1);
     report_bad_alloc_error("Allocation failed");
+  }
   return Result;
 }