From 3c151f0b1c560167326aa73ebbb7923dd810ee95 Mon Sep 17 00:00:00 2001 From: fardragon Date: Thu, 5 Jun 2025 21:23:40 +0200 Subject: [PATCH 1/3] Handle empty hashes in build.zig.zon --- src/Package.zig | 6 ++++++ src/Package/Fetch.zig | 7 +++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Package.zig b/src/Package.zig index 7f231f5ad7..aa3a9e3e5d 100644 --- a/src/Package.zig +++ b/src/Package.zig @@ -67,6 +67,7 @@ pub const Hash = struct { pub fn toSlice(ph: *const Hash) []const u8 { var end: usize = ph.bytes.len; while (true) { + if (end == 0) return &.{}; end -= 1; if (ph.bytes[end] != 0) return ph.bytes[0 .. end + 1]; } @@ -195,6 +196,11 @@ test Hash { try std.testing.expectEqualStrings("nasm-2.16.1-3-vrr-ygAAoADH9XG3tOdvPNuHen_d-XeHndOG-nNXmved", result.toSlice()); } +test "EmptyHash" { + const hash = Hash.fromSlice(""); + try std.testing.expectEqualStrings("", hash.toSlice()); +} + test { _ = Fetch; } diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index 12eec6009d..9a64bebd99 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -567,16 +567,18 @@ fn runResource( if (declared_hash.isOld()) { const actual_hex = Package.multiHashHexDigest(f.computed_hash.digest); if (!std.mem.eql(u8, declared_hash.toSlice(), &actual_hex)) { + const declared = if (declared_hash.toSlice().len > 0) declared_hash.toSlice() else ""; return f.fail(hash_tok, try eb.printString( "hash mismatch: manifest declares {s} but the fetched package has {s}", - .{ declared_hash.toSlice(), actual_hex }, + .{ declared, actual_hex }, )); } } else { if (!computed_package_hash.eql(&declared_hash)) { + const declared = if (declared_hash.toSlice().len > 0) declared_hash.toSlice() else ""; return f.fail(hash_tok, try eb.printString( "hash mismatch: manifest declares {s} but the fetched package has {s}", - .{ declared_hash.toSlice(), computed_package_hash.toSlice() }, + .{ declared, computed_package_hash.toSlice() }, )); } } @@ -726,6 +728,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { .hash = h: { const h = dep.hash orelse break :h null; const pkg_hash: Package.Hash = .fromSlice(h); + if (h.len == 0) break :h pkg_hash; const gop = f.job_queue.table.getOrPutAssumeCapacity(pkg_hash); if (gop.found_existing) { if (!dep.lazy) { From 8f7fc63847fd2c2334a13e5dce564942146120c7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 6 Jun 2025 11:13:36 -0700 Subject: [PATCH 2/3] Package.Hash.toSlice: consistent pointer Makes the returned pointer always point inside `Hash.bytes` even when it is length zero. --- src/Package.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Package.zig b/src/Package.zig index aa3a9e3e5d..2eb7321cee 100644 --- a/src/Package.zig +++ b/src/Package.zig @@ -66,11 +66,11 @@ pub const Hash = struct { pub fn toSlice(ph: *const Hash) []const u8 { var end: usize = ph.bytes.len; - while (true) { - if (end == 0) return &.{}; + while (end > 0) { end -= 1; if (ph.bytes[end] != 0) return ph.bytes[0 .. end + 1]; } + return ph.bytes[0..0]; } pub fn eql(a: *const Hash, b: *const Hash) bool { @@ -196,7 +196,7 @@ test Hash { try std.testing.expectEqualStrings("nasm-2.16.1-3-vrr-ygAAoADH9XG3tOdvPNuHen_d-XeHndOG-nNXmved", result.toSlice()); } -test "EmptyHash" { +test "empty hash" { const hash = Hash.fromSlice(""); try std.testing.expectEqualStrings("", hash.toSlice()); } From bc3ce4b9715fc487eddfa1819a252a8fc82a369e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 6 Jun 2025 11:16:44 -0700 Subject: [PATCH 3/3] hash mismatch error: don't make empty such a special case we can more simply use quotes instead --- src/Package/Fetch.zig | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index 9a64bebd99..dbd5896196 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -567,18 +567,16 @@ fn runResource( if (declared_hash.isOld()) { const actual_hex = Package.multiHashHexDigest(f.computed_hash.digest); if (!std.mem.eql(u8, declared_hash.toSlice(), &actual_hex)) { - const declared = if (declared_hash.toSlice().len > 0) declared_hash.toSlice() else ""; return f.fail(hash_tok, try eb.printString( - "hash mismatch: manifest declares {s} but the fetched package has {s}", - .{ declared, actual_hex }, + "hash mismatch: manifest declares '{s}' but the fetched package has '{s}'", + .{ declared_hash.toSlice(), actual_hex }, )); } } else { if (!computed_package_hash.eql(&declared_hash)) { - const declared = if (declared_hash.toSlice().len > 0) declared_hash.toSlice() else ""; return f.fail(hash_tok, try eb.printString( - "hash mismatch: manifest declares {s} but the fetched package has {s}", - .{ declared, computed_package_hash.toSlice() }, + "hash mismatch: manifest declares '{s}' but the fetched package has '{s}'", + .{ declared_hash.toSlice(), computed_package_hash.toSlice() }, )); } }