From fbc7fc130f14f116772d007acc9b1113abb5ee07 Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Sat, 20 Jun 2026 01:20:48 +0530 Subject: [PATCH 1/2] 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"); From b740206fc0d5751ac769bd6f18127ff97fb20f9a Mon Sep 17 00:00:00 2001 From: Naveed Khan Date: Wed, 24 Jun 2026 15:07:27 +0530 Subject: [PATCH 2/2] fold cfeBMF rework, read pages at common-block offset 8, bound parseBMF chars block --- modules/commodetto/cfeBMF.c | 47 ++++++++----------------- modules/commodetto/commodettoParseBMF.c | 2 +- 2 files changed, 16 insertions(+), 33 deletions(-) diff --git a/modules/commodetto/cfeBMF.c b/modules/commodetto/cfeBMF.c index b9558e2f2c..29d92846f1 100644 --- a/modules/commodetto/cfeBMF.c +++ b/modules/commodetto/cfeBMF.c @@ -77,26 +77,20 @@ void CFELockCache(CommodettoFontEngine bmf, uint8_t lock) void CFESetFontData(CommodettoFontEngine bmf, const void *fontData, uint32_t fontDataSize) { - const unsigned char *bytes, *start, *end; - uint32_t size; - uint8_t version; - if (fontData == bmf->fontData) return; // unchanged bmf->charCount = 0; // zero in case of failure - - start = fontData; - bytes = start; - end = start + fontDataSize; - if (fontDataSize < 5) return; - version = c_read8(bytes + 3); + const unsigned char *start = fontData; + const unsigned char *bytes = start; + const unsigned char *end = start + fontDataSize; + + uint8_t 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))) return; - bmf->isCompressed = 4 == version; bytes += 4; @@ -108,42 +102,33 @@ void CFESetFontData(CommodettoFontEngine bmf, const void *fontData, uint32_t fon if ((end - bytes) < 4) return; - size = c_read32(bytes); + uint32_t size = c_read32(bytes); if (size > (uint32_t)((end - bytes) - 4)) return; bytes += 4 + size; // get lineHeight from block 2 - if (((end - bytes) < 1) || (2 != c_read8(bytes))) + if (((end - bytes) < 5) || (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; - - bmf->ascent = c_read16(bytes); - bytes += 2; - - bytes += 2 + 2; // scaleW and scaleH - if (1 != c_read16(bytes)) // pages + bmf->ascent = c_read16(bytes + 2); + if (1 != c_read16(bytes + 8)) // pages return; - bytes += size - 8; + bytes += size; // skip block 3 - if (((end - bytes) < 1) || (3 != c_read8(bytes))) + if (((end - bytes) < 5) || (3 != c_read8(bytes))) return; bytes += 1; - if ((end - bytes) < 4) - return; size = c_read32(bytes); if (size > (uint32_t)((end - bytes) - 4)) return; @@ -157,22 +142,20 @@ void CFESetFontData(CommodettoFontEngine bmf, const void *fontData, uint32_t fon if ((end - bytes) < 4) return; size = c_read32(bytes); - if ((size % 20) || (size > (uint32_t)((end - bytes) - 4))) + if ((size % 20) || (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->isContinuous = (0x40 & c_read8(19 + bmf->charTable)) ? 1 : 0; bmf->charCount = size / 20; #if MODDEF_CFE_KERN // block 5 - kerning bytes += 4 + size; - if (((end - bytes) >= 1) && (5 == c_read8(bytes))) { + if (((end - bytes) >= 11) && (5 == c_read8(bytes))) { bytes += 1; - if ((end - bytes) < 4) - return; bmf->kernCount = c_read32(bytes) / 10; bmf->kernTriples = bytes + 4; - bmf->kernSorted = (size && (0x80 & c_read8(19 + bmf->charTable))) ? 1 : 0; + bmf->kernSorted = (0x80 & c_read8(19 + bmf->charTable)) ? 1 : 0; } #endif diff --git a/modules/commodetto/commodettoParseBMF.c b/modules/commodetto/commodettoParseBMF.c index c73b6ff564..4d3962c09f 100644 --- a/modules/commodetto/commodettoParseBMF.c +++ b/modules/commodetto/commodettoParseBMF.c @@ -100,7 +100,7 @@ void xs_parseBMF(xsMachine *the) if ((end - bytes) < 4) xsUnknownError("truncated BMF"); size = c_read32(bytes); - if (size % 20) + if ((size % 20) || (size > (uint32_t)((end - bytes) - 4))) xsUnknownError("bad chars block size"); charCount = size / 20;