mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
std.math.big.int: Initialize limbs in addWrap
When a big.Int.Mutable had more than two limbs, it was possible for this function to change the `len` field without zeroing limbs in the active range. These uninitialized limbs would then be used in `truncate()` and could cause invalid results. Closes #13571
This commit is contained in:
parent
7d90410b96
commit
e8fdb249b6
@ -489,6 +489,7 @@ pub const Mutable = struct {
|
|||||||
if (msl < req_limbs) {
|
if (msl < req_limbs) {
|
||||||
r.limbs[msl] = 1;
|
r.limbs[msl] = 1;
|
||||||
r.len = req_limbs;
|
r.len = req_limbs;
|
||||||
|
mem.set(Limb, r.limbs[msl + 1 .. req_limbs], 0);
|
||||||
} else {
|
} else {
|
||||||
carry_truncated = true;
|
carry_truncated = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
const std = @import("../../std.zig");
|
const std = @import("../../std.zig");
|
||||||
|
const builtin = @import("builtin");
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const Managed = std.math.big.int.Managed;
|
const Managed = std.math.big.int.Managed;
|
||||||
@ -2123,6 +2124,33 @@ test "big.int bitNotWrap signed multi" {
|
|||||||
try testing.expect((try a.to(SignedDoubleLimb)) == -1);
|
try testing.expect((try a.to(SignedDoubleLimb)) == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "big.int bitNotWrap more than two limbs" {
|
||||||
|
// This test requires int sizes greater than 128 bits.
|
||||||
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
|
// LLVM: unexpected runtime library name: __umodei4
|
||||||
|
if (builtin.zig_backend == .stage2_llvm and comptime builtin.target.isWasm()) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
|
var a = try Managed.initSet(testing.allocator, maxInt(Limb));
|
||||||
|
defer a.deinit();
|
||||||
|
|
||||||
|
var res = try Managed.init(testing.allocator);
|
||||||
|
defer res.deinit();
|
||||||
|
|
||||||
|
const bits = @bitSizeOf(Limb) * 4 + 2;
|
||||||
|
|
||||||
|
try res.bitNotWrap(&a, .unsigned, bits);
|
||||||
|
const Unsigned = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = bits } });
|
||||||
|
try testing.expectEqual((try res.to(Unsigned)), ~@as(Unsigned, maxInt(Limb)));
|
||||||
|
|
||||||
|
try res.bitNotWrap(&a, .signed, bits);
|
||||||
|
const Signed = @Type(.{ .Int = .{ .signedness = .signed, .bits = bits } });
|
||||||
|
try testing.expectEqual((try res.to(Signed)), ~@as(Signed, maxInt(Limb)));
|
||||||
|
}
|
||||||
|
|
||||||
test "big.int bitwise and simple" {
|
test "big.int bitwise and simple" {
|
||||||
var a = try Managed.initSet(testing.allocator, 0xffffffff11111111);
|
var a = try Managed.initSet(testing.allocator, 0xffffffff11111111);
|
||||||
defer a.deinit();
|
defer a.deinit();
|
||||||
@ -2655,11 +2683,10 @@ test "big int popcount" {
|
|||||||
try popCountTest(&a, limb_size * 2 - 1, limb_size);
|
try popCountTest(&a, limb_size * 2 - 1, limb_size);
|
||||||
try popCountTest(&a, limb_size * 2, limb_size + 1);
|
try popCountTest(&a, limb_size * 2, limb_size + 1);
|
||||||
try popCountTest(&a, limb_size * 2 + 1, limb_size + 2);
|
try popCountTest(&a, limb_size * 2 + 1, limb_size + 2);
|
||||||
// TODO: These produce incorrect pop count for Mutable
|
try popCountTest(&a, limb_size * 2 + 2, limb_size + 3);
|
||||||
// https://github.com/ziglang/zig/issues/13571
|
try popCountTest(&a, limb_size * 2 + 3, limb_size + 4);
|
||||||
// try popCountTest(&a, limb_size * 2 + 2, limb_size + 3);
|
try popCountTest(&a, limb_size * 2 + 4, limb_size + 5);
|
||||||
// try popCountTest(&a, limb_size * 2 + 3, limb_size + 4);
|
try popCountTest(&a, limb_size * 4 + 2, limb_size * 3 + 3);
|
||||||
// try popCountTest(&a, limb_size * 2 + 4, limb_size + 5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn popCountTest(val: *const Managed, bit_count: usize, expected: usize) !void {
|
fn popCountTest(val: *const Managed, bit_count: usize, expected: usize) !void {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user