From d64d0eb9e10691d02bced345ec95c3b3417118a7 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Mon, 20 Apr 2020 22:47:22 +1000 Subject: [PATCH] Fix game crashing if using default.png with width < 16 or non power of two --- src/Drawer2D.c | 26 ++++++++++++++++++++------ src/Drawer2D.h | 2 +- src/Launcher.c | 6 ++++-- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/Drawer2D.c b/src/Drawer2D.c index 3a04d4285..5c5df0205 100644 --- a/src/Drawer2D.c +++ b/src/Drawer2D.c @@ -109,9 +109,6 @@ static void CalculateTextWidths(void) { BitmapCol* row; int i, x, y, xx, tileX, tileY; - /* If 128x256 font bitmap is supplied, treat it as 128x128 */ - height = min(width, height); - for (y = 0; y < height; y++) { tileY = y / tileSize; row = Bitmap_GetRow(&fontBitmap, y); @@ -139,11 +136,27 @@ static void FreeFontBitmap(void) { Mem_Free(fontBitmap.Scan0); } -void Drawer2D_SetFontBitmap(Bitmap* bmp) { +cc_bool Drawer2D_SetFontBitmap(Bitmap* bmp) { + /* If all these cases are not accounted for, end up overwriting memory after tileWidths */ + if (bmp->Width != bmp->Height) { + static const String msg = String_FromConst("&cWidth of default.png must equal its height"); + Logger_WarnFunc(&msg); + return false; + } else if (bmp->Width < 16) { + static const String msg = String_FromConst("&cdefault.png must be at least 16 pixels wide"); + Logger_WarnFunc(&msg); + return false; + } else if (!Math_IsPowOf2(bmp->Width)) { + static const String msg = String_FromConst("&cWidth of default.png must be a power of two"); + Logger_WarnFunc(&msg); + return false; + } + FreeFontBitmap(); fontBitmap = *bmp; tileSize = bmp->Width >> LOG2_CHARS_PER_ROW; CalculateTextWidths(); + return true; } void Font_ReducePadding(struct FontDesc* desc, int scale) { @@ -683,9 +696,10 @@ static void OnFileChanged(void* obj, struct Stream* src, const String* name) { if ((res = Png_Decode(&bmp, src))) { Logger_Warn2(res, "decoding", name); Mem_Free(bmp.Scan0); - } else { - Drawer2D_SetFontBitmap(&bmp); + } else if (Drawer2D_SetFontBitmap(&bmp)) { Event_RaiseVoid(&ChatEvents.FontChanged); + } else { + Mem_Free(bmp.Scan0); } } diff --git a/src/Drawer2D.h b/src/Drawer2D.h index 1c63cbc45..fc18d6d52 100644 --- a/src/Drawer2D.h +++ b/src/Drawer2D.h @@ -93,7 +93,7 @@ void Drawer2D_ReducePadding_Tex(struct Texture* tex, int point, int scale); void Drawer2D_ReducePadding_Height(int* height, int point, int scale); /* Sets the bitmap used for drawing bitmapped fonts. (i.e. default.png) */ /* The bitmap must be square and consist of a 16x16 tile layout. */ -void Drawer2D_SetFontBitmap(Bitmap* bmp); +cc_bool Drawer2D_SetFontBitmap(Bitmap* bmp); /* Gets the list of all supported system font names on this platform. */ void Font_GetNames(StringsBuffer* buffer); diff --git a/src/Launcher.c b/src/Launcher.c index 6fe35806e..bc2197f37 100644 --- a/src/Launcher.c +++ b/src/Launcher.c @@ -391,9 +391,11 @@ static cc_result Launcher_ProcessZipEntry(const String* path, struct Stream* dat if (res) { Logger_Warn(res, "decoding default.png"); return res; - } else { - Drawer2D_SetFontBitmap(&fontBmp); + } else if (Drawer2D_SetFontBitmap(&fontBmp)) { useBitmappedFont = !Options_GetBool(OPT_USE_CHAT_FONT, false); + } else { + Mem_Free(fontBmp.Scan0); + fontBmp.Scan0 = NULL; } } else if (String_CaselessEqualsConst(path, "terrain.png")) { if (dirtBmp.Scan0) return 0;