From 157c005f02deadd3251003f43513b84926f69f59 Mon Sep 17 00:00:00 2001 From: Ingo Paschke Date: Tue, 12 May 2026 15:18:44 +0200 Subject: [PATCH] Amiga: harden host-side bmp/xpm to iff converters Replace #pragma-pack BMP header reads with little-endian byte readers so the tool works on any host endianness. Add dimension and color-count range checks, zero-init pixel remap table, check calloc, free bmpdata on early returns, send malloc errors to stderr. Add bp>xbuf guards to xpmgetline's strip loop. --- sys/amiga/bmp2iff_host.c | 76 ++++++++++++++++++++++++++++++++++++---- sys/amiga/xpm2iff_host.c | 18 +++++++--- 2 files changed, 83 insertions(+), 11 deletions(-) diff --git a/sys/amiga/bmp2iff_host.c b/sys/amiga/bmp2iff_host.c index 85bb42088..1182aa732 100644 --- a/sys/amiga/bmp2iff_host.c +++ b/sys/amiga/bmp2iff_host.c @@ -65,6 +65,41 @@ static const RGB amiv_pal[16] = { {0xFF,0xBB,0x99}, /* 15 peach */ }; +/* --------------------------------------------------------- */ +/* Little-endian readers (BMP is LE regardless of host) */ +/* --------------------------------------------------------- */ + +static int +read_u16le(FILE *fp, uint16_t *out) +{ + int lo = fgetc(fp), hi = fgetc(fp); + if (hi == EOF) return 0; + *out = (uint16_t)(((unsigned) hi << 8) | (unsigned) lo); + return 1; +} + +static int +read_u32le(FILE *fp, uint32_t *out) +{ + int b0 = fgetc(fp), b1 = fgetc(fp); + int b2 = fgetc(fp), b3 = fgetc(fp); + if (b3 == EOF) return 0; + *out = ((uint32_t)(unsigned) b3 << 24) + | ((uint32_t)(unsigned) b2 << 16) + | ((uint32_t)(unsigned) b1 << 8) + | (uint32_t)(unsigned) b0; + return 1; +} + +static int +read_i32le(FILE *fp, int32_t *out) +{ + uint32_t v; + if (!read_u32le(fp, &v)) return 0; + *out = (int32_t) v; + return 1; +} + /* --------------------------------------------------------- */ /* Colour helpers */ /* --------------------------------------------------------- */ @@ -345,7 +380,7 @@ main(int argc, char **argv) int nplanes, maxcol; int i, y; RGB outpal[256]; - int remap[256]; + int remap[256] = {0}; uint8_t *remapped; uint8_t *plane_data[8]; uint8_t cmap_rgb[256 * 3]; @@ -370,8 +405,22 @@ main(int argc, char **argv) bmpfp = fopen(argv[3], "rb"); if (!bmpfp) { perror(argv[3]); return 1; } - if (fread(&fhdr, sizeof(fhdr), 1, bmpfp) != 1 - || fread(&ihdr, sizeof(ihdr), 1, bmpfp) != 1) { + if (!read_u16le(bmpfp, &fhdr.bfType) + || !read_u32le(bmpfp, &fhdr.bfSize) + || !read_u16le(bmpfp, &fhdr.bfReserved1) + || !read_u16le(bmpfp, &fhdr.bfReserved2) + || !read_u32le(bmpfp, &fhdr.bfOffBits) + || !read_u32le(bmpfp, &ihdr.biSize) + || !read_i32le(bmpfp, &ihdr.biWidth) + || !read_i32le(bmpfp, &ihdr.biHeight) + || !read_u16le(bmpfp, &ihdr.biPlanes) + || !read_u16le(bmpfp, &ihdr.biBitCount) + || !read_u32le(bmpfp, &ihdr.biCompression) + || !read_u32le(bmpfp, &ihdr.biSizeImage) + || !read_i32le(bmpfp, &ihdr.biXPelsPerMeter) + || !read_i32le(bmpfp, &ihdr.biYPelsPerMeter) + || !read_u32le(bmpfp, &ihdr.biClrUsed) + || !read_u32le(bmpfp, &ihdr.biClrImportant)) { fprintf(stderr, "Failed to read BMP header\n"); return 1; } @@ -388,6 +437,11 @@ main(int argc, char **argv) img_w = ihdr.biWidth; img_h = abs(ihdr.biHeight); + if (img_w <= 0 || img_w > 16384 || img_h <= 0 || img_h > 16384) { + fprintf(stderr, "BMP dimensions out of range: %dx%d\n", + img_w, img_h); + return 1; + } ncolors = ihdr.biClrUsed ? ihdr.biClrUsed : 256; if (ncolors > 256) ncolors = 256; @@ -410,13 +464,15 @@ main(int argc, char **argv) rowstride = (img_w + 3) & ~3; bmpdata = malloc(rowstride * img_h); if (!bmpdata) { - printf("%s\n", "malloc failure on bmpdata"); + fprintf(stderr, "malloc failure on bmpdata\n"); return 1; } fseek(bmpfp, fhdr.bfOffBits, SEEK_SET); if (fread(bmpdata, 1, rowstride * img_h, bmpfp) != (size_t)(rowstride * img_h)) { fprintf(stderr, "Failed to read pixel data\n"); + free(bmpdata); + fclose(bmpfp); return 1; } fclose(bmpfp); @@ -424,7 +480,8 @@ main(int argc, char **argv) /* flip bottom-up to top-down */ pixels = malloc(img_w * img_h); if (!pixels) { - printf("%s\n", "malloc failure on pixels"); + fprintf(stderr, "malloc failure on pixels\n"); + free(bmpdata); return 1; } if (ihdr.biHeight > 0) { @@ -450,7 +507,7 @@ main(int argc, char **argv) remapped = malloc(img_w * img_h); if (!remapped) { - printf("%s\n", "malloc failure on remapped"); + fprintf(stderr, "malloc failure on remapped\n"); return 1; } for (i = 0; i < img_w * img_h; i++) @@ -458,8 +515,13 @@ main(int argc, char **argv) /* convert to bitplanes */ planesize = (img_w / 8) * img_h; - for (i = 0; i < nplanes; i++) + for (i = 0; i < nplanes; i++) { plane_data[i] = calloc(1, planesize); + if (!plane_data[i]) { + fprintf(stderr, "calloc failure for plane %d\n", i); + return 1; + } + } to_planes(remapped, img_w, img_h, nplanes, plane_data); diff --git a/sys/amiga/xpm2iff_host.c b/sys/amiga/xpm2iff_host.c index 589d4f56f..5a968979e 100644 --- a/sys/amiga/xpm2iff_host.c +++ b/sys/amiga/xpm2iff_host.c @@ -62,12 +62,13 @@ xpmgetline(void) /* strip trailing <",> and whitespace */ for (bp = xbuf; *bp; bp++) ; - bp--; - while (isspace((unsigned char)*bp)) + if (bp > xbuf) bp--; - if (*bp == ',') + while (bp > xbuf && isspace((unsigned char)*bp)) bp--; - if (*bp == '"') + if (bp > xbuf && *bp == ',') + bp--; + if (bp > xbuf && *bp == '"') bp--; bp++; *bp = '\0'; @@ -209,10 +210,19 @@ main(int argc, char **argv) return 1; } + if (XpmScreen.Colors < 1 || XpmScreen.Colors > 256) { + fprintf(stderr, + "xpm2iff_host: unsupported color count %d\n", + XpmScreen.Colors); + return 1; + } + /* nplanes = ceil(log2(Colors)) */ nplanes = 0; i = XpmScreen.Colors - 1; while (i > 0) { nplanes++; i >>= 1; } + if (nplanes == 0) + nplanes = 1; colors = 1 << nplanes;