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.
This commit is contained in:
@@ -65,6 +65,41 @@ static const RGB amiv_pal[16] = {
|
|||||||
{0xFF,0xBB,0x99}, /* 15 peach */
|
{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 */
|
/* Colour helpers */
|
||||||
/* --------------------------------------------------------- */
|
/* --------------------------------------------------------- */
|
||||||
@@ -345,7 +380,7 @@ main(int argc, char **argv)
|
|||||||
int nplanes, maxcol;
|
int nplanes, maxcol;
|
||||||
int i, y;
|
int i, y;
|
||||||
RGB outpal[256];
|
RGB outpal[256];
|
||||||
int remap[256];
|
int remap[256] = {0};
|
||||||
uint8_t *remapped;
|
uint8_t *remapped;
|
||||||
uint8_t *plane_data[8];
|
uint8_t *plane_data[8];
|
||||||
uint8_t cmap_rgb[256 * 3];
|
uint8_t cmap_rgb[256 * 3];
|
||||||
@@ -370,8 +405,22 @@ main(int argc, char **argv)
|
|||||||
bmpfp = fopen(argv[3], "rb");
|
bmpfp = fopen(argv[3], "rb");
|
||||||
if (!bmpfp) { perror(argv[3]); return 1; }
|
if (!bmpfp) { perror(argv[3]); return 1; }
|
||||||
|
|
||||||
if (fread(&fhdr, sizeof(fhdr), 1, bmpfp) != 1
|
if (!read_u16le(bmpfp, &fhdr.bfType)
|
||||||
|| fread(&ihdr, sizeof(ihdr), 1, bmpfp) != 1) {
|
|| !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");
|
fprintf(stderr, "Failed to read BMP header\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -388,6 +437,11 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
img_w = ihdr.biWidth;
|
img_w = ihdr.biWidth;
|
||||||
img_h = abs(ihdr.biHeight);
|
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;
|
ncolors = ihdr.biClrUsed ? ihdr.biClrUsed : 256;
|
||||||
if (ncolors > 256) ncolors = 256;
|
if (ncolors > 256) ncolors = 256;
|
||||||
|
|
||||||
@@ -410,13 +464,15 @@ main(int argc, char **argv)
|
|||||||
rowstride = (img_w + 3) & ~3;
|
rowstride = (img_w + 3) & ~3;
|
||||||
bmpdata = malloc(rowstride * img_h);
|
bmpdata = malloc(rowstride * img_h);
|
||||||
if (!bmpdata) {
|
if (!bmpdata) {
|
||||||
printf("%s\n", "malloc failure on bmpdata");
|
fprintf(stderr, "malloc failure on bmpdata\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
fseek(bmpfp, fhdr.bfOffBits, SEEK_SET);
|
fseek(bmpfp, fhdr.bfOffBits, SEEK_SET);
|
||||||
if (fread(bmpdata, 1, rowstride * img_h, bmpfp)
|
if (fread(bmpdata, 1, rowstride * img_h, bmpfp)
|
||||||
!= (size_t)(rowstride * img_h)) {
|
!= (size_t)(rowstride * img_h)) {
|
||||||
fprintf(stderr, "Failed to read pixel data\n");
|
fprintf(stderr, "Failed to read pixel data\n");
|
||||||
|
free(bmpdata);
|
||||||
|
fclose(bmpfp);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
fclose(bmpfp);
|
fclose(bmpfp);
|
||||||
@@ -424,7 +480,8 @@ main(int argc, char **argv)
|
|||||||
/* flip bottom-up to top-down */
|
/* flip bottom-up to top-down */
|
||||||
pixels = malloc(img_w * img_h);
|
pixels = malloc(img_w * img_h);
|
||||||
if (!pixels) {
|
if (!pixels) {
|
||||||
printf("%s\n", "malloc failure on pixels");
|
fprintf(stderr, "malloc failure on pixels\n");
|
||||||
|
free(bmpdata);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (ihdr.biHeight > 0) {
|
if (ihdr.biHeight > 0) {
|
||||||
@@ -450,7 +507,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
remapped = malloc(img_w * img_h);
|
remapped = malloc(img_w * img_h);
|
||||||
if (!remapped) {
|
if (!remapped) {
|
||||||
printf("%s\n", "malloc failure on remapped");
|
fprintf(stderr, "malloc failure on remapped\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
for (i = 0; i < img_w * img_h; i++)
|
for (i = 0; i < img_w * img_h; i++)
|
||||||
@@ -458,8 +515,13 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
/* convert to bitplanes */
|
/* convert to bitplanes */
|
||||||
planesize = (img_w / 8) * img_h;
|
planesize = (img_w / 8) * img_h;
|
||||||
for (i = 0; i < nplanes; i++)
|
for (i = 0; i < nplanes; i++) {
|
||||||
plane_data[i] = calloc(1, planesize);
|
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,
|
to_planes(remapped, img_w, img_h,
|
||||||
nplanes, plane_data);
|
nplanes, plane_data);
|
||||||
|
|||||||
@@ -62,12 +62,13 @@ xpmgetline(void)
|
|||||||
/* strip trailing <",> and whitespace */
|
/* strip trailing <",> and whitespace */
|
||||||
for (bp = xbuf; *bp; bp++)
|
for (bp = xbuf; *bp; bp++)
|
||||||
;
|
;
|
||||||
bp--;
|
if (bp > xbuf)
|
||||||
while (isspace((unsigned char)*bp))
|
|
||||||
bp--;
|
bp--;
|
||||||
if (*bp == ',')
|
while (bp > xbuf && isspace((unsigned char)*bp))
|
||||||
bp--;
|
bp--;
|
||||||
if (*bp == '"')
|
if (bp > xbuf && *bp == ',')
|
||||||
|
bp--;
|
||||||
|
if (bp > xbuf && *bp == '"')
|
||||||
bp--;
|
bp--;
|
||||||
bp++;
|
bp++;
|
||||||
*bp = '\0';
|
*bp = '\0';
|
||||||
@@ -209,10 +210,19 @@ main(int argc, char **argv)
|
|||||||
return 1;
|
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 = ceil(log2(Colors)) */
|
||||||
nplanes = 0;
|
nplanes = 0;
|
||||||
i = XpmScreen.Colors - 1;
|
i = XpmScreen.Colors - 1;
|
||||||
while (i > 0) { nplanes++; i >>= 1; }
|
while (i > 0) { nplanes++; i >>= 1; }
|
||||||
|
if (nplanes == 0)
|
||||||
|
nplanes = 1;
|
||||||
|
|
||||||
colors = 1 << nplanes;
|
colors = 1 << nplanes;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user