fix [x]u65529 and above overflowing

```
$ cat overflow.zig
test {
    var a: [1]u65535 = undefined;
    _ = a;
}
$ zig-out/bin/zig test overflow.zig
thread 290266 panic: integer overflow
zig/src/type.zig:3604:55: 0xada43d in intAbiAlignment (zig)
            std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8),
                                                      ^
zig/src/type.zig:3598:42: 0xadd4ea in intAbiSize (zig)
        const alignment = intAbiAlignment(bits, target);
                                         ^
zig/src/type.zig:3500:61: 0x92be91 in abiSizeAdvanced (zig)
                return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
                                                            ^
zig/src/type.zig:3385:62: 0x928933 in abiSizeAdvanced (zig)
                switch (try payload.elem_type.abiSizeAdvanced(target, strat)) {
                                                             ^
zig/src/type.zig:3268:32: 0x92c012 in abiSize (zig)
        return (abiSizeAdvanced(ty, target, .eager) catch unreachable).scalar;
                               ^
```
This is only noticed in a debug build of zig and silently does the wrong
thing and overflows in release builds.

This happened to `[x]u65529` and above because of the ` + 7` on a `u16`.
This commit is contained in:
r00ster91
2023-05-01 19:15:51 +02:00
committed by Veikka Tuominen
parent f40539e5d8
commit 297b5d1074
2 changed files with 23 additions and 2 deletions

View File

@@ -3596,12 +3596,12 @@ pub const Type = extern union {
fn intAbiSize(bits: u16, target: Target) u64 {
const alignment = intAbiAlignment(bits, target);
return std.mem.alignForwardGeneric(u64, (bits + 7) / 8, alignment);
return std.mem.alignForwardGeneric(u64, @intCast(u16, (@as(u17, bits) + 7) / 8), alignment);
}
fn intAbiAlignment(bits: u16, target: Target) u32 {
return @min(
std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8),
std.math.ceilPowerOfTwoPromote(u16, @intCast(u16, (@as(u17, bits) + 7) / 8)),
target.maxIntAlignment(),
);
}

View File

@@ -1124,3 +1124,24 @@ test "runtime-known globals initialized with undefined" {
try expect(S.s[0] == 1);
try expect(S.s[4] == 5);
}
test "arrays and vectors with big integers" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
// TODO: only aarch64-windows didn't pass in the PR that added this code.
// figure out why if you can run this target.
if (builtin.os.tag == .windows and builtin.cpu.arch == .aarch64) return error.SkipZigTest;
inline for (.{ u65528, u65529, u65535 }) |Int| {
var a: [1]Int = undefined;
a[0] = std.math.maxInt(Int);
try expect(a[0] == comptime std.math.maxInt(Int));
var b: @Vector(1, Int) = undefined;
b[0] = std.math.maxInt(Int);
try expect(b[0] == comptime std.math.maxInt(Int));
}
}