Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deflate.zig: check for distances past beginning of output stream #9860

Merged
merged 1 commit into from
Oct 4, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions lib/std/compress/deflate.zig
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ pub fn InflateStream(comptime ReaderType: type) type {
wi: usize = 0, // Write index
ri: usize = 0, // Read index
el: usize = 0, // Number of readable elements
total_written: usize = 0,

fn readable(self: *WSelf) usize {
return self.el;
Expand All @@ -210,6 +211,7 @@ pub fn InflateStream(comptime ReaderType: type) type {
self.buf[self.wi] = value;
self.wi = (self.wi + 1) & (self.buf.len - 1);
self.el += 1;
self.total_written += 1;
}

// Fill dest[] with data from the window, starting from the read
Expand Down Expand Up @@ -462,7 +464,7 @@ pub fn InflateStream(comptime ReaderType: type) type {
const distance = DISTS[distance_symbol] +
@intCast(u16, try self.readBits(DEXT[distance_symbol]));

if (distance > self.window.buf.len)
if (distance > self.window.buf.len or distance > self.window.total_written)
return error.InvalidDistance;

const written = self.window.copyFrom(distance, length);
Expand Down Expand Up @@ -666,13 +668,20 @@ test "lengths overflow" {
}

test "empty distance alphabet" {
// dynamic block with empty distance alphabet is valid if end of data symbol is used immediately
// dynamic block with empty distance alphabet is valid if only literals and end of data symbol are used
// f dy hlit hdist hclen 16 17 18 0 8 7 9 6 10 5 11 4 12 3 13 2 14 1 15 (18) x128 (18) x128 (1) ( 0) (256)
// 1 10 00000 00000 1111 000 000 010 010 000 000 000 000 000 000 000 000 000 000 000 000 000 001 000 (11) 1110101 (11) 1110101 (0) (10) (0)
const stream = [_]u8{ 0b00000101, 0b11100000, 0b00000001, 0b00001001, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00010000, 0b01011100, 0b10111111, 0b00101110 };
try testInflate(stream[0..]);
}

test "distance past beginning of output stream" {
// f fx ('A') ('B') ('C') <len=4, dist=4> (end)
// 1 01 (01110001) (01110010) (01110011) (0000010) (00011) (0000000)
const stream = [_]u8{ 0b01110011, 0b01110100, 0b01110010, 0b00000110, 0b01100001, 0b00000000 };
try std.testing.expectError(error.InvalidDistance, testInflate(stream[0..]));
}

test "inflateStream fuzzing" {
// see https://github.com/ziglang/zig/issues/9842
try std.testing.expectError(error.EndOfStream, testInflate("\x950000"));
Expand Down