Skip to content

Commit 5a3391f

Browse files
authored
[rtext] Fix multiple security vulnerabilities in font loading (#5433, #5434, #5436) (#5450)
1 parent 909f040 commit 5a3391f

File tree

1 file changed

+41
-12
lines changed

1 file changed

+41
-12
lines changed

src/rtext.c

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -743,8 +743,14 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
743743
stbtt_GetCodepointHMetrics(&fontInfo, cp, &glyphs[k].advanceX, NULL);
744744
glyphs[k].advanceX = (int)((float)glyphs[k].advanceX*scaleFactor);
745745

746+
// [Security Fix] Prevent integer overflow/negative allocation
747+
// Issue #5436: Malicious font files may contain negative advanceX,
748+
// causing calloc overflow or crash
749+
if (glyphs[k].advanceX < 0) glyphs[k].advanceX = 0;
750+
746751
Image imSpace = {
747-
.data = RL_CALLOC(glyphs[k].advanceX*fontSize, 2),
752+
// Only allocate memory if width > 0, otherwise set to NULL
753+
.data = (glyphs[k].advanceX > 0) ? RL_CALLOC(glyphs[k].advanceX*fontSize, 2) : NULL,
748754
.width = glyphs[k].advanceX,
749755
.height = fontSize,
750756
.mipmaps = 1,
@@ -853,7 +859,8 @@ Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyp
853859
}
854860
#endif
855861

856-
atlas.data = (unsigned char *)RL_CALLOC(1, atlas.width*atlas.height); // Create a bitmap to store characters (8 bpp)
862+
int atlasDataSize = atlas.width * atlas.height; // Save total size for bounds checking
863+
atlas.data = (unsigned char *)RL_CALLOC(1, atlasDataSize); // Create a bitmap to store characters (8 bpp)
857864
atlas.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
858865
atlas.mipmaps = 1;
859866

@@ -898,7 +905,17 @@ Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyp
898905
{
899906
for (int x = 0; x < glyphs[i].image.width; x++)
900907
{
901-
((unsigned char *)atlas.data)[(offsetY + y)*atlas.width + (offsetX + x)] = ((unsigned char *)glyphs[i].image.data)[y*glyphs[i].image.width + x];
908+
int destX = offsetX + x;
909+
int destY = offsetY + y;
910+
911+
// Security fix: check both lower and upper bounds
912+
// destX >= 0: prevent heap underflow (#5434)
913+
// destX < atlas.width: prevent heap overflow (#5433)
914+
if (destX >= 0 && destX < atlas.width && destY >= 0 && destY < atlas.height)
915+
{
916+
((unsigned char *)atlas.data)[destY * atlas.width + destX] =
917+
((unsigned char *)glyphs[i].image.data)[y * glyphs[i].image.width + x];
918+
}
902919
}
903920
}
904921

@@ -946,7 +963,15 @@ Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyp
946963
{
947964
for (int x = 0; x < glyphs[i].image.width; x++)
948965
{
949-
((unsigned char *)atlas.data)[(rects[i].y + padding + y)*atlas.width + (rects[i].x + padding + x)] = ((unsigned char *)glyphs[i].image.data)[y*glyphs[i].image.width + x];
966+
int destX = rects[i].x + padding + x;
967+
int destY = rects[i].y + padding + y;
968+
969+
// Security fix: check both lower and upper bounds
970+
if (destX >= 0 && destX < atlas.width && destY >= 0 && destY < atlas.height)
971+
{
972+
((unsigned char *)atlas.data)[destY * atlas.width + destX] =
973+
((unsigned char *)glyphs[i].image.data)[y * glyphs[i].image.width + x];
974+
}
950975
}
951976
}
952977
}
@@ -960,14 +985,18 @@ Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyp
960985

961986
#if defined(SUPPORT_FONT_ATLAS_WHITE_REC)
962987
// Add a 3x3 white rectangle at the bottom-right corner of the generated atlas,
963-
// useful to use as the white texture to draw shapes with raylib, using this rectangle
964-
// shapes and text can be backed into a single draw call: SetShapesTexture()
965-
for (int i = 0, k = atlas.width*atlas.height - 1; i < 3; i++)
966-
{
967-
((unsigned char *)atlas.data)[k - 0] = 255;
968-
((unsigned char *)atlas.data)[k - 1] = 255;
969-
((unsigned char *)atlas.data)[k - 2] = 255;
970-
k -= atlas.width;
988+
// useful to use as the white texture to draw shapes with raylib.
989+
// [Security Fix] Ensure the atlas is large enough to hold a 3x3 rectangle.
990+
// This prevents heap underflow when width < 3 or height < 3 (Fixes #5434 variant)
991+
if (atlas.width >= 3 && atlas.height >= 3)
992+
{
993+
for (int i = 0, k = atlas.width*atlas.height - 1; i < 3; i++)
994+
{
995+
((unsigned char *)atlas.data)[k - 0] = 255;
996+
((unsigned char *)atlas.data)[k - 1] = 255;
997+
((unsigned char *)atlas.data)[k - 2] = 255;
998+
k -= atlas.width;
999+
}
9711000
}
9721001
#endif
9731002

0 commit comments

Comments
 (0)