-- VT1200: demonstrate the pcfReadBitmaps n*4 integer overflow in-emulator. -- -- We jump straight into the arithmetic block with a crafted PCF_CharInfo: -- a9 = fake pCS, pCS->nChars at a9+0x270 -- a13 = fake arg blk, n (32-bit pcfReadInt32 result) at a13+0x20 -- PC = 3f984e70 -- A breakpoint after 'sll 0x2,a11' (3f985060) prints the resulting size and -- quits, so we never enter fosAlloc with a bogus heap. -- -- vt1200 -rompath harness/mame/roms -video none -sound none -nothrottle \ -- -debug -debugger none -debuglog \ -- -autoboot_script harness/mame/overflow.lua -autoboot_delay 0 local function hex(v) return string.format("%08X", v) end local machine = manager.machine local cpu = machine.devices[':maincpu'] local dbg = machine.debugger local prog = cpu.spaces['program'] if not dbg then print("ERROR: debugger not enabled; pass -debug") machine:exit() return end -- n defaults to 0x40000001: n*4 wraps mod 2^32 to 4, but the following loop -- still writes n CARD32 entries -- a heap overflow. Override with OVF_N -- (decimal) to run a control case. local n = tonumber(os.getenv("OVF_N") or "1073741825") cpu.state['SP'].value = 0x00080000 cpu.state['A9'].value = 0x00040000 -- fake pCS cpu.state['A13'].value = 0x00060000 -- fake arg block prog:write_u32(0x00040270, 0) -- pCS->nChars = 0 prog:write_u32(0x00060020, n) -- n cpu.state['PC'].value = 0x3f984e70 -- pcfReadBitmaps arithmetic block print(string.format("setup: n=%s (n*4 should wrap to 00000004)", hex(n))) -- 3f985060 is the instruction right after '3f985050 sll 0x2,a11'. dbg:command("bpset 3f985060,,{ printf \"RESULT n=%08X a11_fosAlloc_arg=%08X nChars=%08X\\n\", d@00060020, a11, d@00040270 ; quit }") dbg.visible_cpu = cpu dbg.execution_state = 'run'