Avoid memory allocation in EnumSymbols for small buffers
authorFilip Navara <filip.navara@gmail.com>
Sun, 3 Feb 2019 02:37:19 +0000 (03:37 +0100)
committerFilip Navara <filip.navara@gmail.com>
Sun, 3 Feb 2019 10:18:03 +0000 (11:18 +0100)
Commit migrated from https://github.com/dotnet/coreclr/commit/91df8d26a01cc50672ac4f7f71359cd19e8e2db2

src/coreclr/src/corefx/System.Globalization.Native/pal_calendarData.c

index 8e14d8b..12b735d 100644 (file)
@@ -319,39 +319,44 @@ bool EnumSymbols(const char* locale,
     udat_setCalendar(pFormat, pCalendar);
 
     int32_t symbolCount = udat_countSymbols(pFormat, type);
+    UChar stackSymbolBuf[100];
+    UChar* symbolBuf;
 
-    for (int32_t i = startIndex; i < symbolCount; i++)
+    for (int32_t i = startIndex; U_SUCCESS(err) && i < symbolCount; i++)
     {
         UErrorCode ignore = U_ZERO_ERROR;
         int symbolLen = udat_getSymbols(pFormat, type, i, NULL, 0, &ignore) + 1;
 
-        UChar* symbolBuf = calloc(symbolLen, sizeof(UChar));
-        if (symbolBuf == NULL)
+        if (symbolLen <= sizeof(stackSymbolBuf) / sizeof(stackSymbolBuf[0]))
         {
-            udat_close(pFormat);
-            ucal_close(pCalendar);
-            return false;
+            symbolBuf = stackSymbolBuf;
+        }
+        else
+        {
+            symbolBuf = calloc(symbolLen, sizeof(UChar));
+            if (symbolBuf == NULL)
+            {
+                err = U_MEMORY_ALLOCATION_ERROR;
+                break;
+            }
         }
 
         udat_getSymbols(pFormat, type, i, symbolBuf, symbolLen, &err);
 
-        assert(U_SUCCESS(err));
+        if (U_SUCCESS(err))
+        {
+            callback(symbolBuf, context);
+        }
 
-        if (U_FAILURE(err))
+        if (symbolBuf != stackSymbolBuf)
         {
-            udat_close(pFormat);
-            ucal_close(pCalendar);
             free(symbolBuf);
-            return false;
         }
-
-        callback(symbolBuf, context);
-        free(symbolBuf);
     }
 
     udat_close(pFormat);
     ucal_close(pCalendar);
-    return true;
+    return U_SUCCESS(err);
 }
 
 bool EnumUResourceBundle(const UResourceBundle* bundle, EnumCalendarInfoCallback callback, const void* context)