Integer overflow in Io.Writer

I was trying to invent a toy zip-bomb while doing an exercise at Exercism and noticed an integer overflow in std.Io.Writer interface:

test "Io.Writer does not integer overflow" {
    var w: std.Io.Writer.Discarding = .init(&.{});
    _ = try w.writer.writeSplat(&.{"A", "B"}, std.math.maxInt(usize));
}

It crashes:

$ zig test example.zig 
thread 380898 panic: integer overflow
zig-x86_64-linux-0.16.0/lib/std/Io/Writer.zig:162:11: 0x1042243 in countSplat (std.zig)
    total += data[data.len - 1].len * splat;
          ^
zig-x86_64-linux-0.16.0/lib/std/Io/Writer.zig:184:29: 0x10413c7 in writeSplat (std.zig)
    const count = countSplat(data, splat);
                            ^
example.zig:19:32: 0x124f2e7 in test_0 (example.zig)
    _ = try w.writer.writeSplat(&.{"A", "B"}, std.math.maxInt(usize));

Is it a bug in standard library or am I using it wrong? I did not expect anything to actually crash.

i’d argue you’re using it wrong, although i could see arguments against this. if you cannot address the total number of bites you want to write, you should not be writing that many bytes.

1 Like

On a 64 bit system, wouldn’t this write millions of terabytes?

2 Likes

The exercise is to write a Run-Length Encoding compressor and decompressor. My compressor implements Io.Writer interface and decompressor implements Io.Reader interface. Then I chain them to test if they decompress and compress back to the original:

try decompress.reader().streamRemaining(compress.writer())

The compressed input is a zip bomb that would decompress into maxInt(usize) bytes. But the interfaces interact through splatByteAll() method and do not need to allocate millions of terabytes. I was testing my implementation with different edge case inputs to catch all integer overflows in my code. Then I discovered an overflow in the standard library.

I am not a security expert. I do not know if there is a way to throw a malicious compressed file at some program and trigger a vulnerability.

1 Like

But what if I have a compressed file that would decompress into 5Gb on a 32-bit system? Is it okay for it to trigger Illegal Behaviour?

Yes, I think so :slight_smile:

Hmm IDK, isn’t that a limitation of using usize? I guess using u64 would make all memory writer code akward on 32 bits system..

I discovered it on 64-bit machine. It crashed my toy compressor/decompressor. I managed to overflow u64.

https://codeberg.org/ziglang/zig/issues/36893