DF-5194 / sim.c
/* * sim.c -- offline replication of the snake_saver() movement engine * (sys/dev/misc/syscons/snake/snake_saver.c:83-111) * * Proves the wall-bounce arithmetic claim for DF-5194: * - geometry ysize==1 (permitted by sc_set_text_mode's clamp, * scvidctl.c:94-96): the FIRST move escapes the vtb and the * row test (f/xsize) can never fire again -> unbounded forward * drift, one sc_vtb_putc OOB write per tick. * - control run with real geometry (80x25): never escapes. * * The arithmetic is copied verbatim from the kernel source, including * C truncating division/modulo on ints. */ #include <stdio.h> #include <stdlib.h> static int xsize, ysize, messagelen; static int dirx, diry; static int savs[64]; static void run(const char *label, int xs, int ys, int xp, int yp, int ticks) { long vtb_size = (long)xs * ys; long maxpos, minpos; int i; xsize = xs; ysize = ys; messagelen = 20; /* snake_saver.c:83-87 init */ dirx = (xp ? 1 : -1); diry = (yp ? xsize : -xsize); for (i = 0; i < messagelen; i++) savs[i] = xp + yp * xsize; maxpos = minpos = savs[0]; for (i = 0; i < ticks; i++) { int f = savs[0]; /* snake_saver.c:101-108, krandom() replaced by rand() */ if ((f % xsize) == 0 || (f % xsize) == xsize - 1 || (rand() % 50) == 0) dirx = -dirx; if ((f / xsize) == 0 || (f / xsize) == ysize - 1 || (rand() % 20) == 0) diry = -diry; savs[0] += dirx + diry; /* :109 */ if (savs[0] > maxpos) maxpos = savs[0]; if (savs[0] < minpos) minpos = savs[0]; } printf("%-28s vtb_size=%-7ld final=%-9d max=%-9ld min=%-9ld %s\n", label, vtb_size, savs[0], maxpos, minpos, (maxpos >= vtb_size || minpos < 0) ? "ESCAPED (OOB writes)" : "in-bounds"); } int main(void) { srand(1234); /* cursor mid-screen, degenerate 1-row geometry */ run("ysize=1 xsize=80 (latent)", 80, 1, 40, 0, 2000); /* top-left corner */ run("ysize=1 xsize=80 corner", 80, 1, 0, 0, 2000); /* real VGA geometry, several cursors, 100k ticks */ run("80x25 cursor mid", 80, 25, 40, 12, 100000); run("80x25 corner 0,0", 80, 25, 0, 0, 100000); run("80x25 corner 79,24", 80, 25, 79, 24, 100000); run("132x60 cursor mid", 132, 60, 66, 30, 100000); return 0; } |