zig
zig copied to clipboard
stage1: Incorrect SHA-256 hash value computed at comptime
Zig Version
0.10.0-dev.4622+f28e4e03e
Steps to Reproduce and Observed Behavior
const std = @import("std");
const Hasher = std.crypto.hash.sha2.Sha256;
const testfile = @embedFile("testfile");
test {
comptime
{
@setEvalBranchQuota(100_000_000);
var digest: [Hasher.digest_length]u8 = undefined;
_ = Hasher.hash(testfile, &digest, .{});
//std.log.err("digest: {}", .{std.fmt.fmtSliceHexLower(digest[0..])});
@compileLog(digest);
}
}
"testfile" is a 1KB file of random bytes generated using dd if=/dev/urandom of=testfile bs=1K count=1
Computes a hash of all zeros:
./build/stage3/bin/zig test testct.zig --zig-lib-dir lib -fstage1
Semantic Analysis [66/90] | [32]u8{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
./testct.zig:11:9: error: found compile log statement
@compileLog(digest);
^
Expected Behavior
Should compute the same hash as at runtime:
(74b7d714d7c401efbb6a4c276101f8e1e93e74962310744c180bc9352fded2d7 for my testfile)
This:
for (rr) |s, j| {
mem.writeIntBig(u32, out[4 * j ..][0..4], s);
}
or its equivalent:
for (rr) |s, j| {
@ptrCast(*align(1) u32, out[4 * j ..]).* = mem.nativeToBig(u32, s);
}
doesn't properly fill the output buffer when using comptime.
It can be worked around by using a temporary buffer:
--- lib/std/crypto/sha2.zig 2022-10-29 17:11:12
+++ /opt/zig/lib/zig/std/crypto/sha2.zig 2022-11-01 11:00:16
@@ -171,7 +171,9 @@
const rr = d.s[0 .. params.digest_bits / 32];
for (rr) |s, j| {
- mem.writeIntBig(u32, out[4 * j ..][0..4], s);
+ var t: [4]u8 = undefined;
+ mem.writeIntBig(u32, &t, s);
+ mem.copy(u8, out[4 * j ..], &t);
}
}
@@ -650,7 +652,9 @@
const rr = d.s[0 .. params.digest_bits / 64];
for (rr) |s, j| {
- mem.writeIntBig(u64, out[8 * j ..][0..8], s);
+ var t: [8]u8 = undefined;
+ mem.writeIntBig(u64, &t, s);
+ mem.copy(u8, out[8 * j ..], &t);
}
}
But this is certainly not a proper fix, and it probably affects other things as well.