authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-05-11 09:56:01+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-11 09:54:48-04:00
log6756e545f40dc7de373186a6581594e07bfd8200
treee687494ee8bfc3185d267a60f0e5e825f2616012
parent5f4c3e6557b6ffd654fad5ef3928e5f21db56a50

Fix more corner cases in LEB128 parsing


1 files changed, 56 insertions(+), 32 deletions(-)

std/debug/leb128.zig+56-32
......@@ -5,22 +5,24 @@ pub fn readULEB128(comptime T: type, in_stream: var) !T {
55 const ShiftT = @IntType(false, std.math.log2(T.bit_count));
66
77 var result: T = 0;
8 var shift: ShiftT = 0;
8 var shift: usize = 0;
99
1010 while (true) {
1111 const byte = try in_stream.readByte();
1212
13 if (shift > T.bit_count)
14 return error.Overflow;
15
1316 var operand: T = undefined;
14 if (@shlWithOverflow(T, byte & 0x7f, shift, &operand))
17 if (@shlWithOverflow(T, byte & 0x7f, @intCast(ShiftT, shift), &operand))
1518 return error.Overflow;
1619
1720 result |= operand;
1821
19 if (@addWithOverflow(ShiftT, shift, 7, &shift))
20 return error.Overflow;
21
2222 if ((byte & 0x80) == 0)
2323 return result;
24
25 shift += 7;
2426 }
2527}
2628
......@@ -28,82 +30,92 @@ pub fn readULEB128Mem(comptime T: type, ptr: *[*]const u8) !T {
2830 const ShiftT = @IntType(false, std.math.log2(T.bit_count));
2931
3032 var result: T = 0;
31 var shift: ShiftT = 0;
33 var shift: usize = 0;
3234 var i: usize = 0;
3335
34 while (true) {
36 while (true) : (i += 1) {
3537 const byte = ptr.*[i];
36 i += 1;
38
39 if (shift > T.bit_count)
40 return error.Overflow;
3741
3842 var operand: T = undefined;
39 if (@shlWithOverflow(T, byte & 0x7f, shift, &operand))
43 if (@shlWithOverflow(T, byte & 0x7f, @intCast(ShiftT, shift), &operand))
4044 return error.Overflow;
4145
4246 result |= operand;
4347
44 if (@addWithOverflow(ShiftT, shift, 7, &shift))
45 return error.Overflow;
46
4748 if ((byte & 0x80) == 0) {
4849 ptr.* += i;
4950 return result;
5051 }
52
53 shift += 7;
5154 }
5255}
5356
5457pub fn readILEB128(comptime T: type, in_stream: var) !T {
58 const UT = @IntType(false, T.bit_count);
5559 const ShiftT = @IntType(false, std.math.log2(T.bit_count));
5660
57 var result: T = 0;
58 var shift: ShiftT = 0;
61 var result: UT = 0;
62 var shift: usize = 0;
5963
6064 while (true) {
6165 const byte = u8(try in_stream.readByte());
6266
63 var operand: T = undefined;
64 if (@shlWithOverflow(T, @intCast(T, byte & 0x7f), shift, &operand))
67 if (shift > T.bit_count)
6568 return error.Overflow;
6669
70 var operand: UT = undefined;
71 if (@shlWithOverflow(UT, UT(byte & 0x7f), @intCast(ShiftT, shift), &operand)) {
72 if (byte != 0x7f)
73 return error.Overflow;
74 }
75
6776 result |= operand;
6877
69 if (@addWithOverflow(ShiftT, shift, 7, &shift))
70 return error.Overflow;
78 shift += 7;
7179
7280 if ((byte & 0x80) == 0) {
73 if (shift <= ShiftT(T.bit_count - 1) and (byte & 0x40) != 0) {
74 result |= T(-1) << shift;
81 if (shift < T.bit_count and (byte & 0x40) != 0) {
82 result |= @bitCast(UT, @intCast(T, -1)) << @intCast(ShiftT, shift);
7583 }
76 return result;
84 return @bitCast(T, result);
7785 }
7886 }
7987}
8088
8189pub fn readILEB128Mem(comptime T: type, ptr: *[*]const u8) !T {
90 const UT = @IntType(false, T.bit_count);
8291 const ShiftT = @IntType(false, std.math.log2(T.bit_count));
8392
84 var result: T = 0;
85 var shift: ShiftT = 0;
93 var result: UT = 0;
94 var shift: usize = 0;
8695 var i: usize = 0;
8796
88 while (true) {
97 while (true) : (i += 1) {
8998 const byte = ptr.*[i];
90 i += 1;
9199
92 var operand: T = undefined;
93 if (@shlWithOverflow(T, @intCast(T, byte & 0x7f), shift, &operand))
100 if (shift > T.bit_count)
94101 return error.Overflow;
95102
103 var operand: UT = undefined;
104 if (@shlWithOverflow(UT, UT(byte & 0x7f), @intCast(ShiftT, shift), &operand)) {
105 if (byte != 0x7f)
106 return error.Overflow;
107 }
108
96109 result |= operand;
97110
98 if (@addWithOverflow(ShiftT, shift, 7, &shift))
99 return error.Overflow;
111 shift += 7;
100112
101113 if ((byte & 0x80) == 0) {
102 if (shift <= ShiftT(T.bit_count - 1) and (byte & 0x40) != 0) {
103 result |= T(-1) << shift;
114 if (shift < T.bit_count and (byte & 0x40) != 0) {
115 result |= @bitCast(UT, @intCast(T, -1)) << @intCast(ShiftT, shift);
104116 }
105117 ptr.* += i;
106 return result;
118 return @bitCast(T, result);
107119 }
108120 }
109121}
......@@ -145,6 +157,7 @@ test "deserialize signed LEB128" {
145157 testing.expectError(error.Overflow, test_read_ileb128(i16, "\x80\x80\x80\x40"));
146158 testing.expectError(error.Overflow, test_read_ileb128(i32, "\x80\x80\x80\x80\x40"));
147159 testing.expectError(error.Overflow, test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x40"));
160 testing.expectError(error.Overflow, test_read_ileb128(i8, "\xff\x7e"));
148161
149162 // Decode SLEB128
150163 testing.expect((try test_read_ileb128(i64, "\x00")) == 0);
......@@ -160,6 +173,13 @@ test "deserialize signed LEB128" {
160173 testing.expect((try test_read_ileb128(i64, "\x81\x7f")) == -127);
161174 testing.expect((try test_read_ileb128(i64, "\xc0\x00")) == 64);
162175 testing.expect((try test_read_ileb128(i64, "\xc7\x9f\x7f")) == -12345);
176 testing.expect((try test_read_ileb128(i8, "\xff\x7f")) == -1);
177 testing.expect((try test_read_ileb128(i16, "\xff\xff\x7f")) == -1);
178 testing.expect((try test_read_ileb128(i32, "\xff\xff\xff\xff\x7f")) == -1);
179 testing.expect((try test_read_ileb128(i32, "\x80\x80\x80\x80\x08")) == -0x80000000);
180 testing.expect((try test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01")) == @bitCast(i64, @intCast(u64, 0x8000000000000000)));
181 testing.expect((try test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x40")) == -0x4000000000000000);
182 testing.expect((try test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x7f")) == -0x8000000000000000);
163183
164184 // Decode unnormalized SLEB128 with extra padding bytes.
165185 testing.expect((try test_read_ileb128(i64, "\x80\x00")) == 0);
......@@ -175,8 +195,11 @@ test "deserialize unsigned LEB128" {
175195 testing.expectError(error.EndOfStream, test_read_stream_uleb128(u64, "\x80"));
176196
177197 // Overflow
198 testing.expectError(error.Overflow, test_read_uleb128(u8, "\x80\x02"));
178199 testing.expectError(error.Overflow, test_read_uleb128(u8, "\x80\x80\x40"));
200 testing.expectError(error.Overflow, test_read_uleb128(u16, "\x80\x80\x84"));
179201 testing.expectError(error.Overflow, test_read_uleb128(u16, "\x80\x80\x80\x40"));
202 testing.expectError(error.Overflow, test_read_uleb128(u32, "\x80\x80\x80\x80\x90"));
180203 testing.expectError(error.Overflow, test_read_uleb128(u32, "\x80\x80\x80\x80\x40"));
181204 testing.expectError(error.Overflow, test_read_uleb128(u64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x40"));
182205
......@@ -193,6 +216,7 @@ test "deserialize unsigned LEB128" {
193216 testing.expect((try test_read_uleb128(u64, "\x80\x02")) == 0x100);
194217 testing.expect((try test_read_uleb128(u64, "\x81\x02")) == 0x101);
195218 testing.expect((try test_read_uleb128(u64, "\x80\xc1\x80\x80\x10")) == 4294975616);
219 testing.expect((try test_read_uleb128(u64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01")) == 0x8000000000000000);
196220
197221 // Decode ULEB128 with extra padding bytes
198222 testing.expect((try test_read_uleb128(u64, "\x80\x00")) == 0);