Jelajahi Sumber

REVIEWED: Avoid realloc() calls, small security improvement

Ray 2 minggu lalu
induk
melakukan
1777da9056
4 mengubah file dengan 39 tambahan dan 25 penghapusan
  1. 10 9
      src/rcore.c
  2. 14 4
      src/rmodels.c
  3. 10 6
      src/rtext.c
  4. 5 6
      src/rtextures.c

+ 10 - 9
src/rcore.c

@@ -2562,19 +2562,20 @@ unsigned char *DecompressData(const unsigned char *compData, int compDataSize, i
 
 #if defined(SUPPORT_COMPRESSION_API)
     // Decompress data from a valid DEFLATE stream
-    data = (unsigned char *)RL_CALLOC(MAX_DECOMPRESSION_SIZE*1024*1024, 1);
+    unsigned char *data0 = (unsigned char *)RL_CALLOC(MAX_DECOMPRESSION_SIZE*1024*1024, 1);
     int length = sinflate(data, MAX_DECOMPRESSION_SIZE*1024*1024, compData, compDataSize);
 
-    // WARNING: RL_REALLOC can make (and leave) data copies in memory, be careful with sensitive compressed data!
-    // TODO: Use a different approach, create another buffer, copy data manually to it and wipe original buffer memory
-    unsigned char *temp = (unsigned char *)RL_REALLOC(data, length);
-
-    if (temp != NULL) data = temp;
-    else TRACELOG(LOG_WARNING, "SYSTEM: Failed to re-allocate required decompression memory");
+    // WARNING: RL_REALLOC can make (and leave) data copies in memory, 
+    // that can be a security concern in case of compression of sensitive data
+    // So, we use a second buffer to copy data manually, wiping original buffer memory
+    data = (unsigned char *)RL_CALLOC(length, 1);
+    memcpy(data, data0, length);
+    memset(data0, 0, MAX_DECOMPRESSION_SIZE*1024*1024); // Wipe memory, is memset() safe?
+    RL_FREE(data0);
+    
+    TRACELOG(LOG_INFO, "SYSTEM: Decompress data: Comp. size: %i -> Original size: %i", compDataSize, length);
 
     *dataSize = length;
-
-    TRACELOG(LOG_INFO, "SYSTEM: Decompress data: Comp. size: %i -> Original size: %i", compDataSize, *dataSize);
 #endif
 
     return data;

+ 14 - 4
src/rmodels.c

@@ -6573,13 +6573,23 @@ static Model LoadM3D(const char *fileName)
             // Materials are grouped together
             if (mi != m3d->face[i].materialid)
             {
-                // there should be only one material switch per material kind, but be bulletproof for non-optimal model files
+                // There should be only one material switch per material kind,
+                // but be bulletproof for non-optimal model files
                 if (k + 1 >= model.meshCount)
                 {
                     model.meshCount++;
-                    model.meshes = (Mesh *)RL_REALLOC(model.meshes, model.meshCount*sizeof(Mesh));
-                    memset(&model.meshes[model.meshCount - 1], 0, sizeof(Mesh));
-                    model.meshMaterial = (int *)RL_REALLOC(model.meshMaterial, model.meshCount*sizeof(int));
+                    
+                    // Create a second buffer for mesh re-allocation
+                    Mesh *tempMeshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
+                    memcpy(tempMeshes, model.meshes, (model.meshCount - 1)*sizeof(Mesh));
+                    RL_FREE(model.meshes);
+                    model.meshes = tempMeshes;
+
+                    // Create a second buffer for material re-allocation
+                    int *tempMeshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
+                    memcpy(tempMeshMaterial, model.meshMaterial, (model.meshCount - 1)*sizeof(int));
+                    RL_FREE(model.meshMaterial);
+                    model.meshMaterial = tempMeshMaterial;
                 }
 
                 k++;

+ 10 - 6
src/rtext.c

@@ -1920,10 +1920,11 @@ char *LoadUTF8(const int *codepoints, int length)
         size += bytes;
     }
 
-    // Resize memory to text length + string NULL terminator
-    void *ptr = RL_REALLOC(text, size + 1);
-
-    if (ptr != NULL) text = (char *)ptr;
+    // Create second buffer and copy data manually to it
+    char *temp = (char *)RL_CALLOC(size + 1, 1);
+    memcpy(temp, text, size);
+    RL_FREE(text);
+    text = temp;
 
     return text;
 }
@@ -1951,8 +1952,11 @@ int *LoadCodepoints(const char *text, int *count)
         i += codepointSize;
     }
 
-    // Re-allocate buffer to the actual number of codepoints loaded
-    codepoints = (int *)RL_REALLOC(codepoints, codepointCount*sizeof(int));
+    // Create second buffer and copy data manually to it
+    int *temp = (int *)RL_CALLOC(codepointCount, sizeof(int));
+    for (int i = 0; i < codepointCount; i++) temp[i] = codepoints[i];
+    RL_FREE(codepoints);
+    codepoints = temp;
 
     *count = codepointCount;
 

+ 5 - 6
src/rtextures.c

@@ -2400,10 +2400,11 @@ void ImageMipmaps(Image *image)
 
     if (image->mipmaps < mipCount)
     {
-        void *temp = RL_REALLOC(image->data, mipSize);
-
-        if (temp != NULL) image->data = temp;      // Assign new pointer (new size) to store mipmaps data
-        else TRACELOG(LOG_WARNING, "IMAGE: Mipmaps required memory could not be allocated");
+        // Create second buffer and copy data manually to it
+        void *temp = RL_CALLOC(mipSize, 1);
+        memcpy(temp, image->data, GetPixelDataSize(image->width, image->height, image->format));
+        RL_FREE(image->data);
+        image->data = temp;
 
         // Pointer to allocated memory point where store next mipmap level data
         unsigned char *nextmip = image->data;
@@ -2429,9 +2430,7 @@ void ImageMipmaps(Image *image)
             if (i < image->mipmaps) continue;
 
             TRACELOGD("IMAGE: Generating mipmap level: %i (%i x %i) - size: %i - offset: 0x%x", i, mipWidth, mipHeight, mipSize, nextmip);
-
             ImageResize(&imCopy, mipWidth, mipHeight); // Uses internally Mitchell cubic downscale filter
-
             memcpy(nextmip, imCopy.data, mipSize);
         }