DF-5756 / craft5756.c
/* DF-5756 — craft a FAT image whose LFN entries contain unpaired surrogate * code units, then the reader (kread5756) shows what the kernel does with * them on readdir. * * Patch targets (UTF-16LE bytes, found by scanning the raw image): * "abcdefghij.k" unit[4] 'e' -> U+DC00 (lone LOW surrogate) * "wxyzabcd.k" unit[0] 'w' -> U+D83D (lone HIGH surrogate) * * weChksum covers only the 8.3 alias, so no checksum fixup is needed. */ #include <sys/types.h> #include <err.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> /* wePart1 (units 0-4, UTF-16LE) + entry meta (attr 0x0f follows at +10) */ static const unsigned char patA[] = { 'a',0,'b',0,'c',0,'d',0,'e',0 }; static const unsigned char patB[] = { 'w',0,'x',0,'y',0,'z',0,'a',0 }; static size_t find(unsigned char *buf, size_t sz, const unsigned char *pat, size_t pl) { size_t i; for (i = 0; i + pl <= sz; i++) if (memcmp(buf + i, pat, pl) == 0) return i; return (size_t)-1; } static void patch(unsigned char *buf, size_t sz, const unsigned char *pat, size_t pl, size_t unitidx, unsigned char lo, unsigned char hi, const char *label) { size_t off = find(buf, sz, pat, pl); if (off == (size_t)-1) { printf("[craft] %s: base name NOT found in image\n", label); exit(1); } if (off + 10 < sz && buf[off + 10] != 0x0f) { printf("[craft] %s: found at 0x%zx but attr byte is 0x%02x " "(not an LFN entry)\n", label, off, buf[off + 10]); exit(1); } /* LFN entry: byte0=seq, name starts at entry+1 == match offset */ printf("[craft] %s: name at 0x%zx, patching unit[%zu] -> %02x %02x\n", label, off, unitidx, lo, hi); buf[off + unitidx * 2] = lo; buf[off + unitidx * 2 + 1] = hi; } int main(int argc, char **argv) { unsigned char *buf; ssize_t n; size_t sz; int fd; if (argc != 2) errx(1, "usage: %s <image>", argv[0]); fd = open(argv[1], O_RDWR); if (fd < 0) err(1, "open %s", argv[1]); sz = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); buf = malloc(sz); if (!buf) err(1, "malloc"); n = read(fd, buf, sz); if (n < 0 || (size_t)n != sz) err(1, "read"); /* unit[4] of A ('e') -> U+DC00 (LE: 00 DC) */ patch(buf, sz, patA, sizeof(patA), 4, 0x00, 0xDC, "low-surrogate"); /* unit[0] of B ('w') -> U+D83D (LE: 3D D8) */ patch(buf, sz, patB, sizeof(patB), 0, 0x3D, 0xD8, "high-surrogate"); if (lseek(fd, 0, SEEK_SET) != 0) err(1, "lseek"); if (write(fd, buf, sz) != (ssize_t)sz) err(1, "write"); close(fd); free(buf); printf("[craft] image patched\n"); return 0; } |