namespace; include rt, std; // a capture holds 256 characters and drops the rest. end() must still put its // 0 inside the buffer, even when the capture was full: the length is 256 and the // last kept character is the 256th one written (index 255, 'a' + 255 % 26 = 'v'). // a block allocated right after the buffer is checked afterwards: a 0 written one // word past the buffer would land in its header and read as a bad or freed block. memdebug on; // header checks make a write into a neighbouring block visible fn capture_long() { let buf = std.capture.start(); int* next = rt.new(8); int i = 0; while (i < 300) { rt.put_c('a' + i % 26); i++; } std.capture.end(buf); next[0] = 7; // stops with "bad heap pointer" if its header was overwritten rt.put_n(next[0]); rt.put_c(10); // 7 return buf; } memdebug off; // the header check only searches 64 words back, so the long buffer is read unchecked fn main() { char* buf = capture_long(); rt.put_n(rt.len_w(buf)); rt.put_c(10); // 256 rt.put_c(buf[255]); rt.put_c(10); // v return 0; }