An AMD Ryzen booted to a working compositor with no USB and no storage, and the log said only "register refused". A tree-wide audit of every compile-time ceiling followed: 235 of them, 139 on quantities the machine or a file decides rather than us, 5 documented anywhere, 171 silent when reached. docs/fixed-bounds-audit.md has the inventory. Errno attribution. The errno space was split between the kernel and the envelope, free to drift; it is now one list in system/abi.zig, restated on both sides, with a comptime check in library/device/driver where the two halves are visible. device_register's six refusals and device_claim's three are distinct codes, so a bus driver can say which rule stopped it, and BadParent splits into NoSuchParent and NotYourParent. pci-bus reconciles found against registered instead of counting refused functions as found. Idempotency ordering. The child cap was checked before the identity match, so a restarted bus was refused its own devices — the supervision restart the system leans on ratcheted toward a degraded machine. A re-registration consumes no slot and is now admitted first. IOMMU fail-closed. confineDevice returned success for a device id past the confinement table, leaving the device outside every domain while the caller believed it confined — unreachable only while ids stop at 64, which both the inventory move and a hardware-reported domain count would change. It refuses now, and the coupling to the broker's device cap is a comptime assert rather than a sentence in a comment. PCI apertures. The bridge's MMIO apertures are derived from the holes in the firmware memory map, and the derivation copied sub-4 GiB entries into a fixed [64] array and skipped the rest. A skipped region is not merely lost: the gap finder concludes it is free, so a real machine's 60-200 entry map yields an aperture over live RAM, and containment then admits a child BAR covering kernel memory. Rewritten to walk the map in place, with the hole finder extracted as a pure function and driven by a synthetic 100-entry map in a new test case. Both new tests were verified to fail on the old code. parameters.zig gains the rationale it was missing and loses a stale sentence pointing at the wrong file; vdso.md documents the errno space, including EPEER, which had no written meaning anywhere. docs/os-development/bounds.md is how a ceiling is declared from here. docs/bounds-track-plan.md is the plan to remove the ones we invented. Suite 114 -> 115.
92 KiB
Fixed-bounds audit
2026-08-07. A tree-wide audit of every compile-time ceiling on a runtime quantity, commissioned after an AMD Ryzen desktop booted to a working compositor with no USB and no storage. Seven parallel sweeps, adversarial verification of each finding, and a completeness critic. 235 bounds confirmed.
The audit was not commissioned to fix that machine. It was commissioned to answer a different question: why did a machine have to find this? The answer is in the first table below, and it is not that anyone failed to predict an AMD desktop.
What the audit found
| Bounds confirmed | 235 |
| Decided by hardware or external data, not by us | 139 (59%) |
Recorded in system/parameters.zig |
5 (2%) |
| With no comment explaining the number at all | 97 (41%) |
| Silent when exceeded — no log, no counter, no error | 171 (73%) |
| Severity critical / high | 17 / 26 |
The project has a stated convention: tunables live in system/parameters.zig with
their reasoning attached. Two percent of them do. That is the finding — not any
individual number.
And 59% of these are not tunables at all. They are guesses about someone else's computer: how many PCI functions a board has, how many SSDTs its firmware ships, how many descriptors its memory map carries, how many interfaces a USB headset declares. A fixed bound on a quantity the machine decides is not a knob. It is a defect with a plausible-looking number in it.
Why "raise the number" is not available
This is the part that matters most, and it was found by the completeness critic rather than by any of the seven sweeps.
system/kernel/iommu.zig:97 sizes the per-device confinement table by
maximum_domains = 64 — "64 mirrors devices-broker's device cap" — and indexes it
by device id. Line 107:
pub fn confineDevice(device_id: u64, bdf: u16, owner: u32) bool {
if (!active) return true;
if (device_id >= confined.len) return true; // unusual id; leave it to fail-open
It returns true — success — without confining the device. The doc comment three
lines above states the opposite invariant: "a claim that can't be confined must not
stand."
Device ids are assigned d.id = count with count < maximum_devices, so today ids
run 0–63 and that branch is unreachable. It becomes reachable the moment
maximum_devices is raised above 64. Every device with id ≥ 64 would then be
claimed by a ring-3 driver, reported as successfully confined, and left outside every
IOMMU domain — an unconfined DMA master with a driver holding it.
So the one-line fix for the Ryzen — raise 64 to 512 — is a privilege escalation. Not inelegant: escalating. Nothing in the type system, the tests or the comments would have caught it, because the two constants agree only by a sentence in a comment.
The Ryzen was three bugs, not one
Each of these independently produces "the xHCI and SATA controllers are missing." Fixing any one of them leaves the machine broken by the next.
devices-broker.zig:33,maximum_children_per_parent = 16—pci-busregisters every discovered function as a direct child of the one host bridge, so 16 is the ceiling on PCI functions for the whole machine. Enumeration runs in bus/device/function order, so low-numbered chipset functions consume all 16 and the high-numbered controllers — xHCI at 0x14, SATA at 0x17 — are refused. This is the one that fired.device-manager.zig:174,maximum_children = 64— the userspace inventory has its own flat table. ACPI contributes ~34 nodes before PCI is scanned. Refusal returns-ENOSPC, whichpci-bus.zig:246discards andacpi.zig:257swallows in an emptycatch {}. The log line "child added" is printed before the status is consulted, so the log says the device was added when it was not.acpi.zig:651,gaps = [3]Range— only three sub-4 GiB MMIO holes become PCI bridge apertures. A BAR landing in a fourth hole fails containment and is refused, indistinguishably from a full table.
Three ceilings, three teams of one, one symptom. "Raise the limit" would have moved the failure to the next one and produced a second debugging session from a second photograph.
Two latent security findings
acpi.zig:627, below = [64]Range. Firmware memory-map entries below 4 GiB, used
to derive the PCI bridge's apertures from the gaps between described regions. Past the
64th entry: continue. A dropped region is not merely missing — it vanishes from the
"described space" the gap-finder subtracts, so occupied physical memory is concluded to
be a free MMIO hole and registered as a bridge aperture. devices-broker.contains()
then admits a child BAR covering RAM, and its claimant can mmio_map it: a ring-3
read/write window onto kernel memory. Real UEFI maps carry 60–200 descriptors; OVMF
carries 15–25, which is why the suite has never approached it.
devices-broker.zig:217, the PCI requester id is a u16 with no segment field,
propagated unbroken into both IOMMU backends. On a multi-segment machine two physically
distinct functions alias onto one translation structure.
Both are the same shape as the finding above: a bound whose failure mode is not "we run out" but "the protection silently stops applying."
Bugs found in passing
Not bounds, but found by looking at what happens at the bound:
usb-xhci-library.zig:1331—else if (device.interface_count < max_interfaces)has noelse, so at the limitcurrentis left pointing at interface 3 and the 5th interface's endpoints are appended to interface 3's array. A class driver bound to interface 3 can be handed an endpoint belonging to another interface. The alternate-setting arm one line above doescurrent = nullcorrectly.usb-xhci-library.zig:899/1102—allocateDevice()failing returns afterenableSlot()already succeeded, with no Disable Slot. Every failed attempt permanently leaks a controller slot.acpi.zig:445— the AML loop reservesmaximum_resources - 2slots and the function then adds four more resources. At 5 AML blocks the FADT is lost; at 6+ the broad IRQ window is lost too, so every legacy-IRQ device (PS/2 keyboard at IRQ 1) fails containment. Real firmware ships 5–15 SSDTs; QEMU ships 2.fat.zig:252— au64protocol offset reaches au32engine parameter through a bare@intCast. In ReleaseSafe — this project's build mode — that panics.boot/efi.zig:318— the bootstrap page tables map [0, 4 GiB) and nothing checks that the handoff buffers UEFI allocated (BootInformation, the memory-map pool, the initial ramdisk) landed below it. Several firmware implementations allocate top-down. Above 4 GiB it is a triple fault with no output at all.
Headroom actually measured
Every other bound here is hypothetical. One is a schedule:
system/configuration/protocol.csv, the manifest deciding which binary may bind which
protocol name, is at 50 of 64 grant rows and 12,668 of 16,384 bytes — 78% and 77%.
To its credit, both overflow paths log (init.zig:147 and :238). It will fail
loudly. It will still fail.
The rule this suggests
The audit's own exemplar turned out to be broken, which is worth recording. Two sweeps
held up devices_broker.dropped as the model the others should be rewritten against.
It is not: register() never increments it, and kernel.zig:203 reads it once at boot
before seedDisplay and long before any ring-3 driver exists. It can only report
firmware-discovery losses — precisely the opposite of the runtime case under audit.
parameters.maximum_cpus is the one bound that meets the standard: hardware-determined
and bounded, but it states what happens to the surplus (parked) and how you find out
(platform.cpusDropped() → a WARNING at kernel.zig:281). Verified.
So:
- A fixed bound on a quantity the hardware or an external file decides is a defect, not a tunable. It does not need a better number; it needs to not be fixed. This covers 139 of the 235.
- A bound that must exist states three things: what it protects against, what the system does when it is reached, and how an operator finds out. One of 235 does.
- Refusal must be attributable.
process.zig:944collapses five distinctRegisterErrorvariants into a bare-1;pci-buscan only log "register refused" with no reason. Half this audit's difficulty was that the machine could not say which ceiling it hit. - Two constants that must agree may not agree by comment.
maximum_domains = 64andmaximum_devices = 64are coupled by prose, and the coupling fails open.
Appendix: the inventory
Sorted by severity, then file. Decided by is the audit's judgment of who chooses the
quantity — the machine, an external file or peer, or us.
| File:line | Bound | Value | Decided by | At the limit | Observable |
|---|---|---|---|---|---|
boot/efi.zig:318 |
(4 * gib) | 4 GiB | hardware | No check exists. buildBootstrapTables maps [0, 4 GiB) as identity + physmap 2 MiB leaves and stops; the only carve-out is the framebuffer window at ef… | Nothing on this path. No log, no error, no panic. The last thing printed is the unconditional con_out line at … |
library/device/model/device-abi.zig:81 |
maximum_device_resources | 8 | hardware | Silent drop, but at a different site than claimed. The live enforcement is system/kernel/device-model.zig:114 `if (self.resource_count >= maximum_reso… | None on any drop path, and the code says otherwise: device-model.zig:111-112 claims "Silently drops beyond `ma… |
system/drivers/pci-bus/pci-bus.zig:228 |
device.register refusal path (kernel maximum_chi… | 16 children per parent / 64 … | hardware | system/kernel/devices-broker.zig:305 if (childCount(parent_id) >= maximum_children_per_parent) return error.TooManyChildren; and :306 `if (count >= … |
One line per lost function: std.log.info("register refused for {d}:{d}.{d}", .{ bus, dev, function }) (pci-b… |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:227 |
max_interfaces | 4 | external-data | CORRECTION to this claim's description: it is not only a silent drop. parseConfiguration (1326-1342) has no else on `else if (device.interface_count… |
None. usb-xhci-bus.zig:368/425 log {d} interface(s) with the truncated count; nothing says any were dropped … |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:333 |
max_devices | 8 | hardware | Two different behaviours, exactly as claimed. Root port, setupDevice (899-902): `const device = self.allocateDevice() orelse { std.log.info("port {d… |
Root ports: one log line. Hub-attached: nothing. I confirmed the leak is real — the only Disable Slot in the f… |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:1304 |
blob: [512]u8 | 512 | external-data | Silent truncation of device-supplied data. Lines 1304-1307: `var blob: [512]u8 = undefined; const length = @min(configuration.total_length, blob.len);… | None. configuration.total_length is read at 1299 and never compared to blob.len, never logged. The `{d} in… |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:1305 |
blob (inline [512]u8, declared line 1304) | 512 bytes | external-data | Silent truncation of externally-supplied data. The @min clamps the GET_DESCRIPTOR request to 512; parseConfiguration then walks it and stops dead at l… | Nothing. No log line, no counter, no comparison of configuration.total_length against blob.len. The symptom is… |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:1331 |
max_interfaces (= 4), used as `else if (device.i… | 4 | external-data | CORRUPTING, not merely dropping. When interface_count == 4, neither branch of the if/else-if runs, so current is NOT cleared — it still points at in… |
Nothing. No log, no counter, no error. The device enumerates, port N device: ... 4 interface(s) is logged (a… |
system/kernel/acpi.zig:445 |
device_model.maximum_resources … | 6 AML blocks, inside an 8-re… | hardware | Silent double loss. The loop stops at 6 blocks, so SSDTs 7+ are never published. Then acpi.zig:454-463 adds the io_port grant (7th), the SCI irq (8th)… | Nothing at all. No counter, no log, no error. The ring-3 acpi service simply finds an acpi-tables node without… |
system/kernel/acpi.zig:445 |
device_model.maximum_resources - 2 (inline expre… | 6 AML blocks, out of 8 total… | hardware | Silent drop, then a silent cascade. Resources are appended in order: up to 6 AML memory resources (445-448), io_port (454), the SCI irq (459), the bro… | Nothing at the kernel. The only downstream trace is the acpi service writing "acpi: no FADT on the node — powe… |
system/kernel/acpi.zig:627 |
below | [64]Range | hardware | Silent skip: if (region.base >= (1 << 32) or below_count == below.len) continue;. Every region past the 64th is treated as 'not described', i.e. as … |
None directly, though kernel.zig:133 does print " regions : {d} - entries in the firmware memory map", w… |
system/kernel/acpi.zig:627 |
below (inline [64]Range) | 64 entries | hardware | Silent drop, and — worse than a drop — a corrupted result. A dropped region is not merely missing from the list; it disappears from the "described spa… | Nothing at all. No counter, no log line. The kernel prints the device tree including the bogus aperture, with … |
system/kernel/acpi.zig:651 |
gaps | [3]Range | hardware | Silent replacement of the smallest kept gap (acpi.zig:658-664): a fourth (or fifth) MMIO hole is simply forgotten. A PCI function whose BAR lands in a… | Nothing. No log, no counter, and the resulting failure is indistinguishable at the caller from a table-full re… |
system/kernel/device-model.zig:66 |
maximum_resources | 8 | external-data | addResource (line 113-118) returns false without recording. I grepped every call site: system/kernel/acpi.zig lines 448, 454, 459, 460, 463, 552, 55… |
Nothing at the drop. Downstream there are two ring-3 lines that name the symptom and misattribute the cause: s… |
system/kernel/devices-broker.zig:33 |
maximum_children_per_parent | 16 | hardware | Confirmed at devices-broker.zig:305: if (childCount(parent_id) >= maximum_children_per_parent) return error.TooManyChildren;, where childCount (28… |
One reasonless line per lost device, and nothing from the kernel. Confirmed at pci-bus.zig:228-231: `const reg… |
system/services/acpi/acpi.zig:129 |
blocks | [8][]const u8 | external-data | The blocks: [8][]const u8 array at line 129 and its if (block_count == blocks.len) continue; at line 152 are dead — they can never fire, because t… |
Only an indirect count that cannot reveal the loss: `std.log.info("parsed {d} AML blob(s), {d} namespace devic… |
system/services/device-manager/device-manager.zig:174 |
maximum_children | 64 | hardware | Silent drop with a misleading log. addChild (180-194) returns false when no free slot exists. onChildAdded (442-452): `if (!addChild(...)) status … |
Effectively none, and actively misleading. The -ENOSPC goes back to the bus driver, which discards it — verifi… |
boot/efi.zig:108 |
(handles[0]) | 1 | hardware | Silent selection of GOP handle 0, and the two halves genuinely disagree — nativeResolution (efi.zig:167-176) iterates for (handles) |h| over every… |
Nothing. No log names the handle count, the chosen adapter, or the resolved mode; the only con_out writes in t… |
library/device/driver/driver.zig:149 |
@min(total, buffer.len) | hardware | Silently searches a prefix: `const total = enumerate(buffer); const n = @min(total, buffer.len); for (@as([]DeviceDescriptor, buffer[0..n])) |d| { …… | Nothing. The discarded total is the only evidence that the buffer was too small, and it is thrown away on th… |
|
library/kernel/file-system.zig:227 |
Entry.name_buffer | [64]u8 | external-data | Silent truncation on both readdir paths, exactly as claimed. Backend path, Directory.next line 264-266: `const nlen = @min(@min(@as(usize, header.name… | Nothing. No log, no flag, no short-count anywhere in library/kernel/file-system.zig. Entry.name() returns a pl… |
system/drivers/virtio-gpu/virtio-gpu.zig:49 |
max_width / max_height (line 50) | 800 x 600 | hardware | Two distinct behaviours, and the claim conflates their visibility. (a) onSetMode, line 533-540: `if (w == 0 or h == 0 or w > max_width or h > max_heig… | Partial and misleading, as claimed. Confirmed the two adjacent lines: `std.log.info("EDID preferred mode {d}x{… |
system/kernel/architecture/x86_64/cpu.zig:489 |
irq_vector_count | 14 | hardware | irq.zig:138 allocVector() scans base..base+count for a vector free of both an MSI binding and a GSI binding and returns null when none is; bind (irq.z… | No kernel log line. Driver-side, both messages verified: usb-xhci-bus.zig:279 `std.log.info("msi_bind unavaila… |
system/kernel/architecture/x86_64/idt.zig:17 |
gate_count | 48 | our-design | Nothing is enforced at this line. pub fn init() at line 136 does `inline for (0..gate_count) |vector| { const stub = @extern(*const anyopaque, .{ … |
None at runtime. The bound only ever becomes visible as the vector-exhaustion path in irq.zig, which each driv… |
system/kernel/architecture/x86_64/ioapic.zig:21 |
base (module-level singleton) | 1 I/O APIC | hardware | Confirmed exactly. system/kernel/acpi.zig:547-556 adds EVERY MADT I/O APIC record to the device tree as ioapic0, ioapic1, ...; kernel.zig:545-548 then… | None. No log counts the discarded units, unlike the neighbouring drop counters that ARE logged (devices_broker… |
system/kernel/architecture/x86_64/iommu-amd.zig:56 |
ring_entries (event log) | 256 | hardware | Confirmed. faultDrain (lines 180-198) reads EventHead/EventTail, walks the ring wrapping at if (head >= ring_entries * 16) head = 0;, and writes the… |
None. I grepped the file: const reg_status = 0x2020; appears at line 32 and at NO other line — it is declare… |
system/kernel/architecture/x86_64/iommu-intel.zig:102 |
16 * 1024 | 16384 (bytes of VT-d registe… | hardware | No check. faultDrain computes frcd_base = fro*16 with fro up to 0x3FF (16368 bytes) and nfr = ((cap >> 40) & 0xFF) + 1 up to 256 registers of 16… |
A kernel-mode #PF: the fault handler reports the vector/CR2 and halts the core. Loud, but reported as a page f… |
system/kernel/architecture/x86_64/iommu.zig:17 |
Discovery.register_base (single unit) | 1 IOMMU unit | hardware | Confirmed. pub const Discovery = struct { register_base: u64, amd: bool }; at iommu.zig:16-19 carries exactly one base. Intel (acpi.zig:826-852): th… |
Asymmetric, exactly as claimed. Intel warns: system/kernel/iommu.zig:395-396 `if (info.iommu_extra_units > 0) … |
system/kernel/devices-broker.zig:25 |
maximum_devices | 64 | hardware | Three inconsistent behaviours, all confirmed. Boot discovery: devices-broker.zig:111-114 `if (count >= maximum_devices) { dropped += 1; return device_… | Partial and aimed at the wrong path, exactly as claimed. kernel.zig:203-206 prints `"/system/kernel: WARNING {… |
system/kernel/iommu.zig:43 |
maximum_domains | 64 | hardware | Two behaviours. Domain exhaustion is safe: domainCreate returns null → confineDevice false → process.zig:418-420 rolls the claim back and returns … |
The rollback path is visible as a failed device_claim. The fail-open path is completely silent — no log, no … |
system/kernel/irq.zig:43 |
maximum_gsi | 24 | hardware | Refusal at three places, all becoming a bare -1. irq.zig:158 if (gsi >= maximum_gsi or !architecture.irqOwnsGsi(gsi)) return error.BadGsi; -> proces… |
Nothing in the kernel, but every caller logs: ps2-bus.zig:246 and :265, acpi.zig:315 "acpi: SCI irq_bind faile… |
system/kernel/irq.zig:139 |
allocVector over architecture.irq_vector_count | 14 (vectors 33..46, from arc… | hardware | fn allocVector() ?u8 (line 139) scans v in [irq_vector_base, irq_vector_base + irq_vector_count) = [33, 47) — 14 vectors — and returns null when all… |
Better than claimed at the driver level, absent at the kernel level. The kernel logs nothing and has no counte… |
system/kernel/process.zig:546 |
maximum_dma_regions | 256 | hardware | Confirmed, and the safety-invariant break is real. process.zig:549-556 `fn dmaRegistryAdd(object: ?*ipc.DmaRegionObject, physical: u64, len: u64, owne… | None whatsoever — confirmed. dma_alloc returns success, no log, no counter, no failed syscall. The symptom i… |
system/kernel/scheduler.zig:546 |
maximum_tasks (via freeSlot in secondaryMain) | 48 (parameters.maximum_tasks… | hardware | Confirmed: const t = freeSlot() orelse @panic("sched: task table full (AP idle task)"); at scheduler.zig:546, reached from secondaryMain with the … |
A named panic on console/serial — loud, but the machine is dead and the message points at the task table rathe… |
system/kernel/vfs.zig:58 |
maximum_mounts | 8 | our-design | FALSE SUCCESS plus a reference leak, confirmed end to end. installMount, vfs.zig:182: const m = slot orelse return; — it gives up silently when no s… |
Worse than nothing: the syscall reports success, so the mounting service logs its own success — system/service… |
system/kernel/vfs.zig:86 |
maximum_directories | 8 | external-data | Silent skip inside the boot walk: if (directoryIndex(parent) == null and directory_count < maximum_directories) (vfs.zig:141). An unregistered direc… |
Nothing. No log, no counter, no dropped variable of the kind acpi.zig:542 and the device manager both mainta… |
system/kernel/vfs.zig:141 |
maximum_directories (declared line 86) | 8 | external-data | Silent drop with a mount-level knock-on, confirmed. The ninth distinct ancestor is skipped by the guard at vfs.zig:141; it then fails to resolve (reso… | Nothing — no counter, no log line, no dropped variable of the sort acpi.zig:542 (cpu_information.dropped, pr… |
system/kernel/vfs.zig:182 |
maximum_mounts (declared line 58) | 8 | our-design | False success, confirmed: installMount gives up at vfs.zig:182 (const m = slot orelse return;) and mountBackend returns true regardless at vfs.zig:3… |
Nothing in the kernel. The mounting service logs its own success — fat.zig:173/:178/:183 all `std.log.info("mo… |
system/services/acpi/acpi.zig:542 |
buffer (readHid) / Registered.hid / Notice.hid | [8]u8 | external-data | Both failures confirmed. (a) readHid (lines 540-566) accepts only an integer _HID it can EISA-decode: a method result must be .integer, and a static… |
None for (a): a skipped device produces no line at all. For (b) the log at line 408, `std.log.info("power: not… |
system/services/acpi/acpi.zig:648 |
descriptor.resources.len | 8 (maximum_device_resources,… | external-data | Silent drop of the surplus. `fn addResource(descriptor: *device.DeviceDescriptor, kind: device.ResourceKind, start: u64, len: u64) void { if (descript… | Nothing at the drop. The only echo is the per-device summary at line 241, `std.log.info("device {d} bus=acpi … |
system/services/device-manager/device-manager.zig:149 |
maximum_drivers | 16 | hardware | addDriver (240-254) walks for a free slot and, finding none, falls through the loop to `std.log.info("driver table full; cannot supervise {s}", .{na… |
One log line only (quoted above). No counter, no status to any caller, and it lands amid the stream of `child … |
system/services/device-manager/device-manager.zig:358 |
64 | hardware | Silent truncation. Line 362-363: const total = device.enumerate(buffer); const count = @min(total, buffer.len); — the difference is computed and thr… |
Nothing. No log mentions total. The only related line, `"/system/services/device-manager: no matchable devic… |
|
system/services/fat/fat.zig:73 |
open_nodes | 32 | our-design | An error is returned, but a maximally confusing one: const index = allocOpen() orelse return refused; (line 242), where refused is `-envelope.ENOE… |
Nothing on the server side — no log at all in allocOpen or onOpen. The client sees ENOENT and will report "fil… |
system/services/fat/fat.zig:252 |
u32 (via @intCast of a u64 p… | external-data | Panic. vfs_protocol.Read.offset is a u64 (library/protocol/vfs/vfs-protocol.zig:82-86) and engine.readFile takes offset: u32; the bridge is a … |
A process fault and whatever the supervisor logs about the death; nothing identifies the offending request or … | |
boot/efi.zig:371 |
maximum_bundled | 64 | external-data | Two different behaviours for one constant, confirmed. loadByManifest (efi.zig:507): if (count.* == maximum_bundled) return; — silent success with th… |
Manifest path: nothing. Walk path: the unconditional con_out line at efi.zig:71-75, `log("EFI: no /system bina… |
boot/efi.zig:375 |
maximum_tree_depth | 3 | our-design | if (depth == maximum_tree_depth) continue; (efi.zig:580) — the subdirectory is silently skipped and nothing beneath it is bundled. No error, no coun… |
Nothing. The boot proceeds; the missing binary surfaces much later as an init spawn failure or a device-manage… |
boot/efi.zig:507 |
maximum_bundled (declared line 371) | 64 | external-data | As described and verified: efi.zig:507 if (count.* == maximum_bundled) return; in loadByManifest is a silent stop keeping the first 64; efi.zig:590 … |
Manifest path: nothing. Enumeration path: efi.zig:71-75 prints 'EFI: no /system binaries (TooManyBinaries) - b… |
boot/efi.zig:582 |
(child_prefix bufPrint) | 64 bytes (initial_ramdisk.ma… | external-data | const child = try std.fmt.bufPrint(&child_prefix, "{s}/{s}", .{ prefix, name }); into a [initial_ramdisk.maximum_name]u8 = [64]u8. error.NoSpaceLeft… |
efi.zig:71-75 prints 'EFI: no /system binaries (NoSpaceLeft) - booting without user space' on con_out. Visible… |
boot/efi.zig:633 |
ehdr.e_phnum / e_phoff / e_phentsize (no bound a… | unbounded — read straight fr… | external-data | Unchecked out-of-bounds read. efi.zig:632-636 forms image.ptr + ehdr.e_phoff + i * ehdr.e_phentsize as raw pointer arithmetic and @ptrCasts it — no … |
Nothing until it faults or panics, at which point the machine is still in the firmware with no kernel. |
library/device/acpi/aml/interpreter.zig:158 |
notify_queue | [16]NotifyEvent | external-data | Silent drop of the 17th and later Notify. notify() (line 571-576): `if (target) |node| { if (self.notify_count < self.notify_queue.len) { ...appen… |
None. No log in interpreter.zig at all (grepped: zero std.log/log.print/logging.write calls in the file). `tak… |
library/device/acpi/aml/interpreter.zig:523 |
100_000 | our-design | Silently exits the loop and continues executing the method as if the loop had terminated normally: while (guard < 100_000) : (guard += 1) { … } then… |
Nothing. No log, no error.Unsupported, no distinguishable result — the caller receives a normal-looking valu… |
|
library/device/acpi/aml/parser.zig:24 |
maximum_segments (and its disagreeing twin, libr… | 64 in the parser, 16 in the … | external-data | Both files silently drop the surplus segment after consuming its 4 bytes. Parser: appendSegment, parser.zig:137-143. Interpreter: `fn segment(self: *C… | None on either path. Neither file logs; acpi.zig discards ParseResult.consumed/total; interpreter errors surfa… |
library/device/usb/usb.zig:167 |
100 attempts × 20 ms = 2 s | our-design | Gives up and returns null: `const bus = while (attempts < 100) : (attempts += 1) { if (channel.openEndpoint("usb-transfer")) |handle| break handle; … | Nothing here. The driver's own bail-out is what an operator sees, with no indication that it was a timeout rat… | |
library/kernel/channel.zig:124 |
@min(available, into.len) | our-design | Silent truncation to the caller's buffer: `const available = @min(answer.len - envelope.prefix_size, @as(usize, status.len)); const taken = @min(avail… | Weak: Response.status.len holds the true length the provider sent, so a caller could compare it against `p… |
|
library/kernel/file-system.zig:85 |
[224]u8 (twice: lines 77 and… | our-design | Errors invisibly, but the enforcing code is in the KERNEL, not where the claim points. system/kernel/process.zig:1898 rejects the input outright: `if … | None. A too-long path and a nonexistent file are both null from open(); no log on either side — the kernel's… |
|
library/kernel/logging.zig:82 |
[256]u8 | our-design | Truncation, marked with a ~ — but the truncated slice is the whole buffer, not the written prefix: `const line = std.fmt.bufPrint(&buffer, prefix … |
The trailing ~ marks the line as truncated, which is good; the garbage tail is not marked at all. |
|
library/kernel/process.zig:211 |
[32]ProcessDescriptor | our-design | Silent false negative: `var table: [32]ProcessDescriptor = undefined; const total = processes(&table); for (table[0..@min(total, table.len)]) |descri… | Nothing. The function returns a plain bool; the discarded total is the only evidence and it is thrown away b… |
|
library/protocol/device-manager/device-manager-protocol.zig:161 |
entries_per_reply | (envelope.packet_maximum - e… | hardware | Silent cut with a success status. onEnumerate (device-manager.zig:524-536): `for (&children) |*child| { if (!child.used) continue; if (written + e… |
None, and structurally impossible for a client to detect: the protocol's own comment (149-152) says the count … |
library/protocol/envelope/envelope.zig:133 |
packet_maximum | 256 | our-design | Two behaviours, exactly as claimed. Compile time: Define rejects an oversized fixed part with a message naming protocol, verb, size, prefix and floo… |
Compile-time half is excellent. Run-time half is silent everywhere I traced it: library/device/block/block.zig… |
library/protocol/envelope/envelope.zig:134 |
post_maximum | 64 | our-design | Compile error for an event payload that does not fit (Define, envelope.zig:365-370, message names the event and the push floor). At run time `encode… |
Compile-time: named and precise. Run-time: nothing. The orelse return at service.zig:239 is the whole handli… |
library/protocol/usb-transfer/usb-transfer-protocol.zig:58 |
max_report_data | 40 | hardware | Two stacked silent truncations. First in the engine: usb-xhci-library.zig:1569 const n = @min(length, report.data.len); against a data: [64]u8 (li… |
None. No log at either truncation site; the surrounding comment (usb-xhci-bus.zig:766-768) states the truncati… |
library/protocol/usb-transfer/usb-transfer-protocol.zig:62 |
max_reported_endpoints | 4 | hardware | Silent drop, and the primary site is upstream of the one claimed. The bus driver discards surplus endpoint descriptors while parsing the configuration… | None. No log at the parse-time drop, none at the client cap; a driver's findEndpoint just returns null for a… |
system/boot-handoff.zig:143 |
kernel_segments | 8 | our-design | Silent drop with a delayed fatal consequence, as described. boot/efi.zig:659-668 records only if (n < boot_information.kernel_segments.len) with no … |
The loader says nothing. The kernel prints the count it received — kernel.zig:159 `log.print(" kernel segs: {… |
system/drivers/pci-bus/pci-bus.zig:81 |
alloc(device.DeviceDescriptor, … | 64 | our-design | Not reachable today, so nothing happens. If the kernel table grew past the buffer: device.enumerate(buffer) returns the TOTAL, the search clamps wit… |
One misleading line, std.log.info("device {d} not in the device tree", .{bridge_id}) — it names a missing de… |
system/drivers/pci-bus/pci-bus.zig:81 |
64 (bare inline literal — no constant, no link t… | 64 | our-design | Same site as the earlier claim on line 81 — this is a duplicate. Unreachable today (total is bounded by the kernel's own maximum_devices = 64). If i… |
std.log.info("device {d} not in the device tree", .{bridge_id}) — misdescribes the cause and never prints `t… |
system/drivers/usb-hid/hid-report.zig:20 |
KeyboardReport.keys: [6]u8, and max_transitions … | 6 concurrent keys; 14 transi… | hardware | THE CLAIM IS BACKWARDS. max_transitions = 8 + 6 is derived from a wrong worst case, and Transitions.add's guard (`if (self.count < self.items.len)… |
None. add drops without logging and Transitions carries no overflow flag; slice() just returns the first… |
system/drivers/usb-storage/usb-storage.zig:61 |
.lun = 0 in the CommandBlockWra… | 1 LUN (LUN 0 only) | hardware | There is no limit check — LUNs 1..15 simply do not exist to this driver. Every CBW is built with .lun = 0 (usb-storage.zig:57-63), and I confirmed t… |
Nothing. Nothing reads bMaxLUN, so nothing can report that a device has more than one logical unit. |
system/drivers/usb-storage/usb-storage.zig:121 |
while (tries < 10) with time.sl… | 10 attempts = ~500 ms | hardware | Falls out of the loop and proceeds regardless (usb-storage.zig:120-127). INQUIRY's result is discarded (_ = transact(...), line 129), then READ CAPA… |
Present but misattributed, exactly as claimed: `_ = logging.write("/system/drivers/usb-storage: READ CAPACITY … |
system/drivers/usb-storage/usb-storage.zig:172 |
@intCast(request.lba) -> u32, @… | LBA < 2^32, count < 2^16 (RE… | external-data | Bare, unchecked @intCast on both fields — verified there is no range check anywhere between the wire struct and the CDB. scsi.read10/write10 take (lba… | In a safe build, driver death with a fault exit reason and a device-manager restart with backoff — attributed … |
system/drivers/usb-storage/usb-storage.zig:172 |
@intCast(request.lba) / @intCast(request.count) … | u64 -> u32 LBA, u32 -> u16 b… | external-data | Unchecked narrowing of two peer-chosen wire fields. library/protocol/block/block-protocol.zig:30-35 declares `Transfer { lba: u64, count: u32, physica… | Nothing in ReleaseFast; in a safe build a driver crash with a fault exit reason and a supervised restart, attr… |
system/drivers/usb-xhci-bus/usb-xhci-bus.zig:80 |
opens (= [_]Open{.{}} ** 16) | 16 | our-design | Confirmed, including the success-on-failure shape. recordOpen (line 87) walks opens for a matching token, then for a free slot, and falls through to… |
Nothing on the bus side — no log when the table fills, and the harness closes the unclaimed report endpoint si… |
system/drivers/usb-xhci-bus/usb-xhci-bus.zig:728 |
prev_connected (declared line 326 as [64]bool), … | 64 | hardware | Confirmed off-by-one. Line 728: while (port <= engine.max_ports and port <= prev_connected.len) : (port += 1) with var port: u32 = 1 — at port == … |
The OOB half surfaces as a driver fault and a supervised restart into the same panic — loud but attributed to … |
system/drivers/usb-xhci-bus/usb-xhci-bus.zig:728 |
prev_connected (inline [64]bool, declared line 3… | 64 | hardware | Same site as the earlier line-728 claim — this is a duplicate. Two failures, both confirmed. (1) Off-by-one out-of-bounds: `while (port <= engine.max_… | The panic half is loud (process fault + supervised restart loop) but misattributed. The silent-drop half has n… |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:228 |
max_endpoints_per_interface (and max_configured_… | 4 per interface, 16 configur… | hardware | Parsing: if (interface.endpoint_count < max_endpoints_per_interface) with no else — the 5th endpoint descriptor is silently discarded, so a class dr… |
The endpoint-drop during parsing is entirely silent. The ring-exhaustion path reaches the class driver as a ge… |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:228 |
max_endpoints_per_interface | 4 | external-data | Silent drop, no else (1345-1354). An endpoint never recorded cannot be found by endpointForAddress (1377-1382), so a class driver's subscribe or bul… |
None at the drop. The secondary consequence the claim names is real and I verified it: usb-xhci-bus.zig:612 se… |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:328 |
Report.data: [64]u8 (and usb_tr… | 64 in the driver, then 40 ov… | hardware | Truncated twice, silently: const n = @min(length, report.data.len); in enqueueReport, then `const n = @min(report.length, usb_transfer_protocol.max_… |
Nothing. Both truncations are @min with no branch and no log. |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:334 |
max_subscriptions | 8 | hardware | Two paths, as claimed. Class driver: subscribeInterrupt (1482) const subscription = self.allocateSubscription() orelse return false; -> usb-xhci-b… |
Class drivers log it: usb-hid/keyboard.zig:94 and mouse.zig:57 both write interrupt subscribe failed. The hu… |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:335 |
report_queue_capacity | 16 | hardware | enqueueReport (1561-1562): if (self.report_count >= self.report_queue.len) return; // full: drop the newest — the report is discarded and the subs… |
None. The comment in the source is the only trace; no log, no counter. The symptom is dropped keystrokes or a … |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:968 |
hub_change_mask: u32 (declared line 298) and the… | 31 usable downstream ports | hardware | Ports 32..255 are never seeded and never serviced: the seed clamps to 0xFFFF_FFFE for hub_ports >= 31, and takeHubChange picks bits via @ctz on a u32,… | Nothing. No log line mentions bNbrPorts exceeding what the mask holds; the 'N downstream ports powered' line p… |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:1456 |
.status = length on the bulk … |
65535 (the xHCI TRB Transfer… | hardware | Unchecked write of a u32 into a 17-bit field. bulkTransfer (1452-1458) pushes .status = length with no mask and no split across TRBs; the status d… |
Nothing on the way in — no check, no log. It surfaces later as a short/failed transfer or a lost completion at… |
system/drivers/virtio-gpu/virtio-gpu.zig:49 |
max_width / max_height | 800 x 600 | hardware | set_mode errors visibly (line 536 refuses anything larger). But the EDID path is the silent one: readEdid (lines 413-442) parses the panel's preferred… | One std.log.info line naming the preferred mode, in the driver's log file, with nothing saying it was ignored. |
system/drivers/virtio-gpu/virtio-gpu.zig:208 |
descriptors: [64]device.DeviceD… | 64 | hardware | NOT reachable today, contrary to the claim's framing. The kernel's own table is the binding wall: system/kernel/devices-broker.zig:25 `const maximum_d… | device {d} not in the device tree (line 213), which today only means a real absence. The kernel-side drop th… |
system/initial-ramdisk.zig:26 |
maximum_name | 64 bytes | our-design | Four different behaviours, verified individually. (a) Capsule build: tools/pack-system-image.py:35-37 writes 'pack-system-image: path too long (>63)' … | (a) clear build error. (b)(c)(d) nothing: boot/efi.zig has exactly two output helpers (lines 773 and 795) and … |
system/kernel/acpi.zig:94 |
overrides | [16]IsoEntry | hardware | Silent drop: if (platform_information.override_count < platform_information.overrides.len) { ... } with no else branch and no counter — unlike the C… |
Nothing. A lost override means a legacy line is routed at the wrong GSI or the wrong polarity, which shows up … |
system/kernel/acpi.zig:94 |
PlatformInformation.overrides | [16]IsoEntry | hardware | Silent drop, at three separate 16s that must agree by hand: system/kernel/acpi.zig:558 (no else branch), system/kernel/kernel.zig:248 (`var isos: [16]… | Nothing at any of the three clamps. No counter of the cpusDropped kind, no log line. |
system/kernel/acpi.zig:186 |
aml_block_physical / aml_block_len | [32]u64 / [32]usize | hardware | Confirmed at acpi.zig:190-197: `fn addAmlBlock(sdt_physical: u64) void { if (aml_block_count >= aml_block_physical.len or sdt_physical == 0) return; .… | None — confirmed, no log and no dropped counter, unlike cpu_information.dropped (acpi.zig:539) and `rmrr_ski… |
system/kernel/architecture/x86_64/apic.zig:320 |
100_000_000 (calibratePit guard… | 100000000 | our-design | Confirmed: the loop falls out and calibration proceeds on a window that never happened. ticks_per_ms = elapsed / calib_ms and `tsc_hz = (tsc_end -% … |
No failure line, but not quite "none": kernel.zig:322 prints `timer online ({d} Hz tick; timer clock {d} MHz, … |
system/kernel/architecture/x86_64/apic.zig:629 |
localId (return type u8) / apic_id << 24 | 8-bit APIC id (0..255) | hardware | The claimed truncations are not reachable; the real defect is an omission. sendInit/sendStartup (lines 174-184) take a u32 but every caller pass… |
None for the dropped type-9 records. cpu_information.dropped (acpi.zig:542) counts only overflow past the 12… |
system/kernel/architecture/x86_64/iommu-amd.zig:56 |
ring_entries (command buffer) | 256 | our-design | Confirmed. submitCommand (lines 221-228) writes the two qwords, advances command_tail += 16, wraps modulo the ring, and writes the tail register — w… |
None — no head check, no full-ring detection, no log. |
system/kernel/architecture/x86_64/iommu-amd.zig:74 |
fault_log_budget | 32 | hardware | logFault (lines 200-211) opens with if (fault_log_budget == 0) return; — the record's bdf and address are discarded outright, with no suppressed-fau… |
One "(further faults suppressed)" line (line 210) and then permanent silence for the detail. Correcting the cl… |
system/kernel/architecture/x86_64/iommu-amd.zig:246 |
100_000 | 100000 | our-design | Confirmed verbatim at lines 243-253: the spin loop polls the completion frame for the 0xC0FFEE sentinel, and at if (spins > 100_000) warns once behi… |
One line for the whole boot: "/system/kernel: AMD-Vi COMPLETION_WAIT store not observed — proceeding (QEMU pro… |
system/kernel/architecture/x86_64/iommu-intel.zig:77 |
fault_log_budget | 32 | hardware | logFault (lines 252-270) takes the else branch and does faults_suppressed += 1. The budget is only ever decremented (line 255) — nothing resets it… |
One line at the transition: 'DANOS-IOMMU-FAULT: (further faults suppressed)' (line 266). After that a device D… |
system/kernel/architecture/x86_64/iommu-intel.zig:294 |
10_000_000 (spin64) | 10000000 | our-design | if (spins > 10_000_000) return; — the function returns as if the invalidation completed. Callers (invalidateDomain, globalInvalidate, detach) … |
Nothing at all — a bare return with no message, unlike spinStatus which prints "WARNING VT-d status bit ne… |
system/kernel/architecture/x86_64/paging.zig:206 |
0xFEE00000 | 0xFEE00000 (one 4 KiB page) | hardware | Confirmed and worse than "inconsistent": the two halves disagree with no reconciliation. paging.zig:206 maps exactly one hardcoded page `mapPage(pml4,… | A boot-time kernel fault reported as a fault address, never as "LAPIC relocated". The parsed truth is thrown a… |
system/kernel/architecture/x86_64/serial.zig:112 |
5_000 (writeByte guard) | 5000 | hardware | The loop simply falls through and setRegister(0, c) runs anyway (serial.zig:111-113) — the byte is written into a transmit-holding register that may… |
Nothing. The corruption appears in the serial log itself, which is the channel you would use to notice it. |
system/kernel/heap.zig:28 |
heap_maximum | 64 * 1024 * 1024 | our-design | Confirmed mixed. grow returns false at heap.zig:63 if (start + bytes > heap_base + heap_maximum) return false; -> rawAlloc null -> std.mem.Alloc… |
For the graceful callers, a bare -1 to user space with no reason. For scheduler.zig:704, a panic naming the st… |
system/kernel/heap.zig:161 |
alignment ceiling | 16 | our-design | if (alignment.toByteUnits() > 16) return null; confirmed at heap.zig:161 inside allocImpl. Returning null from the vtable alloc is how the allocat… |
None. No log, no distinct error; the caller sees error.OutOfMemory and investigates memory pressure. |
system/kernel/ipc-synchronous.zig:40 |
MESSAGE_MAXIMUM | 256 | our-design | Two different behaviours, both confirmed. The cap itself errors visibly: `if (message_len > MESSAGE_MAXIMUM or reply_cap > MESSAGE_MAXIMUM) return -E2… | -E2BIG for the cap. Nothing for the truncation — no counter, no flag bit, no errno. |
system/kernel/ipc-synchronous.zig:75 |
post_capacity | 16 | external-data | Deliberate silent drop of the OLDEST message: sendLocked, ipc-synchronous.zig:568 `if (endpoint.post_tail -% endpoint.post_head >= post_capacity) endp… | None, and I checked the struct: PostSlot (ipc-synchronous.zig:79-83) carries only length and sender_id — no se… |
system/kernel/ipc-synchronous.zig:513 |
@min(caller.ipc_send_len, receive_cap) (no const… | whatever the receiver's buff… | external-data | Silent truncation. replyWait, ipc-synchronous.zig:512-513: `if (dequeueSender(endpoint)) |caller| { const n = @min(caller.ipc_send_len, receive_cap)… | Nothing — no counter, no errno, no flag bit anywhere on this path. |
system/kernel/log.zig:202 |
buffer (log.print) | [256]u8 | our-design | Confirmed: the entire line is discarded, not truncated. Lines 201-204 verbatim: `pub fn print(comptime fmt: []const u8, args: anytype) void { var buff… | Nothing. The message never appears and its absence is indistinguishable from the code path not having run. Not… |
system/kernel/pmm.zig:94 |
(implicit: bitmap must land bel… | 4 GiB, stated only in prose | hardware | Two distinct failures. If NO usable region is large enough: @panic("pmm: no region large enough for the frame bitmap") — loud and fatal. If the chos… |
The panic is legible. The above-4-GiB case is a triple fault or an early #PF with essentially no diagnostics. |
system/kernel/process.zig:98 |
maximum_shared_memory_pages | 8192 (32 MiB) | hardware | Confirmed at process.zig:790: if (pages == 0 or pages > maximum_shared_memory_pages) return fail(state); in systemSharedMemoryCreate, giving a cle… |
No kernel log; -1 only — confirmed. And the ambiguity the claim notes is real: pmm.allocContiguous failing t… |
system/kernel/process.zig:104 |
maximum_mmap_pages | 8192 (32 MiB) | our-design | Confirmed at process.zig:2050: if (pages == 0 or pages > maximum_mmap_pages) return fail(state); in systemMmap — a clean -1. The independent secon… |
-1 only, no log — confirmed. Indistinguishable from arena exhaustion and from 'not a user process' (line 2049)… |
system/kernel/process.zig:118 |
maximum_resolve_path | 224 | external-data | Confirmed at process.zig:1898: `if (path_len == 0 or path_len > maximum_resolve_path or path_ptr >= user_half_end or path_ptr + path_len > user_half_e… | No log; -1 only — confirmed. There is no ENAMETOOLONG in this path (the function does have `failErr(state, ipc… |
system/kernel/process.zig:1542 |
exit_subscriber_capacity | 16 | hardware | Confirmed at process.zig:1573-1581: subscribeExits scans `for (&exit_subscribers) |slot| { if (slot. == null) { endpoint.refcount += 1; slot.* =… |
Materially worse than claimed, and this is my main correction. The kernel does return a specific -ENOSPC, but … |
system/kernel/process.zig:1649 |
timer_capacity | 16 | our-design | Confirmed at process.zig:1684-1692: systemTimerBind scans `for (&one_shot_timers) |slot| { if (slot. == null) { ...; return architecture.setSyst… |
Effectively none, correcting the claim. The kernel's -ENOSPC is narrowed to a bool by library/kernel/time.zig:… |
system/kernel/process.zig:2172 |
maximum_segments | 16 | external-data | Confirmed at process.zig:2200: if (ehdr.e_phnum > maximum_segments) return error.BadElf;. The claim's key observation is right — the test is on `e_p… |
None — confirmed. error.BadElf is erased at process.zig:1018 and system_spawn returns -1, so a developer i… |
system/kernel/process.zig:2173 |
maximum_pages | 256 | external-data | Confirmed at process.zig:2238, inside the PT_LOAD loop: total_pages += seg.pages(); if (total_pages > maximum_pages) return error.ProgramTooBig;. Th… |
No kernel log — confirmed. error.ProgramTooBig is erased at the syscall boundary and becomes the same -1 as … |
system/kernel/scheduler.zig:206 |
maximum_space_mappings | 16 | our-design | Clean refusal, confirmed. recordSpaceMappingLocked (scheduler.zig:343-355) walks entry.mappings for a null slot and return false when full; proc… |
A bare -1 from shared_memory_map/shared_memory_create — the same value as a bad handle, an exhausted arena… |
system/kernel/vfs.zig:143 |
@memcpy(d.path[0..parent.len], parent) — implici… | 64 == 64, by coincidence | external-data | Safe today, and safe with slightly more margin than the claim states. parentOf (vfs.zig:119-123) returns a strict prefix ending before the last '/', s… | Nothing would warn. The coupling is invisible from either file: system/initial-ramdisk.zig:26-28 reasons about… |
system/kernel/vfs.zig:315 |
name_out (via process.zig:1972 name_buffer) | [64]u8 | external-data | Silent truncation with a header that agrees with the truncation rather than reporting it: vfs.zig:314-317 `const n = @min(name.len, name_out.len); @me… | None. The contrast is fair — system/kernel/log-ring.zig sets abi.klog_flag_truncated for exactly this situatio… |
system/services/acpi/acpi.zig:81 |
mmio_scratch | [4096]u8 | external-data | No overflow — the aliasing IS the failure. library/device/acpi/aml/interpreter.zig:708 (readRegionByte) and :720 (writeRegionByte) both do `const virt… | None. No log fires on a SystemMemory access in either the interpreter or the HAL, so an _STA or _CRS that cons… |
system/services/acpi/acpi.zig:113 |
64 | hardware | Falls through silently and proceeds as though ACPI mode were enabled. `while (tries < 1000 and (halPioRead(2, pm1a_cnt) & sci_en_bit) == 0) : (tries +… | None that distinguishes the two outcomes. No log fires on give-up, and the success message "acpi: power button… | |
system/services/acpi/acpi.zig:306 |
1000 | hardware | Falls through silently and proceeds as though ACPI mode were enabled. `while (tries < 1000 and (halPioRead(2, pm1a_cnt) & sci_en_bit) == 0) : (tries +… | None that distinguishes the two outcomes. No log fires on give-up, and the success message "acpi: power button… | |
system/services/device-manager/device-manager.zig:50 |
registry_source | [8192]u8 | external-data | Silent truncation of the file. loadRegistry (63-68): `while (used < registry_source.len) { const n = file.read(registry_source[used..]) orelse break… |
Nothing says the file was cut. Only downstream symptoms: {d} malformed line(s) skipped (line 70) if the frag… |
system/services/device-manager/device-manager.zig:51 |
registry_source | 8192 bytes | external-data | Silent truncation of the file. loadRegistry (63-68): `while (used < registry_source.len) { const n = file.read(registry_source[used..]) orelse break… |
Nothing says the file was cut. Only downstream symptoms: {d} malformed line(s) skipped (line 70) if the frag… |
system/services/device-manager/device-manager.zig:531 |
reply tail of a 256-byte pac… | our-design | Silent truncation with a success status: if (written + entry_size > tail.len) break; and the handler returns the byte count. There is no cursor and … |
None. The client sees a short but well-formed list. | |
system/services/display/backend.zig:27 |
device_table | [64]device.DeviceDescriptor | hardware | Confirmed as written but NOT reachable today. findDisplay (lines 54-63) does `const total = device.enumerate(&device_table); const n = @min(total, dev… | Misleading when it does fire, as claimed: Gop.init exhausts its retries and writes `display: no framebuffer de… |
system/services/display/compositor.zig:288 |
src.len >= wh4, against a … | our-design | Silent no-op reported as success. blitTile does if (src.len < @as(usize, w) * h * 4) return;, but blitLayer (display.zig:236-242) ignores that, stil… |
None whatsoever: no log, and a success status. The symptom is a blank region. | |
system/services/display/display.zig:76 |
maximum_layers | 16 | our-design | Confirmed. createLayer (display.zig:208-210) is const slot = freeLayer() orelse return null;, and onCreateLayer (695-700) is `const slot = creat… |
Nothing server-side for a client-facing exhaustion — confirmed. The service's own cursor path does log (`_ = l… |
system/services/display/display.zig:395 |
mode_list / list | [4]backend_mod.Mode | hardware | Silent truncation on both hops: the backend clamps with const count = @min(@min(offered.count, scanout_protocol.max_modes), out.len); (backend.zig:1… |
None — no log names the number offered versus the number kept. The mode-set self-check only says "no alternate… |
system/services/fat/engine.zig:70 |
sector_size | 512 | external-data | Mount is refused, confirmed. Both paths test if (geometry.bytes_per_sector == sector_size) — engine.zig:193 (bare FAT at LBA 0) and engine.zig:209 (… |
A wrong diagnosis: _ = logging.write("/system/services/fat: not a FAT filesystem\n") at system/services/fat/… |
system/services/fat/engine.zig:193 |
sector_size (declared line 70) | 512 | external-data | Refuses to mount rather than corrupting, confirmed at engine.zig:193 and the MBR-partition path at engine.zig:209; both fall through to return null. |
system/services/fat/fat.zig:162 _ = logging.write("/system/services/fat: not a FAT filesystem\n") — false fo… |
system/services/fat/fat.zig:73 |
open_nodes (inline [_]OpenNode{.{}} ** 32) | 32 | our-design | Error returned, but the WRONG error, and silently: const index = allocOpen() orelse return refused; where const refused: isize = -envelope.ENOENT;… |
Nothing. No log line at exhaustion, and the client is told the file does not exist. An operator debugging this… |
system/services/fat/fat.zig:285 |
reply tail of a 256-byte pac… | our-design | Silent truncation with a success status: const name_len = @min(listing.name_len, into.len); then return @intCast(name_len); — the client receives … |
None. A directory listing shows a chopped filename that then fails to open. | |
system/services/fat/fat.zig:285 |
into.len (inline; = envelope.packet_maximum - pr… | 224 bytes | external-data | Silent truncation, and the reply's name_len is set to the TRUNCATED value, so the client cannot tell there was more. The engine's own buffer holds 260… | Nothing. |
system/services/init/init.zig:70 |
max_service_args | 4 | external-data | Silent drop of the surplus arguments: loadServices, init.zig:122-127 `while (it.next()) |argument| { if (argument.len == 0) continue; if (service.ar… | None, and the contrast with its immediate sibling is confirmed: the max_services cap ten lines above logs `"/s… |
system/services/init/init.zig:161 |
maximum_bindings | 16 | our-design | An error is returned to the binder: onBind, init.zig:620-622 `const slot = for (&bindings) |*binding| { if (!binding.used) break binding; } else ret… | Weak, and the asymmetry is confirmed: within the same function the EPERM path logs (init.zig:602-608) and the … |
system/services/init/init.zig:162 |
maximum_grants | 64 | external-data | Parsing stops at 64 rows: loadGrants, init.zig:237-240 `if (grant_count >= grants.len) { _ = logging.write("... protocol.csv has more rows than the ta… | The overflow itself is logged with a direct logging.write naming the file (init.zig:238). The consequences a… |
system/services/init/init.zig:220 |
protocol_csv | 16384 bytes | external-data | Silent truncation mid-line, then a heuristic report. readConfiguration (init.zig:138-146) fills the buffer and stops; the tail rows vanish and the las… | One heuristic info log: init.zig:147 `if (used == into.len) std.log.info("{s} filled the read buffer — rows pa… |
system/services/init/init.zig:220 |
protocol_csv (with maximum_grants = 64 rows alon… | 16384 bytes / 64 rows | external-data | Truncation, announced on both limits. readConfiguration reports the byte cap at init.zig:147 (`std.log.info("{s} filled the read buffer — rows past {d… | Both limits log, which is what makes this the calibration point. The byte-limit line rides std.log.info (the r… |
system/services/init/init.zig:274 |
process_table | [64]process.ProcessDescripto… | our-design | Partly handled, partly not — confirmed exactly. refreshProcessTable (init.zig:278-282) sets process_truncated = total > process_table.len, and taskA… |
A bind refusal outside identify does log (init.zig:602-608), but a failed identify in onBind returns -EPERM wi… |
boot/efi.zig:308 |
pool_pages | 64 frames (256 KiB) | hardware | TablePool.alloc, efi.zig:264-265: if (self.next >= self.cap) return error.OutOfBootstrapFrames;. Every map2M/map4K path is try, so it unwinds clea… |
Good, and verified: main (efi.zig:34-39) writes unconditionally to con_out — `log("\r\nEFI: boot failed: "); l… |
boot/efi.zig:543 |
info_buffer | 1024 bytes | external-data | const n = try directory.read(&info_buffer); (efi.zig:545) into a [1024]u8. UEFI answers EFI_BUFFER_TOO_SMALL for an EFI_FILE_INFO that will not fit;… |
efi.zig:71-75 on con_out, naming the UEFI error but not the file. |
boot/efi.zig:543 |
info_buffer (inline [1024]u8) | 1024 bytes | external-data | const n = try directory.read(&info_buffer); (efi.zig:545) — EFI_BUFFER_TOO_SMALL becomes an error and the try propagates out of walkDirectory and … |
efi.zig:71-75 on con_out; names the UEFI error, not the file. |
boot/efi.zig:660 |
BootInformation.kernel_segments (declared system… | [8]KernelSegment | our-design | if (n < boot_information.kernel_segments.len) { ... } (efi.zig:659-668) with no else — the segment is copied to its physical address but never recor… |
Nearly nothing, but not quite nothing: kernel.zig:159 prints `log.print(" kernel segs: {d} (mapped with W^X p… |
boot/efi.zig:680 |
(attempts) and cap = info.len +… | 8 attempts; +8 spare descrip… | hardware | Correct and safe, as claimed. efi.zig:680-700: on each attempt both pool buffers are sized from the firmware's own descriptor count plus 8, a failed g… | The fatal case reaches main's handler: 'EFI: boot failed: ExitBootServicesFailed' on con_out, then hlt. No bre… |
boot/efi.zig:787 |
buffer (logBytes) | 128 UTF-16 units | our-design | if (i + 1 >= buffer.len) break; (efi.zig:790) — the tail of the string is dropped, the result is NUL-terminated at the truncation point and printed.… |
This IS the observability path — logBytes is the only way a runtime string (in practice an @errorName from mai… |
build/images.zig:152 |
(mk_fat.addArg("64")) | 64 (MiB) | our-design | Build-time hard failure. tools/make-fat-image.py:67-68 — if cluster >= self.cluster_count + 2: sys.exit("error: image out of clusters") inside the c… |
"error: image out of clusters" on stderr, which aborts the build. It names neither the file being added nor a … |
library/device/acpi/aml/interpreter.zig:55 |
maximum_segments | 16 | external-data | Silent truncation in Cursor.segment (123-129): const s = try self.take(4); if (name_path.count < maximum_segments) { ...store... } — the cursor ad… |
None. Line 299's comment // unknown name -> treat as uninitialised is by design, so a truncated name is indi… |
library/device/acpi/aml/parser.zig:24 |
maximum_segments | 64 | external-data | appendSegment (parser.zig:137-143) always consumes the 4 name bytes via readNameSegment — so the cursor stays in sync — but silently discards the segm… | None. aml.zig:36-56 builds a ParseResult{consumed,total} precisely so a desync is detectable, but the only con… |
library/device/block/block.zig:95 |
600 attempts × 50 ms = 30 s | our-design | Returns null; the caller (the FAT server) reports no volume. | Nothing logged at this level, but the number is justified against a measurement. | |
library/device/driver/driver.zig:165 |
lookup_attempts | 100 (× lookup_pause_ms = 20 … | our-design | hello() runs `while (attempts < lookup_attempts) : (attempts += 1) { if (channel.openEndpoint("device-manager")) |handle| break handle; time.sleep… |
Good, and I confirmed it at driver.zig:181 — the else branch IS the log. Requiring callers also announce their… |
library/device/model/device-abi.zig:139 |
DeviceDescriptor.hid | [8]u8 | hardware | No truncation is reachable today. The cited site (devices-broker.zig:121-122) cannot truncate: node.hid() returns hid_buffer[0..hid_len] from devi… |
Not applicable — nothing truncates. The 8-byte-with-no-NUL width does cause a live defect elsewhere: system/se… |
library/device/pci/pci.zig:37 |
bar_virtual | [6]usize | hardware | Errors: pub fn mapBar(self: *Function, bar: u8) ?usize { if (bar >= 6) return null; — a caller asking for BAR 6 gets null rather than an out-of-boun… |
Null from mapBar, which each driver reports in its own words. |
library/device/pci/pci.zig:283 |
CapabilityIterator.guard (and ExtendedCapability… | 48 and 480 | hardware | Iteration ends. Silent, but correctly so: the bound is derived from the size of the address space being walked, so reaching it means the device's chai… | Nothing — and it needs nothing, because the bound cannot cut a well-formed chain short. |
library/device/pci/pci.zig:286 |
48 | hardware | The iterator silently ends: if (self.cursor == 0 or self.guard >= 48) return null; — indistinguishable from the end of a well-formed list. `findCapa… |
Nothing. No log distinguishes 'no MSI capability' from 'capability list is a loop'. | |
library/device/pci/pci.zig:371 |
480 | hardware | Silently ends the iteration: if (self.cursor == 0 or self.guard >= 480) return null;. findExtendedCapability then reports absence. |
Nothing. | |
library/device/registry/device-registry.zig:200 |
cols | [9][]const u8 | external-data | Errors and counts. parseLine: if (count >= cols.len) return .malformed; // too many columns and after the loop `if (count != cols.len) return .malfo… |
Verified end to end, and it is genuinely good: system/services/device-manager/device-manager.zig:71 `if (resul… |
library/device/registry/device-registry.zig:239 |
out_rules.len (caller-supplied) | caller's buffer | external-data | if (result.count >= out_rules.len) { result.truncated = true; continue; } inside parse — the surplus valid rules are dropped and the flag records it… |
The best in the tree, and I confirmed the caller actually uses it: device-manager.zig:72 `if (result.truncated… |
library/kernel/channel.zig:37 |
path_maximum | 224 | our-design | Refuses: join (285) if (total > buffer.len) return null;. reach (182-193) returns null when file_system.fsResolve cannot write the rewritten p… |
None — null, no log, same documented three-way ambiguity. |
library/kernel/channel.zig:46 |
name_maximum | 64 | our-design | Refuses, never truncates: join (282-290) if (name.len == 0 or name.len > name_maximum) return null;, which openEndpoint (238-242) turns into a n… |
None (no log), and the null is deliberately three-way ambiguous per the doc at 231-237: no such contract / not… |
library/kernel/memory/heap.zig:199 |
16 | our-design | Refuses cleanly: `fn allocImpl(_: anyopaque, len: usize, alignment: std.mem.Alignment, _: usize) ?[]u8 { if (alignment.toByteUnits() > 16) return nu… | An allocation failure, which std reports as OutOfMemory — a misleading name for an alignment refusal, and no l… | |
library/kernel/process.zig:116 |
[8]u8 | our-design | The kernel refuses the sender rather than truncating (the receive capacity travels in r8 to ipc_reply_wait), so a client that calls into a process… |
The refusal reaches the caller as an IPC failure; the stopping process logs nothing. | |
library/kernel/process.zig:185 |
[256]u8 | our-design | Errors, cleanly: if (len >= blob.len) return null; and if (len + argument.len > blob.len) return null; — the spawn never happens and null is retur… |
Poor. spawn* returning null is the same answer as 'no such binary' or 'task table full'; the caller (e.g. th… |
|
library/kernel/service.zig:94 |
subscriber_capacity | 8 | our-design | onSubscribe (service.zig:264) walks slots, and if no slot is free returns -envelope.ENOSPC. The turn then closes the endpoint capability that arri… |
No log in the provider. On the subscriber side the only real caller in the tree does log: system/services/disp… |
library/kernel/thread.zig:41 |
tls_block_size | 64 | our-design | No check exists anywhere. thread.zig:88-90 carves closure_addr down from the stack top and then `const tls_base = (closure_addr - tls_block_size) & … |
None — nothing tracks a TLS extent, so nothing could report it. The symptom would be a thread running with cor… |
library/protocol/display/display-protocol.zig:99 |
max_modes | 4 | our-design | Silent drop of the surplus, but it can never fire. Provider side confirmed at system/services/display/display.zig:749-757: `var list: [4]backend_mod.M… | Nothing at either end — no log — but nothing is dropped either. |
library/protocol/scanout/scanout-protocol.zig:29 |
max_modes | 4 | hardware | Silent truncation on both sides, exactly as claimed. Driver: virtio-gpu.zig:525-527 `var offered = scanout_protocol.Modes{ .count = offered_modes.len … | None. Confirmed: neither modes() in backend.zig nor the get_modes handler in virtio-gpu.zig emits anything a… |
library/xkeyboard-config/xkeyboard-config.zig:80 |
map(layout, hid_usage: u8, …) | u8 (indexing Layout.keys: [2… | hardware | No overflow is possible — keys: [256]Key (library/xkeyboard-config/generated/layouts.zig:20) exactly covers the u8 domain, and an unmapped usage yie… |
A key that maps to nothing produces no character; nothing distinguishes 'unmapped' from 'narrowed to the wrong… |
system/drivers/pci-bus/pci-bus.zig:36 |
var line: [320]u8 (the per-func… | 320 bytes | our-design | const text = std.fmt.bufPrint(&line, "...", .{...}) catch return; at line 37 — the whole breadcrumb for that function is dropped and logFunction ret… |
Nothing. The function simply does not appear in the boot log, which reads identically to "the walk did not fin… |
system/drivers/pci-bus/pci-bus.zig:182 |
if (descriptor.resource_count >… | 8 | our-design | break out of the while (i < 6) BAR-sizing loop at line 181. Remaining BARs are never sized, never recorded in the descriptor and never restored-th… |
Nothing. No log, no counter, and the loop's configWrite16(bus, dev, function, 0x04, command) decode-restore … |
system/drivers/ps2-bus/ps2-library.zig:464 |
while (guard < 16) in drainOutp… | 16 bytes | hardware | Returns with the output-buffer-full bit possibly still set. No error, no retry, no signal to the caller (the function returns void). Callers are ps2-b… | None — silent void return. |
system/drivers/usb-hid/keyboard.zig:107 |
receive: [64]u8 (identically at… | 64 | our-design | Currently sufficient with 4 bytes to spare: the protocol's own test asserts Protocol.event_maximum == 60 and event_maximum <= envelope.post_maximum (l… | Nothing here would report an over-long message; the driver's guard is `if (message.length < @sizeOf(hid.Keyboa… |
system/drivers/usb-xhci-bus/usb-xhci-bus.zig:521 |
hid_buffer: [8]u8 (the "P… | 8 bytes | our-design | Confirmed at lines 521-523: `var hid_buffer: [8]u8 = undefined; const hid_text = std.fmt.bufPrint(&hid_buffer, "P{d}I{d}", .{ port, interface.number }… | Nothing. catch "" swallows the bufPrint failure, register returns an existing id which looks like a normal i… |
system/drivers/usb-xhci-bus/usb-xhci-bus.zig:763 |
if (serviced >= 32) break | 32 hub changes per tick | our-design | Deferral, not loss. while (engine.takeHubChange()) |change| { ... serviced += 1; if (serviced >= 32) break; } — the remaining changes stay in each… |
Not needed; nothing is lost. There is no log, correctly. |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:131 |
trbs_per_ring (= page_size / @sizeOf(Trb)) | 256 | our-design | Correct wraparound. push (155-178) writes slot enqueue_index, and when the index reaches trbs_per_ring - 1 (the Link slot) it re-installs the Li… |
Not needed. |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:456 |
port_changes: [16]u32 | 16 | hardware | Silently dropped in pump (1610-1613): `if (self.port_change_count < self.port_changes.len) { self.port_changes[...] = port; self.port_change_count +… |
Nothing at the drop site. Recovered in practice by the level reconcile in serviceController (usb-xhci-bus.zig:… |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:456 |
port_changes (inline [16]u32) | 16 | hardware | Silent drop, no else (pump, 1610-1613). The PORTSC change bits are already acknowledged at 1608-1609, so the edge is consumed even when the queue entr… | Nothing at the drop site; recovered by the independent per-port level reconcile at usb-xhci-bus.zig:727-741, w… |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:496 |
guard < 64 in the xECP capabili… | 64 extended capabilities | hardware | The while (offset != 0 and guard < 64) walk simply stops; a Supported Protocol capability past the 64th is not logged. Diagnostic only. |
Nothing distinguishes 'chain ended' (the if (next == 0) break; at 509) from 'guard tripped'. |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:603 |
device_context_array = memory.d… | 512 entries (4096 / 8), vs M… | hardware | Safe, but only by accident of type width: slot_id is a u8 (return @truncate(event.control >> 24) in enableSlot), so array[device.slot_id] cannot e… |
Not applicable today. |
system/drivers/usb-xhci-bus/usb-xhci-library.zig:1069 |
while (tries < 200) with time.s… | 200 tries = ~1 s | hardware | Falls out of the loop, re-reads status at 1076, and if still not enabled: `std.log.info("hub slot {d} port {d}: reset did not enable", .{ hub.slot_id,… | Good — a specific log line naming hub slot and port, quoted above. |
system/drivers/virtio-gpu/virtio-gpu.zig:77 |
queue_size | 16 | our-design | The only failure direction is a device offering fewer than 16, and it is checked and refused loudly — confirmed at lines 282-286: `const device_qsize … | Explicit log line carrying the device's actual value, then a clean bring-up failure. |
system/drivers/virtio-gpu/virtio-gpu.zig:163 |
while (tries < 2000) in waitUse… | 2000 iterations ≈ 2 s | our-design | Returns false (line 172). submit returns false, command_nodata returns 0 (line 184), which never equals ok_nodata, so each bring-up call site logs its… | Good on the BRING-UP path only. The serving path is silent: presentFull's two failure returns (lines 461 and 4… |
system/drivers/virtio-gpu/virtio-gpu.zig:405 |
.scanout_id = 0 (and resource_i… | 1 scanout, 1 resource, 1 bac… | hardware | No runtime limit exists — confirmed. Grepped the whole tree: get_display_info, RespDisplayInfo and max_scanouts appear ONLY in their declaration… |
Nothing about head count, because it is never asked. The file header does state the scope: "this instance clai… |
system/drivers/virtio-gpu/virtio-gpu.zig:486 |
while (tries < 50) with time.sl… | 50 tries = 1 s | our-design | Logs and returns, confirmed at lines 485-492: `const display = while (tries < 50) : (tries += 1) { if (channel.openEndpoint("display")) |h| break h;… | One clearly worded log line. The lasting consequence — the display stays on the boot framebuffer permanently —… |
system/drivers/virtio-gpu/virtio-gpu.zig:525 |
.count = offered_modes.len set … | 2 offered vs 4 slots | our-design | Not reachable at current constants (offered_modes.len = 2 <= scanout_protocol.max_modes = 4), so nothing happens today. The shape is unsafe as describ… | Would be silent at the point of the bug; the downstream re-clamps mean the surplus is dropped rather than read… |
system/kernel/acpi.zig:130 |
maximum_rmrr | 8 | hardware | Counted, not silent — confirmed at acpi.zig:873-882: `if (platform_information.rmrr_count < maximum_rmrr) { ...record... } else { platform_information… | Good, and I verified the log fires: system/kernel/iommu.zig:393-394 `if (info.rmrr_skipped > 0) log.print(" r… |
system/kernel/architecture/x86_64/cpu.zig:69 |
systemCallArg (switch arms 0..5) | 6 arguments | our-design | else => 0 — an argument index of 6 or more silently reads as zero rather than failing. Same shape at cpu.zig:788 (pioRead returns 0 for a width ot… |
None; a caller asking for a seventh argument gets a plausible-looking 0. |
system/kernel/architecture/x86_64/gdt.zig:28 |
entries | 7 | our-design | Compile-time only. const entries = 7; sizes the template (gdt.zig:36-44) and both gdts rows; setTssFor writes fixed indices 5 and 6, and loadOnThisC… |
n/a — a build-time constraint. |
system/kernel/architecture/x86_64/gdt.zig:50 |
gdts | [maximum_cpus][7]u64 (128 ta… | hardware | loadOnThisCpu(cpu) (gdt.zig:78-84) takes @intFromPtr(&gdts[cpu]) with no guard in this file; in a safe build an out-of-range cpu is a bounds-check… |
Via the ACPI/SMP path only: kernel.zig:281 prints 'cpus : WARNING {d} core(s) beyond pool cap dropped' from pl… |
system/kernel/architecture/x86_64/ioapic.zig:24 |
overrides | [16]IsoEntry | hardware | Silent truncation at three independent layers, all verified: acpi.zig:558 `if (platform_information.override_count < platform_information.overrides.le… | None at any of the three layers — no counter, no log. |
system/kernel/architecture/x86_64/iommu-intel.zig:284 |
10_000_000 (spinStatus) | 10000000 | our-design | Logs a warning and returns; enable() then sets gcmd_shadow |= gcmd_te and the core reports the IOMMU as online even though translation may not be… |
"/system/kernel: WARNING VT-d status bit never set — translation may be incomplete" — a real log line, which i… |
system/kernel/architecture/x86_64/paging.zig:70 |
bootstrap_physmap_limit | 4 << 30 (4 GiB) | hardware | @panic("paging: table frame above the 4 GiB bootstrap physmap") at paging.zig:84-85, guarded by `if (!on_own_tables and frame >= bootstrap_physmap_l… |
A named panic message on the console/serial. The 9-line comment at lines 55-62 states the window, why it holds… |
system/kernel/architecture/x86_64/per-cpu.zig:50 |
blocks | [maximum_cpus]ArchitecturePe… | hardware | setLocal(index, …) and setKernelRsp(index, …) index unguarded; bounded upstream, ReleaseSafe bounds check as backstop. A ReleaseFast build would w… |
Nothing in this file. |
system/kernel/architecture/x86_64/serial.zig:83 |
10_000 (probe guard) | 10000 | hardware | The loop ends, echo = register(0) is read regardless, and return echo == 0xAE (serial.zig:83-86). A false answer sets uart_present = false, after … |
Recoverable but indirect: present() is exposed (serial.zig:91-93) and the boot log reports the posture, and re… |
system/kernel/architecture/x86_64/smp.zig:124 |
(1 << 32) | 4294967296 | our-design | if (cr3 >= (1 << 32)) @panic("smp: kernel page tables above 4 GiB"); — the first statement of startAp, before arm() and before any INIT/SIPI is sent… |
Named panic message that states the actual condition. |
system/kernel/architecture/x86_64/smp.zig:141 |
@intCast(tramp_physical >> 12) | u8 SIPI vector (frame must b… | hardware | const vector: u8 = @intCast(tramp_physical >> 12); — in a safety-checked build (the default), a trampoline frame at or above 1 MiB triggers a "cast … |
A safety-check panic with the generic cast message — it does not name the trampoline or the 1 MiB constraint. … |
system/kernel/architecture/x86_64/smp.zig:149 |
100 (ms AP wake window) | 100 | our-design | const deadline = apic.millis() + 100; then a pause-spin on ap_alive; on expiry return false. The caller at system/kernel/kernel.zig:437-444 retrie… |
Good, and the best in this set. On give-up: `log.print("/system/kernel: cpu apic_id {d}: no response after {d… |
system/kernel/architecture/x86_64/tss.zig:48 |
tss_table / ap_ist_top | [maximum_cpus]Tss and [maxim… | hardware | rsp0Ptr (62-64), setApIstStack (68-70) and setupThisCpu index tss_table[cpu] / ap_ist_top[cpu] with no guard in this file; the bound is enfo… |
Reported by the layer above, and it really is reported: kernel.zig:280-281 `if (platform.cpusDropped() > 0) lo… |
system/kernel/device-model.zig:72 |
name_buffer | [24]u8 | our-design | Silent truncation in setName (lines 94-98, @min then @memcpy), reached from DeviceTree.init (line 138) and addChild (line 159). In practice … |
None, but nothing incorrect happens either; names are diagnostic only (the boot dump), never a matching key. |
system/kernel/device-model.zig:72 |
Device.name_buffer | [24]u8 | our-design | Silent truncation in setName; unreachable in practice. See the kernel-core duplicate: every caller passes either a literal or the result of a bufPrint… | None needed. |
system/kernel/ipc-synchronous.zig:71 |
POST_MAXIMUM | 64 | our-design | if (len > POST_MAXIMUM) return -E2BIG; — sendLocked, ipc-synchronous.zig:566, before anything is touched. A distinct errno straight back to the call… |
-E2BIG, specific and actionable. |
system/kernel/ipc-synchronous.zig:113 |
notify_buffer | [8]u64 | our-design | Silent drop of the NEWEST badge: notifyLocked, ipc-synchronous.zig:596-602 — the store happens only inside `if (endpoint.notify_tail -% endpoint.notif… | None, and the file argues at 593-595 why that is correct for a level rather than merely tolerable. |
system/kernel/ipc-synchronous.zig:113 |
Endpoint.notify_buffer | [8]u64 | our-design | Silent drop of the newest badge — outside notifyLocked's guard nothing but the wake happens (ipc-synchronous.zig:596-602). | Nothing, by design. |
system/kernel/kernel.zig:246 |
isos | [16]architecture.IsoEntry | hardware | Silent clamp: var isos: [16]architecture.IsoEntry = undefined; const iso_n = @min(pinfo.override_count, isos.len); (246-247) — a second truncation s… |
None. The boot log prints the I/O APIC base and route information but never the override count. |
system/kernel/kernel.zig:421 |
maximum_wake_attempts | 3 | our-design | The core is left parked and bring-up continues: the while (attempt <= maximum_wake_attempts) loop at 437 falls through to the log at 443-444; the ad… |
Exemplary, and verified verbatim: `log.print("/system/kernel: cpu apic_id {d}: no response after {d} attempts… |
system/kernel/log.zig:41 |
maximum_sinks | 8 | our-design | Silent ignore, confirmed at lines 47-52: `pub fn addSink(sink: SinkFn) void { if (sink_count < maximum_sinks) { sinks[sink_count] = sink; sink_count +… | None in code, though self-announcing in practice (output does not appear on the missing channel). |
system/kernel/log.zig:85 |
ring_capacity | 512 * 1024 | our-design | Whole records are reclaimed from the tail, never a torn record — confirmed at log-ring.zig:48, `while (self.head + record_len - self.tail > capacity) … | Best in the tree, as claimed, and I verified each mechanism: per-boot monotonic sequence stamped into every … |
system/kernel/log.zig:244 |
PanicRecord.message | [512]u8 | our-design | Silent truncation that is self-describing, confirmed at lines 251-256: `const n: u32 = @intCast(@min(message.len, panic_record.message.len)); @memcpy(… | The record carries its own length and the magic-last discipline prevents a torn read. Confirmed the caller's p… |
system/kernel/process.zig:109 |
maximum_arguments / maximum_argument_bytes | 8 / 256 | our-design | All three checks confirmed. process.zig:976 if (arguments_len > maximum_argument_bytes) return fail(state);; process.zig:1012 `if (argc == maximum_a… |
-1 from system_spawn with no log and the error name discarded at process.zig:1018 — confirmed. |
system/kernel/process.zig:148 |
write_buffer | [256]u8 | our-design | Confirmed at process.zig:1801: if (len <= write_buffer.len and ptr < user_half_end and ptr + len <= user_half_end) { ... } else { fail(state); } — I… |
-1 to the caller at the syscall, and the ring-level truncation is flagged in the record header — the only boun… |
system/kernel/process.zig:1460 |
exit_record_capacity | 64 | our-design | Confirmed. recordExitLocked (1467-1470) overwrites the oldest via exit_record_next = (exit_record_next + 1) % exit_record_capacity; and an evicted… |
-ESRCH with a documented interpretation, and the docstring (1455-1459) states the equivalence to 'an id that n… |
system/kernel/scheduler.zig:155 |
ipc_maximum_handles | 32 | our-design | Visible and correctly unwound, confirmed. installEntry (ipc-synchronous.zig:618-627) scans t.handles and return -ENOSPC; the cap-passing path at… |
-ENOSPC reaches the caller through the IPC status — a distinct, actionable error, unlike the -1 that most othe… |
system/kernel/scheduler.zig:485 |
cpus (PerCpu pool) | [maximum_cpus]PerCpu = [128] | hardware | Cannot be overrun. acpi.zig:534-543 gates recording on if (cpu_information.count < cpu_information.cpus.len) and counts the surplus into dropped, … |
kernel.zig:280-281 `if (platform.cpusDropped() > 0) log.print(" cpus : WARNING {d} core(s) beyond pool … |
system/kernel/tests.zig:410 |
buffer (device enumerate staging) | [64]device_abi.DeviceDescrip… | our-design | Two coupled problems. (1) The value 64 duplicates devices-broker's maximum_devices in eight places (tests.zig:410, 1449, 2834, 3931, 4230, 4246, 437… |
None for either. A test that silently examines a truncated table still passes. |
system/kernel/vfs.zig:59 |
maximum_prefix / maximum_rewrite | 64 / 32 | our-design | Visible refusal on the mount path: mountBackend, vfs.zig:383-384 `if (!isAbsolute(prefix) or prefix.len < 2 or prefix.len > maximum_prefix) return fal… | A -1 return with no log and no distinct errno. The mounting service's own failure message is what an operator … |
system/kernel/vfs.zig:143 |
Directory.path | [maximum_prefix]u8 = [64]u8 | external-data | @memcpy(d.path[0..parent.len], parent); (vfs.zig:143) into path: [maximum_prefix]u8 (vfs.zig:88) with no @min and no guard — the only copy in the … |
A boot-time panic in safe modes (loud but fatal, before init runs); nothing at all plus corrupted neighbours i… |
system/services/acpi/acpi.zig:74 |
registered | [64]Registered | our-design | Unreachable — this is NOT the operative ceiling. if (registered_count >= registered.len) return; at line 513 is the first statement of registerDevic… |
The real ceiling does log, once per lost device: `std.log.info("register refused for {s}", .{hid[0..@intCast(h… |
system/services/device-manager/device-manager.zig:51 |
registry_rules | [64]registry.Rule | external-data | Rules past the 64th are dropped by registry.parse (library/device/registry/device-registry.zig:239-241): `if (result.count >= out_rules.len) { resul… |
Good: device-manager.zig:72 `if (result.truncated) _ = logging.write("/system/services/device-manager: /system… |
system/services/device-manager/device-manager.zig:129 |
Driver.name_buffer | [64]u8 | our-design | Silent truncation, not refusal: addDriver (242-244) `const n = @min(name.len, driver.name_buffer.len); @memcpy(driver.name_buffer[0..n], name[0..n])… |
Indirect: the failure appears one step later as failed to spawn {s} (line 268) printing the truncated path, … |
system/services/device-manager/device-manager.zig:260 |
id_text | [20]u8 | our-design | arguments[0] = std.fmt.bufPrint(&id_text, "{d}", .{driver.device_id}) catch return; (264) — on overflow spawnDriver returns without spawning AND w… |
None — the only silent return in spawnDriver; every other failure path there logs (268 failed to spawn, 285/… |
system/services/display/backend.zig:69 |
100 | our-design | Confirmed at lines 68-75: `var tries: u32 = 0; const found = while (tries < 100) : (tries += 1) { if (findDisplay()) |f| break f; time.sleepMillis(5… | Logged, but misleadingly — "headless?" is one of at least three possible causes (genuinely headless, discovery… | |
system/services/display/compositor.zig:74 |
DamageList.capacity | 16 | our-design | No loss: add (lines 79-93) ends self.rects[capacity - 1] = self.rects[capacity - 1].unite(r);, so the overflow rectangle is united into the last e… |
Not needed — nothing is dropped and nothing becomes incorrect. |
system/services/display/compositor.zig:121 |
TileGrid.maximum_columns / maximum_rows | 128 / 128 | hardware | Graceful, documented degradation. reset clamps with @min((width + tile_size - 1) / tile_size, maximum_columns) and the same for rows (lines 139-14… |
No log, and none needed — the behaviour stays correct, only the repaint granularity changes. |
system/services/fat/engine.zig:24 |
max_transfer_sectors | 8 | our-design | Not a failure mode, confirmed. The transfer loop clamps and issues more commands: const run: u32 = @intCast(@min(full, max_transfer_sectors));. The … |
Not applicable — correctness is unaffected, only the number of device round-trips. |
system/services/fat/engine.zig:80 |
block_cache_lines | 16 | our-design | Round-robin eviction, write-through — correctness preserved, only hit rate degrades. | Not needed. |
system/services/fat/engine.zig:871 |
4096 | external-data | if (sector_index > 4096) return null; ends the search, so findFreeRun/addEntry return null, createFile/createDirectory return null and the VFS handl… |
None in the service; no log, and the errno collapses into the same ENOENT everything else uses. | |
system/services/fat/engine.zig:1047 |
run | [21]EntryLoc | external-data | Silent partial cleanup, confirmed. var run: [21]EntryLoc = undefined; at engine.zig:1047 (removeFile, line 1046) and 1114 (rename, line 1110), recor… |
None. |
system/services/init/init.zig:69 |
max_services | 16 | external-data | Rows past the 16th are refused and parsing stops: init.zig:114-117 if (service_count >= services.len) { _ = logging.write(...); break; }. |
Good: a direct logging.write (not just a ring entry) naming the file — `"/system/services/init: /system/conf… |
system/services/init/init.zig:84 |
init_csv / protocol_csv | [4096]u8 / [16384]u8 | external-data | Truncation, detected and reported. readConfiguration (init.zig:138-149) fills the buffer and stops (`while (used < into.len) { const n = file.read(int… | An explicit log naming the file and the byte count. It is a heuristic (a file exactly the buffer's size gives … |
system/services/init/init.zig:84 |
init_csv | 4096 bytes | external-data | Silent truncation mid-line via the shared readConfiguration (init.zig:141-146), after which the severed line parses as a service path that does not ex… | The same heuristic info log as protocol.csv: init.zig:147 '{s} filled the read buffer — rows past {d} bytes ar… |
system/services/init/init.zig:160 |
maximum_name | 64 | our-design | Refused, not truncated — contractName, init.zig:498-502 if (name.len == 0 or name.len > maximum_name) return null;, and both callers answer with an … |
None on the open path, deliberately (init.zig:652-677 explains why a refusal and an absence must be the same a… |
system/services/init/init.zig:173 |
Binding.binary | [64]u8 | our-design | Silent truncation: onBind, init.zig:630-632 `const binary_len = @min(identity.binary.len, slot.binary.len); @memcpy(slot.binary[0..binary_len], identi… | The truncated path is what appears in the provenance line (init.zig:635) and in the EBUSY refusal message (ini… |
system/services/logger/logger.zig:53 |
maximum_files | 24 | our-design | No loss. fileFor (line 229) looks for a matching cached name, then a free slot, then const cached = slot orelse evictOne() orelse return null; at li… |
Nothing logged on eviction. The symptom is slow logging, not lost logging, which is the right trade. |
system/services/logger/logger.zig:57 |
CachedFile.name | [logging.maximum_process_nam… | external-data | Panic, in a narrower window than claimed. fileFor formats the path FIRST (line 245, std.fmt.bufPrint(&path, "{s}/{s}.log", ...) catch return null) i… |
A process fault, visible as the logger dying; init's crash-loop policy stops restarting it after three deaths,… |
system/services/logger/logger.zig:72 |
carry_capacity | 64 + 256 + 64 | our-design | consume (line 187-191): `const rest = bytes.len - offset; if (rest > carry_capacity) { carry_len = 0; // cannot happen with sane frames; drop rather t… | Partly self-reporting, and the claim was right to credit it: deliver (lines 199-206) compares header.sequence … |
system/services/logger/logger.zig:82 |
64 | our-design | Benign today. service.run(64, .{ .init = initialise, .on_message = onMessage, ... }) at line 82 sizes the harness receive/reply buffer. The logger s… |
None, and none needed while onMessage is a no-op. | |
system/services/logger/logger.zig:243 |
path | [base.len + 1 + 19 + 1 + log… | our-design | Silent record loss. const full = std.fmt.bufPrint(&path, "{s}/{s}.log", .{ boot_directory[0..boot_directory_len], relative }) catch return null; (li… |
None. Records for that process never appear on disk, and the gap accounting cannot flag it: next_expected_sequ… |
tools/make-fat-image.py:53 |
(65525) | 65525 clusters (~33 MiB at 5… | our-design | Loud build failure: sys.exit(f"error: image too small for FAT32 ({self.cluster_count} clusters < 65525); use a larger size") — and --verify repeats … |
Build stops with a message naming both the actual count and the requirement, and telling the operator what to … |
tools/make-fat-image.py:212 |
(LFN sequence numbering) | implicitly 20 entries / 255 … | our-design | Silent corruption (my reading; not exercised): count = len(pairs) // 13 then entry[0] = sequence | (0x40 if sequence == count else 0) — for a nam… |
Nothing at build time; --verify only resolves EFI/BOOT/BOOTX64.EFI by short name, so a mangled LFN chain elsew… |
tools/make-fat-image.py:329 |
(guard) | 100000 cluster hops | our-design | return None, which the caller turns into a misleading verdict: sys.exit("verify: EFI/BOOT/BOOTX64.efi not found") — a chain-too-long or cyclic FAT… |
A wrong-but-visible error message. The operator is told the stub is absent when the real problem is FAT struct… |
tools/make-iso-image.py:151 |
sector_count | 0xFFFF (32 MiB at 512 B/sect… | our-design | Deliberate silent clamp, confirmed at line 151: sector_count = min(0xFFFF, esp_size // 512), packed into the El Torito default entry's 16-bit field … |
Nothing at build time about the clamp itself, but the true geometry is visible: the builder prints the ESP siz… |
tools/make-xkeyboard-config.py:308 |
(range(256)) / generated keys: … | 256 HID usages | hardware | No overflow inside the generator (HID_TO_NAME only maps usages below 0x100). The bound is exported into the generated Layout.keys: [256]Key, so any … |
Nothing here; whatever the input service does with an out-of-range usage is its own concern (outside this area… |
tools/make-xkeyboard-config.py:314 |
(range(4)) / generated levels: … | 4 shift levels per key | external-data | Silent truncation at generation time: levels = [resolve_keysym(kd.levels[i], keysymdef) if i < len(kd.levels) else (0, 0) for i in range(4)] — level… |
Nothing. The generator prints no warning and the generated file looks complete; the missing characters only ap… |