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 {...@@ -5,22 +5,24 @@ pub fn readULEB128(comptime T: type, in_stream: var) !T {
5 const ShiftT = @IntType(false, std.math.log2(T.bit_count));5 const ShiftT = @IntType(false, std.math.log2(T.bit_count));
66
7 var result: T = 0;7 var result: T = 0;
8 var shift: ShiftT = 0;8 var shift: usize = 0;
99
10 while (true) {10 while (true) {
11 const byte = try in_stream.readByte();11 const byte = try in_stream.readByte();
1212
13 if (shift > T.bit_count)
14 return error.Overflow;
15
13 var operand: T = undefined;16 var operand: T = undefined;
14 if (@shlWithOverflow(T, byte & 0x7f, shift, &operand))17 if (@shlWithOverflow(T, byte & 0x7f, @intCast(ShiftT, shift), &operand))
15 return error.Overflow;18 return error.Overflow;
1619
17 result |= operand;20 result |= operand;
1821
19 if (@addWithOverflow(ShiftT, shift, 7, &shift))
20 return error.Overflow;
21
22 if ((byte & 0x80) == 0)22 if ((byte & 0x80) == 0)
23 return result;23 return result;
24
25 shift += 7;
24 }26 }
25}27}
2628
...@@ -28,82 +30,92 @@ pub fn readULEB128Mem(comptime T: type, ptr: *[*]const u8) !T {...@@ -28,82 +30,92 @@ pub fn readULEB128Mem(comptime T: type, ptr: *[*]const u8) !T {
28 const ShiftT = @IntType(false, std.math.log2(T.bit_count));30 const ShiftT = @IntType(false, std.math.log2(T.bit_count));
2931
30 var result: T = 0;32 var result: T = 0;
31 var shift: ShiftT = 0;33 var shift: usize = 0;
32 var i: usize = 0;34 var i: usize = 0;
3335
34 while (true) {36 while (true) : (i += 1) {
35 const byte = ptr.*[i];37 const byte = ptr.*[i];
36 i += 1;38
39 if (shift > T.bit_count)
40 return error.Overflow;
3741
38 var operand: T = undefined;42 var operand: T = undefined;
39 if (@shlWithOverflow(T, byte & 0x7f, shift, &operand))43 if (@shlWithOverflow(T, byte & 0x7f, @intCast(ShiftT, shift), &operand))
40 return error.Overflow;44 return error.Overflow;
4145
42 result |= operand;46 result |= operand;
4347
44 if (@addWithOverflow(ShiftT, shift, 7, &shift))
45 return error.Overflow;
46
47 if ((byte & 0x80) == 0) {48 if ((byte & 0x80) == 0) {
48 ptr.* += i;49 ptr.* += i;
49 return result;50 return result;
50 }51 }
52
53 shift += 7;
51 }54 }
52}55}
5356
54pub fn readILEB128(comptime T: type, in_stream: var) !T {57pub fn readILEB128(comptime T: type, in_stream: var) !T {
58 const UT = @IntType(false, T.bit_count);
55 const ShiftT = @IntType(false, std.math.log2(T.bit_count));59 const ShiftT = @IntType(false, std.math.log2(T.bit_count));
5660
57 var result: T = 0;61 var result: UT = 0;
58 var shift: ShiftT = 0;62 var shift: usize = 0;
5963
60 while (true) {64 while (true) {
61 const byte = u8(try in_stream.readByte());65 const byte = u8(try in_stream.readByte());
6266
63 var operand: T = undefined;67 if (shift > T.bit_count)
64 if (@shlWithOverflow(T, @intCast(T, byte & 0x7f), shift, &operand))
65 return error.Overflow;68 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
67 result |= operand;76 result |= operand;
6877
69 if (@addWithOverflow(ShiftT, shift, 7, &shift))78 shift += 7;
70 return error.Overflow;
7179
72 if ((byte & 0x80) == 0) {80 if ((byte & 0x80) == 0) {
73 if (shift <= ShiftT(T.bit_count - 1) and (byte & 0x40) != 0) {81 if (shift < T.bit_count and (byte & 0x40) != 0) {
74 result |= T(-1) << shift;82 result |= @bitCast(UT, @intCast(T, -1)) << @intCast(ShiftT, shift);
75 }83 }
76 return result;84 return @bitCast(T, result);
77 }85 }
78 }86 }
79}87}
8088
81pub fn readILEB128Mem(comptime T: type, ptr: *[*]const u8) !T {89pub fn readILEB128Mem(comptime T: type, ptr: *[*]const u8) !T {
90 const UT = @IntType(false, T.bit_count);
82 const ShiftT = @IntType(false, std.math.log2(T.bit_count));91 const ShiftT = @IntType(false, std.math.log2(T.bit_count));
8392
84 var result: T = 0;93 var result: UT = 0;
85 var shift: ShiftT = 0;94 var shift: usize = 0;
86 var i: usize = 0;95 var i: usize = 0;
8796
88 while (true) {97 while (true) : (i += 1) {
89 const byte = ptr.*[i];98 const byte = ptr.*[i];
90 i += 1;
9199
92 var operand: T = undefined;100 if (shift > T.bit_count)
93 if (@shlWithOverflow(T, @intCast(T, byte & 0x7f), shift, &operand))
94 return error.Overflow;101 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
96 result |= operand;109 result |= operand;
97110
98 if (@addWithOverflow(ShiftT, shift, 7, &shift))111 shift += 7;
99 return error.Overflow;
100112
101 if ((byte & 0x80) == 0) {113 if ((byte & 0x80) == 0) {
102 if (shift <= ShiftT(T.bit_count - 1) and (byte & 0x40) != 0) {114 if (shift < T.bit_count and (byte & 0x40) != 0) {
103 result |= T(-1) << shift;115 result |= @bitCast(UT, @intCast(T, -1)) << @intCast(ShiftT, shift);
104 }116 }
105 ptr.* += i;117 ptr.* += i;
106 return result;118 return @bitCast(T, result);
107 }119 }
108 }120 }
109}121}
...@@ -145,6 +157,7 @@ test "deserialize signed LEB128" {...@@ -145,6 +157,7 @@ test "deserialize signed LEB128" {
145 testing.expectError(error.Overflow, test_read_ileb128(i16, "\x80\x80\x80\x40"));157 testing.expectError(error.Overflow, test_read_ileb128(i16, "\x80\x80\x80\x40"));
146 testing.expectError(error.Overflow, test_read_ileb128(i32, "\x80\x80\x80\x80\x40"));158 testing.expectError(error.Overflow, test_read_ileb128(i32, "\x80\x80\x80\x80\x40"));
147 testing.expectError(error.Overflow, test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x40"));159 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
149 // Decode SLEB128162 // Decode SLEB128
150 testing.expect((try test_read_ileb128(i64, "\x00")) == 0);163 testing.expect((try test_read_ileb128(i64, "\x00")) == 0);
...@@ -160,6 +173,13 @@ test "deserialize signed LEB128" {...@@ -160,6 +173,13 @@ test "deserialize signed LEB128" {
160 testing.expect((try test_read_ileb128(i64, "\x81\x7f")) == -127);173 testing.expect((try test_read_ileb128(i64, "\x81\x7f")) == -127);
161 testing.expect((try test_read_ileb128(i64, "\xc0\x00")) == 64);174 testing.expect((try test_read_ileb128(i64, "\xc0\x00")) == 64);
162 testing.expect((try test_read_ileb128(i64, "\xc7\x9f\x7f")) == -12345);175 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
164 // Decode unnormalized SLEB128 with extra padding bytes.184 // Decode unnormalized SLEB128 with extra padding bytes.
165 testing.expect((try test_read_ileb128(i64, "\x80\x00")) == 0);185 testing.expect((try test_read_ileb128(i64, "\x80\x00")) == 0);
...@@ -175,8 +195,11 @@ test "deserialize unsigned LEB128" {...@@ -175,8 +195,11 @@ test "deserialize unsigned LEB128" {
175 testing.expectError(error.EndOfStream, test_read_stream_uleb128(u64, "\x80"));195 testing.expectError(error.EndOfStream, test_read_stream_uleb128(u64, "\x80"));
176196
177 // Overflow197 // Overflow
198 testing.expectError(error.Overflow, test_read_uleb128(u8, "\x80\x02"));
178 testing.expectError(error.Overflow, test_read_uleb128(u8, "\x80\x80\x40"));199 testing.expectError(error.Overflow, test_read_uleb128(u8, "\x80\x80\x40"));
200 testing.expectError(error.Overflow, test_read_uleb128(u16, "\x80\x80\x84"));
179 testing.expectError(error.Overflow, test_read_uleb128(u16, "\x80\x80\x80\x40"));201 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"));
180 testing.expectError(error.Overflow, test_read_uleb128(u32, "\x80\x80\x80\x80\x40"));203 testing.expectError(error.Overflow, test_read_uleb128(u32, "\x80\x80\x80\x80\x40"));
181 testing.expectError(error.Overflow, test_read_uleb128(u64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x40"));204 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" {...@@ -193,6 +216,7 @@ test "deserialize unsigned LEB128" {
193 testing.expect((try test_read_uleb128(u64, "\x80\x02")) == 0x100);216 testing.expect((try test_read_uleb128(u64, "\x80\x02")) == 0x100);
194 testing.expect((try test_read_uleb128(u64, "\x81\x02")) == 0x101);217 testing.expect((try test_read_uleb128(u64, "\x81\x02")) == 0x101);
195 testing.expect((try test_read_uleb128(u64, "\x80\xc1\x80\x80\x10")) == 4294975616);218 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
197 // Decode ULEB128 with extra padding bytes221 // Decode ULEB128 with extra padding bytes
198 testing.expect((try test_read_uleb128(u64, "\x80\x00")) == 0);222 testing.expect((try test_read_uleb128(u64, "\x80\x00")) == 0);