REVIEWED: GetPixelDataSize(), avoid allocations >2GB - ROS: CLN-013

REVIEWED: `GenImageColor()`, `ImageRotate()`
This commit is contained in:
Ray 2026-07-11 16:42:57 +02:00
commit cfe56d97ea
2 changed files with 61 additions and 42 deletions

View file

@ -5236,7 +5236,9 @@ static int rlGetPixelDataSize(int width, int height, int format)
{ {
int blockWidth = (width + 3)/4; int blockWidth = (width + 3)/4;
int blockHeight = (height + 3)/4; int blockHeight = (height + 3)/4;
dataSize = blockWidth*blockHeight*8; unsigned long long dataSizeBytes = blockWidth*blockHeight*8;
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
} break; } break;
case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA:
case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA: case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA:
@ -5245,13 +5247,17 @@ static int rlGetPixelDataSize(int width, int height, int format)
{ {
int blockWidth = (width + 3)/4; int blockWidth = (width + 3)/4;
int blockHeight = (height + 3)/4; int blockHeight = (height + 3)/4;
dataSize = blockWidth*blockHeight*16; unsigned long long dataSizeBytes = blockWidth*blockHeight*16;
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
} break; } break;
case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 4 bytes per each 4x4 block case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 4 bytes per each 4x4 block
{ {
int blockWidth = (width + 3)/4; int blockWidth = (width + 3)/4;
int blockHeight = (height + 3)/4; int blockHeight = (height + 3)/4;
dataSize = blockWidth*blockHeight*4; unsigned long long dataSizeBytes = blockWidth*blockHeight*4;
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
} break; } break;
default: break; default: break;
} }
@ -5260,10 +5266,12 @@ static int rlGetPixelDataSize(int width, int height, int format)
if ((format >= RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) && if ((format >= RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) &&
(format <= RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16)) (format <= RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16))
{ {
double bytesPerPixel = (double)bpp/8.0; unsigned long long dataSizeBytes = (width*height*bpp) >> 3; // Get size in bytes (dividing by 8)
dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
} }
if (dataSize == 0) TRACELOG(LOG_WARNING, "Requested image size is larger than 2GB, it can not be allocated");
return dataSize; return dataSize;
} }

View file

@ -843,9 +843,10 @@ bool ExportImageAsCode(Image image, const char *fileName)
// Generate image: plain color // Generate image: plain color
Image GenImageColor(int width, int height, Color color) Image GenImageColor(int width, int height, Color color)
{ {
Color *pixels = (Color *)RL_CALLOC(width*height, sizeof(Color)); int dataSize = GetPixelDataSize(width, height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8);
Color *pixels = (Color *)RL_CALLOC(dataSize, 1);
for (int i = 0; i < width*height; i++) pixels[i] = color; for (int i = 0; (pixels != NULL) && (i < width*height); i++) pixels[i] = color;
Image image = { Image image = {
.data = pixels, .data = pixels,
@ -2691,9 +2692,11 @@ void ImageRotate(Image *image, int degrees)
int width = (int)(fabsf(image->width*cosRadius) + fabsf(image->height*sinRadius)); int width = (int)(fabsf(image->width*cosRadius) + fabsf(image->height*sinRadius));
int height = (int)(fabsf(image->height*cosRadius) + fabsf(image->width*sinRadius)); int height = (int)(fabsf(image->height*cosRadius) + fabsf(image->width*sinRadius));
int bytesPerPixel = GetPixelDataSize(1, 1, image->format); int bytesPerPixel = GetPixelDataSize(width, height, image->format);
unsigned char *rotatedData = (unsigned char *)RL_CALLOC(width*height, bytesPerPixel); unsigned char *rotatedData = (unsigned char *)RL_CALLOC(bytesPerPixel, 1);
if (rotatedData != NULL)
{
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
@ -2731,6 +2734,7 @@ void ImageRotate(Image *image, int degrees)
image->width = width; image->width = width;
image->height = height; image->height = height;
} }
}
} }
// Rotate image clockwise 90deg // Rotate image clockwise 90deg
@ -5509,8 +5513,11 @@ int GetPixelDataSize(int width, int height, int format)
default: break; default: break;
} }
double bytesPerPixel = (double)bpp/8.0; unsigned long long dataSizeBytes = (width*height*bpp) >> 3; // Get size in bytes (dividing by 8)
dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes
if (dataSizeBytes < INT_MAX)
{
dataSize = (int)dataSizeBytes;
// Most compressed formats works on 4x4 blocks, // Most compressed formats works on 4x4 blocks,
// if texture is smaller, minimum dataSize is 8 or 16 // if texture is smaller, minimum dataSize is 8 or 16
@ -5519,6 +5526,10 @@ int GetPixelDataSize(int width, int height, int format)
if ((format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8; if ((format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8;
else if ((format >= PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16; else if ((format >= PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16;
} }
}
// NOTE: In case required image data larger than 2GB, no memory allocated at all (NULL)
if (dataSize == 0) TRACELOG(LOG_WARNING, "Requested image size is larger than 2GB, it can not be allocated");
return dataSize; return dataSize;
} }