From ff7f5b2a0a34d4da7286243ef30c3e1a628502f1 Mon Sep 17 00:00:00 2001 From: Matthias Blankertz Date: Fri, 17 Apr 2015 15:39:19 +0200 Subject: [PATCH] font2png, iffexplore: Misc. cleanup --- font2png.cc | 57 +++++++++++++++++++-------------------------------- iffexplore.cc | 48 +++++++++++++++++++++++++------------------ 2 files changed, 49 insertions(+), 56 deletions(-) diff --git a/font2png.cc b/font2png.cc index bfdafd2..fc50d5c 100644 --- a/font2png.cc +++ b/font2png.cc @@ -31,50 +31,29 @@ struct Font { struct FontHeader { // little endian uint32_t unknown1; // (always)? "1.\0\0" uint32_t entries; - uint32_t charWidth; + uint32_t charHeight; uint8_t bgColor; char unknown3[3]; } __attribute__((__packed__)); Font parseFont(FILE* file, size_t length) { - // if (fseeko(file, 16, SEEK_SET) != 0) { - // throw POSIXException(errno, "Could not seek"); - // } - - // uint32_t data, last_data = 0; - // int last_diff = -1, count = 0; - // size_t pos = 16; - // while (pos < length) { - // if (fread(&data, 4, 1, file) != 1) { - // if (feof(file)) - // throw Exception{"Unexpected EOF"}; - // throw POSIXException{errno, "Could not read"}; - // } - - // if ((last_diff == -1) || - // (data-last_data == last_diff)) { - // ++count; - // last_diff = data-last_data; - // // printf("%.8x\n", data); - // } else { - // if ((count > 1) && last_diff ) - // printf("%d times diff %d\n", count, last_diff); - // count = 0; - // last_diff = -1; - // } - // last_data = data; - // pos += 4; - // } - + if (length < sizeof(FontHeader)) + throw FormatException{"File smaller than header"}; + FontHeader header; if (fread(&header, sizeof(FontHeader), 1, file) != 1) throw POSIXException{errno, "Could not read"}; + + if (header.unknown1 != 0x00002E31) + throw FormatException{"Not a font?"}; const unsigned index_start = sizeof(FontHeader); const unsigned index_end = index_start+4*header.entries; - const unsigned char_width = header.charWidth; + if (index_end > length) + throw Exception{"Index table exceeds file length"}; + std::vector indices; for (unsigned i = index_start;i < index_end;i+=4) { uint32_t data; @@ -86,10 +65,13 @@ Font parseFont(FILE* file, size_t length) auto minmax = std::minmax_element(indices.begin(), indices.end()); printf("Index range %u .. %u\n", *minmax.first, *minmax.second); + + if (*minmax.second > length) + throw FormatException{"Index exceeds file length"}; Font ret; ret.numChars = header.entries; - ret.charHeight = char_width; + ret.charHeight = header.charHeight; ret.maxCharWidth = 0; ret.bgColor = header.bgColor; for (auto const& index : indices) { @@ -101,19 +83,22 @@ Font parseFont(FILE* file, size_t length) throw POSIXException{errno, "Could not read"}; if (!len) { - ret.chars.push_back(Image{}); + ret.chars.push_back(Image{0, 0, {}}); continue; } + if (index+4+len*header.charHeight > length) + throw FormatException{"Glyph data exceeds file length"}; + Image chr; - chr.height = char_width; + chr.height = header.charHeight; chr.width = len; - chr.data.resize(char_width*len); + chr.data.resize(chr.height*chr.width); if (chr.width > ret.maxCharWidth) ret.maxCharWidth = chr.width; - if (fread(chr.data.data(), len*char_width, 1, file) != 1) + if (fread(chr.data.data(), chr.height*chr.width, 1, file) != 1) throw POSIXException{errno, "Could not read"}; ret.chars.push_back(chr); diff --git a/iffexplore.cc b/iffexplore.cc index 024f439..e20cdb8 100644 --- a/iffexplore.cc +++ b/iffexplore.cc @@ -13,10 +13,10 @@ struct ChunkHeader { char typeID[4]; - uint32_t length; -}; + uint32_t length; // big endian!! +} __attribute__((__packed__)); -void parseBlob(FILE *iffFile, off_t start, off_t length, char name[4], unsigned level) +void parseBlob(FILE *iffFile, off_t start, off_t length, char name[4], unsigned level, bool dump = false) { static unsigned count = 0; @@ -73,17 +73,23 @@ void parseBlob(FILE *iffFile, off_t start, off_t length, char name[4], unsigned filename.append("0"); filename.append(std::to_string(count) + "-"); filename.append(name, 4); + + if (dump) { + FILEUPtr outFile{fopen(filename.c_str(), "wb")}; + if (!outFile) + throw POSIXException{errno, "Could not open " + filename}; - FILEUPtr outFile{fopen(filename.c_str(), "wb")}; - if (!outFile) - throw POSIXException{errno, "Could not open " + filename}; + for (unsigned i = 0;i < level;++i) + putchar('\t'); + printf("Dumping BLOB of length %ld (0x%lx) to %s\n", length, length, filename.c_str()); - for (unsigned i = 0;i < level;++i) - putchar('\t'); - printf("Dumping BLOB of length %ld (0x%lx) to %s\n", length, length, filename.c_str()); - - if (fwrite(buf.data(), length, 1, outFile.get()) != 1) - throw POSIXException{errno, "Could not write data"}; + if (fwrite(buf.data(), length, 1, outFile.get()) != 1) + throw POSIXException{errno, "Could not write data"}; + } else { + for (unsigned i = 0;i < level;++i) + putchar('\t'); + printf("BLOB of length %ld (0x%lx)\n", length, length); + } ++count; } @@ -96,6 +102,10 @@ void parseChunk(FILE* iffFile, off_t start, off_t length, unsigned level = 0) if (fseeko(iffFile, pos+start, SEEK_SET) != 0) { throw POSIXException(errno, "Could not seek"); } + + // pos < length due to loop condition, cast of difference to unsigned is OK + if (static_cast(length-pos) < sizeof(ChunkHeader)) + throw FormatException{"Remaining size < header size"}; ChunkHeader header; @@ -109,11 +119,10 @@ void parseChunk(FILE* iffFile, off_t start, off_t length, unsigned level = 0) for (unsigned i = 0;i < level;++i) putchar('\t'); printf("Type: %.4s, Length: %u (0x%x)", header.typeID, header.length, header.length); + if (header.length > (length-(pos+8))) + throw FormatException{"Length in header > remaining parent size"}; + if (memcmp(header.typeID, "FORM", 4) == 0) { - if (header.length > (length-(pos+8))) { - throw FormatException{"Length in header > remaining parent size"}; - } - char subType[4]; if (fread(&subType, 4, 1, iffFile) != 1) { throw POSIXException(errno, "Could not read form subtype"); @@ -125,11 +134,10 @@ void parseChunk(FILE* iffFile, off_t start, off_t length, unsigned level = 0) putchar('\n'); parseBlob(iffFile, start+pos+8, header.length, header.typeID, level+1); } - - if (header.length%2 != 0) - pos += 1; - + pos += header.length+8; + if (pos%2 != 0) + ++pos; } }