From fbc7fc130f14f116772d007acc9b1113abb5ee07 Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Sat, 20 Jun 2026 01:20:48 +0530 Subject: [PATCH] bound BMF block walk to buffer end --- modules/commodetto/cfeBMF.c | 45 ++++++++++++++++++------- modules/commodetto/commodettoParseBMF.c | 32 +++++++++++++----- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/modules/commodetto/cfeBMF.c b/modules/commodetto/cfeBMF.c index 7fead08a6f..b9558e2f2c 100644 --- a/modules/commodetto/cfeBMF.c +++ b/modules/commodetto/cfeBMF.c @@ -77,7 +77,7 @@ void CFELockCache(CommodettoFontEngine bmf, uint8_t lock) void CFESetFontData(CommodettoFontEngine bmf, const void *fontData, uint32_t fontDataSize) { - const unsigned char *bytes, *start; + const unsigned char *bytes, *start, *end; uint32_t size; uint8_t version; @@ -88,6 +88,10 @@ void CFESetFontData(CommodettoFontEngine bmf, const void *fontData, uint32_t fon start = fontData; bytes = start; + end = start + fontDataSize; + + if (fontDataSize < 5) + return; version = c_read8(bytes + 3); if ((0x42 != c_read8(bytes + 0)) || (0x4D != c_read8(bytes + 1)) || (0x46 != c_read8(bytes + 2)) || ((3 != version) && (4 != version))) @@ -102,15 +106,24 @@ void CFESetFontData(CommodettoFontEngine bmf, const void *fontData, uint32_t fon return; bytes += 1; - bytes += 4 + c_read32(bytes); + if ((end - bytes) < 4) + return; + size = c_read32(bytes); + if (size > (uint32_t)((end - bytes) - 4)) + return; + bytes += 4 + size; // get lineHeight from block 2 - if (2 != c_read8(bytes)) + if (((end - bytes) < 1) || (2 != c_read8(bytes))) return; bytes += 1; + if ((end - bytes) < 4) + return; size = c_read32(bytes); bytes += 4; + if (((end - bytes) < 10) || (size < 8) || (size > (uint32_t)(end - bytes))) + return; bmf->height = c_read16(bytes); bytes += 2; @@ -125,33 +138,41 @@ void CFESetFontData(CommodettoFontEngine bmf, const void *fontData, uint32_t fon bytes += size - 8; // skip block 3 - if (3 != c_read8(bytes)) + if (((end - bytes) < 1) || (3 != c_read8(bytes))) return; bytes += 1; - bytes += 4 + c_read32(bytes); + if ((end - bytes) < 4) + return; + size = c_read32(bytes); + if (size > (uint32_t)((end - bytes) - 4)) + return; + bytes += 4 + size; // use block 4 - if (4 != c_read8(bytes)) + if (((end - bytes) < 1) || (4 != c_read8(bytes))) return; bytes += 1; - bmf->charTable = bytes + 4; - bmf->isContinuous = (0x40 & c_read8(19 + bmf->charTable)) ? 1 : 0; - + if ((end - bytes) < 4) + return; size = c_read32(bytes); - if (size % 20) + if ((size % 20) || (size > (uint32_t)((end - bytes) - 4))) return; + bmf->charTable = bytes + 4; + bmf->isContinuous = (size && (0x40 & c_read8(19 + bmf->charTable))) ? 1 : 0; bmf->charCount = size / 20; #if MODDEF_CFE_KERN // block 5 - kerning bytes += 4 + size; - if (5 == c_read8(bytes)) { + if (((end - bytes) >= 1) && (5 == c_read8(bytes))) { bytes += 1; + if ((end - bytes) < 4) + return; bmf->kernCount = c_read32(bytes) / 10; bmf->kernTriples = bytes + 4; - bmf->kernSorted = (0x80 & c_read8(19 + bmf->charTable)) ? 1 : 0; + bmf->kernSorted = (size && (0x80 & c_read8(19 + bmf->charTable))) ? 1 : 0; } #endif diff --git a/modules/commodetto/commodettoParseBMF.c b/modules/commodetto/commodettoParseBMF.c index a3ce15e07b..c73b6ff564 100644 --- a/modules/commodetto/commodettoParseBMF.c +++ b/modules/commodetto/commodettoParseBMF.c @@ -24,18 +24,18 @@ #include "xsmc.h" #include "mc.xs.h" // for xsID_ values -//@@ can read beyond end of provided buffer on malformed data void xs_parseBMF(xsMachine *the) { - unsigned char *bytes, *start; + unsigned char *bytes, *start, *end; uint32_t size; xsUnsignedValue byteLength; int charCount; xsmcGetBufferReadable(xsArg(0), (void **)&bytes, &byteLength); start = bytes; + end = bytes + byteLength; - if ((0x42 != c_read8(bytes + 0)) || (0x4D != c_read8(bytes + 1)) || (0x46 != c_read8(bytes + 2)) || ((3 != c_read8(bytes + 3)) && (4 != c_read8(bytes + 3)))) + if ((byteLength < 5) || (0x42 != c_read8(bytes + 0)) || (0x4D != c_read8(bytes + 1)) || (0x46 != c_read8(bytes + 2)) || ((3 != c_read8(bytes + 3)) && (4 != c_read8(bytes + 3)))) xsUnknownError("Invalid BMF header"); bytes += 4; @@ -44,15 +44,24 @@ void xs_parseBMF(xsMachine *the) xsUnknownError("can't find info block"); bytes += 1; - bytes += 4 + c_read32(bytes); + if ((end - bytes) < 4) + xsUnknownError("truncated BMF"); + size = c_read32(bytes); + if (size > (uint32_t)((end - bytes) - 4)) + xsUnknownError("truncated BMF"); + bytes += 4 + size; // get lineHeight from block 2 - if (2 != c_read8(bytes)) + if (((end - bytes) < 1) || (2 != c_read8(bytes))) xsUnknownError("can't find common block"); bytes += 1; + if ((end - bytes) < 4) + xsUnknownError("truncated BMF"); size = c_read32(bytes); bytes += 4; + if (((end - bytes) < 10) || (size < 8) || (size > (uint32_t)(end - bytes))) + xsUnknownError("truncated BMF"); xsmcSetInteger(xsResult, c_read16(bytes)); bytes += 2; @@ -69,20 +78,27 @@ void xs_parseBMF(xsMachine *the) bytes += size - 8; // skip block 3 - if (3 != c_read8(bytes)) + if (((end - bytes) < 1) || (3 != c_read8(bytes))) xsUnknownError("can't find pages block"); bytes += 1; - bytes += 4 + c_read32(bytes); + if ((end - bytes) < 4) + xsUnknownError("truncated BMF"); + size = c_read32(bytes); + if (size > (uint32_t)((end - bytes) - 4)) + xsUnknownError("truncated BMF"); + bytes += 4 + size; // use block 4 - if (4 != c_read8(bytes)) + if (((end - bytes) < 1) || (4 != c_read8(bytes))) xsUnknownError("can't find chars block"); bytes += 1; xsmcSetInteger(xsResult, bytes - start); xsmcDefine(xsArg(0), xsID_position, xsResult, xsDontDelete | xsDontSet); + if ((end - bytes) < 4) + xsUnknownError("truncated BMF"); size = c_read32(bytes); if (size % 20) xsUnknownError("bad chars block size");