aboutsummaryrefslogtreecommitdiff
path: root/test/behavior/bugs/6781.zig
blob: d35612b6956a489be06e57cc29ecf1bdc8d99c56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
const builtin = @import("builtin");
const std = @import("std");
const assert = std.debug.assert;

const segfault = true;

pub const JournalHeader = packed struct {
    hash_chain_root: u128 = undefined,
    prev_hash_chain_root: u128,
    checksum: u128 = undefined,
    magic: u64,
    command: u32,
    size: u32,

    pub fn calculate_checksum(self: *const JournalHeader, entry: []const u8) u128 {
        assert(entry.len >= @sizeOf(JournalHeader));
        assert(entry.len == self.size);

        const checksum_offset = @offsetOf(JournalHeader, "checksum");
        const checksum_size = @sizeOf(@TypeOf(self.checksum));
        assert(checksum_offset == 0 + 16 + 16);
        assert(checksum_size == 16);

        var target: [32]u8 = undefined;
        std.crypto.hash.Blake3.hash(entry[checksum_offset + checksum_size ..], target[0..], .{});
        return @bitCast(u128, target[0..checksum_size].*);
    }

    pub fn calculate_hash_chain_root(self: *const JournalHeader) u128 {
        const hash_chain_root_size = @sizeOf(@TypeOf(self.hash_chain_root));
        assert(hash_chain_root_size == 16);

        const prev_hash_chain_root_offset = @offsetOf(JournalHeader, "prev_hash_chain_root");
        const prev_hash_chain_root_size = @sizeOf(@TypeOf(self.prev_hash_chain_root));
        assert(prev_hash_chain_root_offset == 0 + 16);
        assert(prev_hash_chain_root_size == 16);

        const checksum_offset = @offsetOf(JournalHeader, "checksum");
        const checksum_size = @sizeOf(@TypeOf(self.checksum));
        assert(checksum_offset == 0 + 16 + 16);
        assert(checksum_size == 16);

        assert(prev_hash_chain_root_offset + prev_hash_chain_root_size == checksum_offset);

        const header = @bitCast([@sizeOf(JournalHeader)]u8, self.*);
        const source = header[prev_hash_chain_root_offset .. checksum_offset + checksum_size];
        assert(source.len == prev_hash_chain_root_size + checksum_size);
        var target: [32]u8 = undefined;
        std.crypto.hash.Blake3.hash(source, target[0..], .{});
        if (segfault) {
            return @bitCast(u128, target[0..hash_chain_root_size].*);
        } else {
            var array = target[0..hash_chain_root_size].*;
            return @bitCast(u128, array);
        }
    }

    pub fn set_checksum_and_hash_chain_root(self: *JournalHeader, entry: []const u8) void {
        self.checksum = self.calculate_checksum(entry);
        self.hash_chain_root = self.calculate_hash_chain_root();
    }
};

test "fixed" {
    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_arm) return error.SkipZigTest; // TODO
    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO

    var buffer align(@alignOf(JournalHeader)) = [_]u8{0} ** 65536;
    var entry = std.mem.bytesAsValue(JournalHeader, buffer[0..@sizeOf(JournalHeader)]);
    entry.* = .{
        .prev_hash_chain_root = 0,
        .magic = 0,
        .command = 0,
        .size = 64 + 128,
    };
    entry.set_checksum_and_hash_chain_root(buffer[0..entry.size]);
    try std.io.null_writer.print("{}\n", .{entry});
}