Skip to documentation
SLOP

tiny.closure.link.cover

Reference tiny.closure link cover

Defined in link.

API (10)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

No direct callersNo direct callslinkcover
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallstest sourcelib.closure.src.link.covertest: coverage attributes every execu...test sourcelib.closure.src.link.covertest: coverage fails closed on foreig...private sourcelib.closure.src.link.coveraddedprivate sourcelib.closure.src.link.coverappendPaddingprivate sourcelib.closure.src.link.coversortprivate sourcelib.closure.src.link.covertakeprivate sourcelib.closure.src.link.covertoOffsetprivate sourcelib.closure.src.link.covervalidateAttributionslink.coververify
Static calls · unresolved targets: 1 · external targets: 1.

Source: lib/closure/src/link/cover.zig

zig
const binary = @import("../binary/root.zig");const std = @import("std");pub const attributions_max: usize = 64;pub const padding_ranges_max: usize = 64;pub const Kind = enum(u8) {    root,    primitive,};pub const Attribution = struct {    kind: Kind,    offset: u64,    address: u64,    length: u64,    source_offset: u64 = 0,    relocation_count: u32 = 0,    source_sha256: [32]u8,};pub const Padding = struct {    offset: u64,    address: u64,    length: u16,};pub const Policy = struct {    padding_bytes_max: u16 = 15,    padding_byte: u8 = 0xcc,};pub const Scratch = struct {    ordered: []Attribution,    padding: []Padding,};pub const Report = struct {    attributions: []const Attribution,    padding: []const Padding,    root_bytes: u64,    primitive_bytes: u64,    padding_bytes: u64,    executable_bytes: u64,    executable_sha256: [32]u8,    work: u64,};const CoverError = error{    AttributionCapacityExceeded,    AttributionDigestMissing,    AttributionOutsideExecutable,    AttributionOverlap,    ExecutableCoverageMissing,    PaddingCapacityExceeded,    PaddingInvalid,};pub const Error = binary.strict.Error || CoverError;pub fn verify(    bytes: []const u8,    image: binary.strict.Report,    input: []const Attribution,    policy: Policy,    scratch: Scratch,) Error!Report {    if (input.len > scratch.ordered.len or        input.len > attributions_max or        scratch.padding.len > padding_ranges_max)    {        return error.AttributionCapacityExceeded;    }    @memcpy(scratch.ordered[0..input.len], input);    const ordered = scratch.ordered[0..input.len];    sort(ordered);    var work: u64 = input.len;    try validateAttributions(image, ordered, &work);    var padding_count: usize = 0;    var root_bytes: u64 = 0;    var primitive_bytes: u64 = 0;    var padding_bytes: u64 = 0;    var executable_bytes: u64 = 0;    var attributed_count: usize = 0;    var hasher = std.crypto.hash.sha2.Sha256.init(.{});    for (image.loads) |load| {        if (!load.executable) continue;        const start = toOffset(load.offset) catch            return error.AttributionOutsideExecutable;        const length = toOffset(load.content_bytes) catch            return error.AttributionOutsideExecutable;        const contents = try take(bytes, start, length);        hasher.update(contents);        executable_bytes = try added(executable_bytes, load.content_bytes);        var cursor = load.offset;        const end = try added(load.offset, load.content_bytes);        for (ordered) |attribution| {            work += 1;            if (attribution.offset < load.offset or                attribution.offset >= end)            {                continue;            }            const gap = attribution.offset - cursor;            if (gap != 0) {                try appendPadding(                    bytes,                    load,                    cursor,                    gap,                    policy,                    scratch.padding,                    &padding_count,                    &padding_bytes,                    &work,                );            }            switch (attribution.kind) {                .root => root_bytes =                    try added(root_bytes, attribution.length),                .primitive => primitive_bytes =                    try added(primitive_bytes, attribution.length),            }            cursor = try added(attribution.offset, attribution.length);            attributed_count += 1;        }        if (cursor < end) {            try appendPadding(                bytes,                load,                cursor,                end - cursor,                policy,                scratch.padding,                &padding_count,                &padding_bytes,                &work,            );        }        if (cursor > end) return error.AttributionOverlap;    }    if (attributed_count != ordered.len) {        return error.AttributionOutsideExecutable;    }    const accounted = try added(        try added(root_bytes, primitive_bytes),        padding_bytes,    );    if (accounted != executable_bytes) {        return error.ExecutableCoverageMissing;    }    var digest: [32]u8 = undefined;    hasher.final(&digest);    return .{        .attributions = ordered,        .padding = scratch.padding[0..padding_count],        .root_bytes = root_bytes,        .primitive_bytes = primitive_bytes,        .padding_bytes = padding_bytes,        .executable_bytes = executable_bytes,        .executable_sha256 = digest,        .work = work,    };}fn validateAttributions(    image: binary.strict.Report,    ordered: []const Attribution,    work: *u64,) Error!void {    var previous_end: u64 = 0;    for (ordered, 0..) |attribution, index| {        work.* += 1;        if (attribution.length == 0 or            !digestKnown(attribution.source_sha256))        {            return error.AttributionDigestMissing;        }        if (index != 0 and attribution.offset < previous_end) {            return error.AttributionOverlap;        }        const end = try added(attribution.offset, attribution.length);        var admitted = false;        for (image.loads) |load| {            work.* += 1;            if (!load.executable) continue;            const load_end = try added(load.offset, load.content_bytes);            if (attribution.offset < load.offset or end > load_end) continue;            const relative = attribution.offset - load.offset;            if (attribution.address != try added(load.address, relative)) {                return error.AttributionOutsideExecutable;            }            admitted = true;            break;        }        if (!admitted) return error.AttributionOutsideExecutable;        previous_end = end;    }}fn appendPadding(    bytes: []const u8,    load: binary.strict.Load,    offset: u64,    length: u64,    policy: Policy,    output: []Padding,    count: *usize,    total: *u64,    work: *u64,) Error!void {    if (length == 0 or length > policy.padding_bytes_max) {        return error.PaddingInvalid;    }    if (count.* == output.len) return error.PaddingCapacityExceeded;    const start = toOffset(offset) catch return error.PaddingInvalid;    const length_usize = toOffset(length) catch return error.PaddingInvalid;    const contents = try take(bytes, start, length_usize);    for (contents) |byte| {        work.* += 1;        if (byte != policy.padding_byte) return error.PaddingInvalid;    }    output[count.*] = .{        .offset = offset,        .address = try added(load.address, offset - load.offset),        .length = @intCast(length),    };    count.* += 1;    total.* = try added(total.*, length);}fn sort(values: []Attribution) void {    var index: usize = 1;    while (index < values.len) : (index += 1) {        const value = values[index];        var cursor = index;        while (cursor > 0 and values[cursor - 1].offset > value.offset) {            values[cursor] = values[cursor - 1];            cursor -= 1;        }        values[cursor] = value;    }}fn digestKnown(digest: [32]u8) bool {    for (digest) |byte| {        if (byte != 0) return true;    }    return false;}fn take(    bytes: []const u8,    offset: usize,    length: usize,) Error![]const u8 {    const end = std.math.add(usize, offset, length) catch        return error.BinaryArithmeticOverflow;    if (end > bytes.len) return error.TruncatedBinary;    return bytes[offset..end];}fn toOffset(value: u64) Error!usize {    return std.math.cast(usize, value) orelse        error.BinaryArithmeticOverflow;}fn added(left: anytype, right: anytype) Error!u64 {    return std.math.add(        u64,        @intCast(left),        @intCast(right),    ) catch error.BinaryArithmeticOverflow;}test "coverage attributes every executable byte with bounded padding" {    var bytes: [32]u8 = @splat(0);    @memset(bytes[4..8], 0x11);    @memset(bytes[8..11], 0xcc);    @memset(bytes[11..15], 0x22);    const loads = [_]binary.strict.Load{.{        .offset = 4,        .address = 0x1000,        .file_bytes = 16,        .content_bytes = 11,        .memory_bytes = 16,        .readable = true,        .writable = false,        .executable = true,    }};    const image = binary.strict.Report{        .kind = .elf64,        .loads = &loads,        .relocations = &.{},        .executable_bytes = 11,        .initialized_bytes = 0,        .memory_bytes = 16,        .stack_bytes = 0,        .timestamp = 0,        .image_base = 0,        .work = 1,    };    const digest: [32]u8 = @splat(1);    const input = [_]Attribution{        .{            .kind = .primitive,            .offset = 11,            .address = 0x1007,            .length = 4,            .source_sha256 = digest,        },        .{            .kind = .root,            .offset = 4,            .address = 0x1000,            .length = 4,            .source_sha256 = digest,        },    };    var ordered: [2]Attribution = undefined;    var padding: [1]Padding = undefined;    const report = try verify(        &bytes,        image,        &input,        .{},        .{ .ordered = &ordered, .padding = &padding },    );    try std.testing.expectEqual(@as(u64, 4), report.root_bytes);    try std.testing.expectEqual(@as(u64, 4), report.primitive_bytes);    try std.testing.expectEqual(@as(u64, 3), report.padding_bytes);    try std.testing.expectEqual(@as(u64, 11), report.executable_bytes);}test "coverage fails closed on foreign and excessive gaps" {    var bytes: [32]u8 = @splat(0xcc);    const loads = [_]binary.strict.Load{.{        .offset = 4,        .address = 0x1000,        .file_bytes = 16,        .content_bytes = 16,        .memory_bytes = 16,        .readable = true,        .writable = false,        .executable = true,    }};    const image = binary.strict.Report{        .kind = .elf64,        .loads = &loads,        .relocations = &.{},        .executable_bytes = 16,        .initialized_bytes = 0,        .memory_bytes = 16,        .stack_bytes = 0,        .timestamp = 0,        .image_base = 0,        .work = 1,    };    const digest: [32]u8 = @splat(1);    const input = [_]Attribution{.{        .kind = .root,        .offset = 4,        .address = 0x1000,        .length = 1,        .source_sha256 = digest,    }};    var ordered: [1]Attribution = undefined;    var padding: [1]Padding = undefined;    try std.testing.expectError(        error.PaddingInvalid,        verify(            &bytes,            image,            &input,            .{ .padding_bytes_max = 14 },            .{ .ordered = &ordered, .padding = &padding },        ),    );    bytes[5] = 0x90;    const full = [_]Attribution{.{        .kind = .root,        .offset = 6,        .address = 0x1002,        .length = 14,        .source_sha256 = digest,    }};    try std.testing.expectError(        error.PaddingInvalid,        verify(            &bytes,            image,            &full,            .{},            .{ .ordered = &ordered, .padding = &padding },        ),    );}

Source: lib/closure/src/link/root.zig:1

zig
pub const cover = @import("cover.zig");

Audit

Definitions11
Public names20
Members24
Version26.7.0
Revisiondaab053ee433