aboutsummaryrefslogtreecommitdiff
path: root/src/Value.zig
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2024-03-26 14:10:35 +0000
committermlugg <mlugg@mlugg.co.uk>2024-03-26 17:06:14 +0000
commitbfc0c35689cd5781a3493bdd9c9b8d527847c7a2 (patch)
tree7ab8e45ba6975c7e5881e2d07ff7c59ba8c933eb /src/Value.zig
parent951fc09a7e174f8f7cb7384d1fd56dcae9ac73da (diff)
downloadzig-bfc0c35689cd5781a3493bdd9c9b8d527847c7a2.tar.gz
zig-bfc0c35689cd5781a3493bdd9c9b8d527847c7a2.zip
Value: fix underflow reading large `u64` values from packed memory
Diffstat (limited to 'src/Value.zig')
-rw-r--r--src/Value.zig12
1 files changed, 6 insertions, 6 deletions
diff --git a/src/Value.zig b/src/Value.zig
index b1230954ed..f8f23667e2 100644
--- a/src/Value.zig
+++ b/src/Value.zig
@@ -787,12 +787,12 @@ pub fn readFromPackedMemory(
if (bits == 0) return mod.intValue(ty, 0);
// Fast path for integers <= u64
- if (bits <= 64) {
- return mod.intValue(
- ty,
- std.mem.readVarPackedInt(i64, buffer, bit_offset, bits, endian, int_info.signedness),
- );
- }
+ if (bits <= 64) switch (int_info.signedness) {
+ // Use different backing types for unsigned vs signed to avoid the need to go via
+ // a larger type like `i128`.
+ .unsigned => return mod.intValue(ty, std.mem.readVarPackedInt(u64, buffer, bit_offset, bits, endian, .unsigned)),
+ .signed => return mod.intValue(ty, std.mem.readVarPackedInt(i64, buffer, bit_offset, bits, endian, .signed)),
+ };
// Slow path, we have to construct a big-int
const abi_size = @as(usize, @intCast(ty.abiSize(mod)));