| ... | @@ -122,10 +122,20 @@ fn int(comptime T: type, value: []const u8) error{ NonCanonical, LargeValue }!T | ... | @@ -122,10 +122,20 @@ fn int(comptime T: type, value: []const u8) error{ NonCanonical, LargeValue }!T |
| 122 | | 122 | |
| 123 | const had_sign_byte = value.len >= 2 and value[0] == 0x00; | 123 | const had_sign_byte = value.len >= 2 and value[0] == 0x00; |
| 124 | const bytes = if (had_sign_byte) value[1..] else value; | 124 | const bytes = if (had_sign_byte) value[1..] else value; |
| 125 | if (bytes.len > @sizeOf(T)) return error.LargeValue; | 125 | const der_negative = !had_sign_byte and bytes[0] & 0x80 != 0; |
| 126 | | 126 | |
| 127 | const sign_extend = info.signedness == .signed and !had_sign_byte and bytes[0] & 0x80 != 0; | 127 | switch (info.signedness) { |
| 128 | var buf: [@sizeOf(T)]u8 = @splat(if (sign_extend) 0xff else 0); | 128 | .unsigned => { |
| | 129 | if (der_negative) return error.LargeValue; |
| | 130 | if (bytes.len > @sizeOf(T)) return error.LargeValue; |
| | 131 | }, |
| | 132 | .signed => { |
| | 133 | const max_len: usize = if (had_sign_byte) @sizeOf(T) - 1 else @sizeOf(T); |
| | 134 | if (bytes.len > max_len) return error.LargeValue; |
| | 135 | }, |
| | 136 | } |
| | 137 | |
| | 138 | var buf: [@sizeOf(T)]u8 = @splat(if (der_negative) 0xff else 0); |
| 129 | @memcpy(buf[buf.len - bytes.len ..], bytes); | 139 | @memcpy(buf[buf.len - bytes.len ..], bytes); |
| 130 | return std.mem.readInt(T, &buf, .big); | 140 | return std.mem.readInt(T, &buf, .big); |
| 131 | } | 141 | } |
| ... | @@ -137,7 +147,8 @@ test int { | ... | @@ -137,7 +147,8 @@ test int { |
| 137 | | 147 | |
| 138 | const big = [_]u8{ 0xef, 0xff }; | 148 | const big = [_]u8{ 0xef, 0xff }; |
| 139 | try expectError(error.LargeValue, int(u8, &big)); | 149 | try expectError(error.LargeValue, int(u8, &big)); |
| 140 | try expectEqual(0xefff, int(u16, &big)); | 150 | try expectError(error.LargeValue, int(u16, &big)); |
| | 151 | try expectEqual(@as(i16, -4097), try int(i16, &big)); |
| 141 | | 152 | |
| 142 | try expectEqual(@as(u16, 255), try int(u16, &.{ 0x00, 0xff })); | 153 | try expectEqual(@as(u16, 255), try int(u16, &.{ 0x00, 0xff })); |
| 143 | try expectEqual(@as(u16, 0x8000), try int(u16, &.{ 0x00, 0x80, 0x00 })); | 154 | try expectEqual(@as(u16, 0x8000), try int(u16, &.{ 0x00, 0x80, 0x00 })); |
| ... | @@ -148,6 +159,14 @@ test int { | ... | @@ -148,6 +159,14 @@ test int { |
| 148 | try expectEqual(@as(i16, -129), try int(i16, &.{ 0xff, 0x7f })); | 159 | try expectEqual(@as(i16, -129), try int(i16, &.{ 0xff, 0x7f })); |
| 149 | try expectEqual(@as(i16, 255), try int(i16, &.{ 0x00, 0xff })); | 160 | try expectEqual(@as(i16, 255), try int(i16, &.{ 0x00, 0xff })); |
| 150 | try expectEqual(@as(i32, 0x7fffffff), try int(i32, &.{ 0x7f, 0xff, 0xff, 0xff })); | 161 | try expectEqual(@as(i32, 0x7fffffff), try int(i32, &.{ 0x7f, 0xff, 0xff, 0xff })); |
| | 162 | |
| | 163 | try expectError(error.LargeValue, int(i8, &.{ 0x00, 0xff })); |
| | 164 | try expectError(error.LargeValue, int(i16, &.{ 0x00, 0x80, 0x00 })); |
| | 165 | try expectError(error.LargeValue, int(i32, &.{ 0x00, 0x80, 0x00, 0x00, 0x00 })); |
| | 166 | |
| | 167 | try expectError(error.LargeValue, int(u8, &.{0xff})); |
| | 168 | try expectError(error.LargeValue, int(u16, &.{0x80})); |
| | 169 | try expectError(error.LargeValue, int(u32, &.{ 0x80, 0x00, 0x00, 0x00 })); |
| 151 | } | 170 | } |
| 152 | | 171 | |
| 153 | test Decoder { | 172 | test Decoder { |