<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Eli Grubb · Notes</title><description>Notes from Eli Grubb.</description><link>https://eligrubb.com/</link><language>en-us</language><item><title>TIL: Testing Secure Zeroization in Zig with Custom Memory Allocators</title><link>https://eligrubb.com/writings/notes/2025/til-zig-custom-memory-allocator/</link><guid isPermaLink="true">https://eligrubb.com/writings/notes/2025/til-zig-custom-memory-allocator/</guid><description>Learn how a custom Zig allocator can automatically verify zeroization and catch memory leaks in your security-critical code.</description><pubDate>Wed, 20 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;or, How Zig’s explicit memory management makes it easy to test your sanitization
guarantee&lt;/p&gt;
&lt;p&gt;While &lt;a href=&quot;https://x.com/grubbbyte/status/1935793372679356447&quot;&gt;spending the summer learning
Zig&lt;/a&gt; I have come to love
and appreciate one of the language’s core philosophies: what you see is what
you get.&lt;/p&gt;
&lt;p&gt;In Zig, there’s no operator overloading and memory allocations are always
explicit. Simply reading the code should reveal &lt;em&gt;exactly&lt;/em&gt; what your software is
instructing the computer to do. If a library allocates memory, the idiomatic
approach is to accept a memory allocator as an input, so callers can pick the
memory management strategy that matches the end use-case.&lt;/p&gt;
&lt;p&gt;There are exceptions,&lt;sup&gt;&lt;span data-footnote-ref=&quot;&quot;&gt;1&lt;/span&gt;&lt;/sup&gt; and other languages have reasons they allow
such abstractions, but I’ve enjoyed working in this style. It aligns well with
my current interests and experience. When I return to other, more “sugary”,
languages, using Zig has improved my feel for where the “hidden” allocations
and functionality are.&lt;/p&gt;&lt;aside id=&quot;sidecar-footnote-nerd&quot; class=&quot;sidecar-box sidecar-box--right sidecar-footnote&quot;&gt;&lt;p class=&quot;sidecar-box__title&quot;&gt;Note 1&lt;/p&gt;&lt;div class=&quot;sidecar-box__body&quot;&gt;
&lt;p&gt;Well 🫵, actually ☝️, &lt;em&gt;any&lt;/em&gt; language at all is an abstraction and,
therefore 🤓, a lie 😌. &lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;an-idea-begins-to-form&quot;&gt;An idea begins to form&lt;/h2&gt;
&lt;p&gt;In particular, this is useful for &lt;strong&gt;testing that your custom memory
management strategies are, actually, working&lt;/strong&gt;. My first “real” Zig project, the
&lt;a href=&quot;https://github.com/eligrubb/zecrecy&quot;&gt;Zecrecy&lt;/a&gt; library, zeros out sensitive
data before freeing the memory to &lt;a href=&quot;https://dwheeler.com/essays/heartbleed.html#overwrite-critical&quot;&gt;mitigate the
impact&lt;/a&gt; of
Heartbleed-style vulnerabilities.&lt;/p&gt;
&lt;p&gt;Because Zig is explicit and its docs are still maturing, you are reading the
standard library’s source code by the time you build much more than “hello
world”.&lt;sup&gt;&lt;span data-footnote-ref=&quot;&quot;&gt;2&lt;/span&gt;&lt;/sup&gt; I’d read the code for the &lt;code&gt;std.mem.Allocator&lt;/code&gt; interface, along
with several of the allocator implementations in the standard library, so I
felt confident enough to try it when the idea popped into my head: a custom
allocator that panics if asked to free non-zero memory.&lt;/p&gt;&lt;aside id=&quot;sidecar-footnote-mh&quot; class=&quot;sidecar-box sidecar-box--right sidecar-footnote&quot;&gt;&lt;p class=&quot;sidecar-box__title&quot;&gt;Note 2&lt;/p&gt;&lt;div class=&quot;sidecar-box__body&quot;&gt;
&lt;p&gt;I recently heard &lt;a href=&quot;https://mitchellh.com/&quot;&gt;Mitchell Hashimoto&lt;/a&gt; on a
podcast say when he’s learning a new language, his first step is to read
the standard library. After, effectively, being forced to do so to truly learn
Zig, I’m ready to co-sign this approach (&lt;a href=&quot;https://x.com/grubbbyte/status/1957989330166992944&quot;&gt;massive
news&lt;/a&gt;, I know). I need to
try with at least one more language to be sure - Zig, by design, is relatively
simple. Reading the standard library too early could be unnecessarily
overwhelming in some other languages. &lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Of course, this is not a novel idea. I learned it from the Zig Standard
Library’s testing &lt;code&gt;Allocator&lt;/code&gt;, a nifty implementation that takes advantage of
Zig’s memory management paradigm. In testing, use &lt;code&gt;std.testing.allocator&lt;/code&gt; when
a call requests a memory allocator. The test will panic if the
allocator detects any memory leaks during testing.&lt;sup&gt;&lt;span data-footnote-ref=&quot;&quot;&gt;3&lt;/span&gt;&lt;/sup&gt;&lt;/p&gt;&lt;aside id=&quot;sidecar-footnote-leak&quot; class=&quot;sidecar-box sidecar-box--right sidecar-footnote&quot;&gt;&lt;p class=&quot;sidecar-box__title&quot;&gt;Note 3&lt;/p&gt;&lt;div class=&quot;sidecar-box__body&quot;&gt;
&lt;p&gt;So far, this has only caught &lt;code&gt;defer .deinit()&lt;/code&gt; statements missing from
the tests themselves. But, that helped build the habit of using Zig’s
&lt;code&gt;defer&lt;/code&gt; keyword and memory management style. It’s because of this, and very
nice feedback on Zig’s discord (thank you @silversquirl), that I built the
&lt;code&gt;Zecrecy&lt;/code&gt; library around a &lt;code&gt;defer .deinit()&lt;/code&gt; management pattern. &lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;To improve Zecrecy’s testing quality, I wrote
&lt;a href=&quot;https://github.com/eligrubb/zecrecy/blob/trunk/src/testing/ZerosOnlyAllocator.zig&quot;&gt;ZerosOnlyAllocator&lt;/a&gt;.
It’s pretty simple, it wraps a child allocator to handle the actual
allocations. This has a couple benefits:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I don’t have to write my own allocation logic just for a bit of testing,
and&lt;/li&gt;
&lt;li&gt;If the child allocator is &lt;code&gt;std.testing.allocator&lt;/code&gt;, then I get
memory-leak detection in the same test run!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The core “functionality” lies in the &lt;code&gt;free()&lt;/code&gt; function:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;zig&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/// Panics if the memory is not zeroed before freeing.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; free&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    ctx&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*anyopaque&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: []&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    alignment&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;mem&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;Alignment&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    ret_addr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;usize&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ZerosOnlyAllocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; @ptrCast&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;@alignCast&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;buf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;@panic&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;non-zero byte freed&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;child_allocator&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;rawFree&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;buf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;alignment&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ret_addr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I love this kind of thing because it only gains value the more tests I add.
Test setup is only three lines:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;zig&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; ZerosOnlyAllocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; @import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;testing/ZerosOnlyAllocator.zig&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; zeros_only_allocator&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ZerosOnlyAllocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;init&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;testing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; allocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; zeros_only_allocator&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, every single test automatically verifies our core security guarantee
with zero additional effort.&lt;/p&gt;
&lt;h2 id=&quot;debugging-detour&quot;&gt;Debugging detour&lt;/h2&gt;
&lt;p&gt;Except! The first time I ran unit tests using the shiny, new, custom allocator,
every single test panicked:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/zecrecy&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; zig test src/secret.zig&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;thread&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3381248&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; panic:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; non-zero&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; byte&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; freed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/zecrecy/src/testing/ZerosOnlyAllocator.zig:59:24: 0x104dbc753 in free (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;test&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;@panic(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;&quot;non-zero byte freed&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;                       ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/.cache/zig/p/N-V-__8AAPWKhxNMNK6YniIioDpRryBzI7DMp0hJB4rExlGU/lib/std/mem/Allocator.zig:147:25: 0x10236238f in free__anon_5332 (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;test&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; a.vtable.free&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;a.ptr,&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; memory,&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; alignment,&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ret_addr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;                        ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/zecrecy/src/secret.zig:120:34: 0x10235e12b in deinit (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;test&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;            secret.allocator.free(secret.data&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Turns out, my assumption that reading the standard library once makes one an
expert was, unsurprisingly, wrong. The custom allocator’s logic was correct,
but the standard library contained some unexpected functionality that broke my
assumptions:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;zig&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/// From `std.mem.Allocator`:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;///&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/// Free an array allocated with `alloc`.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/// If memory has length 0, free is a no-op.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/// To free a single item, see `destroy`.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; fn&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; free&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;Allocator&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;memory&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;anytype&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; Slice&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; @typeInfo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;@TypeOf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;memory&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)).&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;pointer&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; bytes&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; mem&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;sliceAsBytes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;memory&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; bytes_len&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; bytes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                      if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;Slice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;sentinel&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;@sizeOf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;Slice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;child&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;bytes_len&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; non_const_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; @constCast&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;bytes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ptr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    @memset&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;non_const_ptr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;bytes_len&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;undefined&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;rawFree&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;non_const_ptr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;bytes_len&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fromByteUnits&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;Slice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;alignment&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;@returnAddress&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All tests panicked because &lt;code&gt;std.mem.Allocator.free&lt;/code&gt;&lt;sup&gt;&lt;span data-footnote-ref=&quot;&quot;&gt;4&lt;/span&gt;&lt;/sup&gt; writes &lt;code&gt;undefined&lt;/code&gt;
into freed memory before calling &lt;code&gt;.rawFree&lt;/code&gt;. In Debug and ReleaseSafe modes
&lt;a href=&quot;https://ziglang.org/documentation/master/#undefined&quot;&gt;Zig fills undefined
bytes&lt;/a&gt; with a debug
pattern (&lt;code&gt;0xAA&lt;/code&gt;) to catch use-after-free bugs,&lt;sup&gt;&lt;span data-footnote-ref=&quot;&quot;&gt;5&lt;/span&gt;&lt;/sup&gt; which meant my test allocator
saw non-zero bytes.&lt;/p&gt;&lt;aside id=&quot;sidecar-footnote-oops&quot; class=&quot;sidecar-box sidecar-box--right sidecar-footnote&quot;&gt;&lt;p class=&quot;sidecar-box__title&quot;&gt;Note 4&lt;/p&gt;&lt;div class=&quot;sidecar-box__body&quot;&gt;
&lt;p&gt;Not to be mistaken with &lt;code&gt;std.mem.Allocator.vtable.free&lt;/code&gt;. &lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;&lt;aside id=&quot;sidecar-footnote-zero&quot; class=&quot;sidecar-box sidecar-box--right sidecar-footnote&quot;&gt;&lt;p class=&quot;sidecar-box__title&quot;&gt;Note 5&lt;/p&gt;&lt;div class=&quot;sidecar-box__body&quot;&gt;
&lt;p&gt;At other optimization levels, the compiler probably removes the
&lt;code&gt;memset&lt;/code&gt; operation completely. This is why libraries like Zecrecy are
important, compilers have free reign to do unsightly things to your code in the
name of optimization. Even when you try your hardest and follow best practices,
&lt;a href=&quot;https://eprint.iacr.org/2023/1713&quot;&gt;it can be impossible to completely stop the compiler from doing things like
this&lt;/a&gt;. But that’s the subject of a future
rant :). &lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;The solution? Bypass the layer altogether and call &lt;code&gt;.rawFree()&lt;/code&gt;
directly.&lt;sup&gt;&lt;span data-footnote-ref=&quot;&quot;&gt;6&lt;/span&gt;&lt;/sup&gt; Now, we can verify zeroization at the layer closest to
deallocation.&lt;/p&gt;&lt;aside id=&quot;sidecar-footnote-test&quot; class=&quot;sidecar-box sidecar-box--right sidecar-footnote&quot;&gt;&lt;p class=&quot;sidecar-box__title&quot;&gt;Note 6&lt;/p&gt;&lt;div class=&quot;sidecar-box__body&quot;&gt;
&lt;p&gt;I considered modifying &lt;code&gt;.deinit&lt;/code&gt; to check if it’s being called from a
test, using either &lt;code&gt;.rawFree&lt;/code&gt; or &lt;code&gt;.free&lt;/code&gt; based on the result. But, I
dislike the idea of creating branches designed to be untestable. I could be
swayed, but a little responsibility is fine if it means tests follow the same
paths as normal library use. &lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;&lt;code&gt;mem.Allocator.free&lt;/code&gt; does what it does for a reason, and I don’t skip it
lightly. The name &lt;code&gt;.rawFree&lt;/code&gt; is meant to make you nervous. For example, in
Debug or ReleaseSafe mode, setting all bytes to &lt;code&gt;undefined&lt;/code&gt; means you get some
use-after-free protection that we could be losing by calling &lt;code&gt;.rawFree&lt;/code&gt;
instead.&lt;/p&gt;
&lt;p&gt;However, in this case, I felt comfortable with this choice after familiarizing
myself.&lt;/p&gt;
&lt;p&gt;The first three lines of &lt;code&gt;Allocator.free&lt;/code&gt; are because memory can be &lt;code&gt;anytype&lt;/code&gt;,
so the code verifies memory is a slice, handles a potential sentinel, etc.
This the only function I call &lt;code&gt;.rawFree&lt;/code&gt; in is &lt;code&gt;.deinit&lt;/code&gt;, which only accepts
slices. No &lt;code&gt;@typeInfo&lt;/code&gt; magic needed.&lt;/p&gt;
&lt;p&gt;What about the &lt;code&gt;@memset&lt;/code&gt;? Zecrecy uses standard library’s &lt;code&gt;crypto.secureZero&lt;/code&gt;
function to wipe memory, which uses techniques intended to avoid optimization
removal. However, those techniques have their own &lt;a href=&quot;https://users.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf&quot;&gt;flawed history and corner
cases&lt;/a&gt;. Test
reinforcement is always valuable, never take security for granted.&lt;/p&gt;
&lt;p&gt;Outside of actually calling &lt;code&gt;.rawFree&lt;/code&gt;,  the only change I is to return early
if the data length is 0. This has no security/correctness benefits but offers a
small performance bump by avoiding the virtual function call when it’s not
needed. Due to the nature of the library (how often will someone will be
initializing a secret of length 0?), I think even if I had skipped this no-op
opportunity, the &lt;code&gt;.rawFree&lt;/code&gt; call is fine.&lt;/p&gt;
&lt;p&gt;And boom! All tests pass:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/zecrecy&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; zig test src/secret.zig&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;All&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 15&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; tests&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; passed.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With each one, I can feel a tiny bit better
knowing all secrets were actually zeroed before they were freed.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The effort required was low for the value gained, I’ve barely scratched the
surface of using custom memory allocators to improve testing.&lt;sup&gt;&lt;span data-footnote-ref=&quot;&quot;&gt;7&lt;/span&gt;&lt;/sup&gt; Reducing the
“black box” opaqueness that sometimes hangs like a fog over unit tests is a
nice tool to have. I’m optimistic that Zig’s upcoming async/IO changes will
provide similar opportunities to get surgical during testing.&lt;/p&gt;&lt;aside id=&quot;sidecar-footnote-fail&quot; class=&quot;sidecar-box sidecar-box--right sidecar-footnote&quot;&gt;&lt;p class=&quot;sidecar-box__title&quot;&gt;Note 7&lt;/p&gt;&lt;div class=&quot;sidecar-box__body&quot;&gt;
&lt;p&gt;Do you test if your system gracefully and securely handles failing
memory allocations? Well, in Zig you easily can with
&lt;code&gt;std.testing.FailingAllocator&lt;/code&gt;! &lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;And, of course, building test harnesses that enforce application invariants is
far from unique to Zig. It’s a powerful technique with demonstrated value.
Zig’s win, for me, is in making every decision explicit and shoving the reality
of an implementation into your face at all times. You naturally think deeper
about how to wield the verbosity in your favor.&lt;/p&gt;
&lt;p&gt;Have any cool, weird, or otherwise nerdy uses you’ve gotten out of Zig’s memory
management explicitness? Do you have a favorite method for testing your
system’s security guarantees? &lt;a href=&quot;mailto:eli@eligrubb.com&quot;&gt;Send me an email&lt;/a&gt; or a
&lt;a href=&quot;https://twitter.com/grubbbyte&quot;&gt;message&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;TL;DR:
&lt;img alt=&quot;The Drake meme. On top, Drake rejecting the common refrain &amp;#x22;RTFM&amp;#x22; (Read The
F***ing Manual). On bottom, Drake approving the text &amp;#x22;RTFSTD&amp;#x22; (Read The
F***ing Standard Library.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;500&quot; src=&quot;https://eligrubb.com/_astro/meme.zR9tPDUj_XoO7X.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
</content:encoded><category>Notes</category><category>TIL</category><category>programming</category><category>zig</category><category>systems engineering</category><category>memory management</category><category>security</category><category>zeroization</category><author>Eli Grubb</author></item><item><title>TIL: compile with a locally patched Zig standard library via &lt;code&gt;--zig-lib-dir&lt;/code&gt;</title><link>https://eligrubb.com/writings/notes/2025/til-zig-lib-dir/</link><guid isPermaLink="true">https://eligrubb.com/writings/notes/2025/til-zig-lib-dir/</guid><description>TIL: compile with a locally patched Zig standard library via &lt;code&gt;--zig-lib-dir&lt;/code&gt;</description><pubDate>Fri, 25 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;alt-title: find a way to narrow down the scope of your comparisons (and
compilations).&lt;/p&gt;
&lt;p&gt;While &lt;a href=&quot;https://eligrubb.com/#TBC&quot;&gt;benchmarking the impact&lt;/a&gt; of &lt;a href=&quot;https://github.com/ziglang/zig/pull/24429&quot;&gt;Zig removing inlines from their
standard cryptography library&lt;/a&gt;, my
naive initial approach compared the changes from the perspective of the Zig
project as a whole, not just the standard library itself. In reality, this
meant every time I modified a Zig crypto implementation while experimenting,
even just to call &lt;code&gt;std.debug.print&lt;/code&gt;, I was rebuilding the entire project from
source.&lt;/p&gt;
&lt;p&gt;The Zig build system feels powerful and I’m planning out a new project to coat
myself in all the grimy details&lt;sup&gt;&lt;span data-footnote-ref=&quot;&quot;&gt;1&lt;/span&gt;&lt;/sup&gt;. In the meantime, I got started with Loris
Cro’s excellent &lt;a href=&quot;https://www.youtube.com/watch?v=jy7w_7JZYyw&quot;&gt;Zig Build System Basics
video&lt;/a&gt;, and the &lt;a href=&quot;https://ziglang.org/learn/build-system/&quot;&gt;existing
documentation&lt;/a&gt;. I followed the Zig
wiki’s instructions for &lt;a href=&quot;https://github.com/ziglang/zig/wiki/Building-Zig-From-Source&quot;&gt;building from
source&lt;/a&gt; on both
&lt;a href=&quot;https://eligrubb.com/#TBC&quot;&gt;mac and linux&lt;/a&gt;.&lt;/p&gt;&lt;aside id=&quot;sidecar-footnote-1&quot; class=&quot;sidecar-box sidecar-box--right sidecar-footnote&quot;&gt;&lt;p class=&quot;sidecar-box__title&quot;&gt;Note 1&lt;/p&gt;&lt;div class=&quot;sidecar-box__body&quot;&gt;
&lt;p&gt;Hint: it involves porting the build system of an existing (academic) C++
project I’ve long admired, with a goal of extending the code base using
Zig. More soon! &lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;But, of course, &lt;strong&gt;there’s a flag for that&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;zsh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; zig&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; build&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --help&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Usage:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; zig&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; build&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [steps] [options]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Advanced&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Options:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  --zig-lib-dir&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [arg]          Override path to Zig lib directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can input the path of the &lt;code&gt;lib&lt;/code&gt; directory containing an instantiation of the
Zig standard library and &lt;code&gt;zig build&lt;/code&gt; will compile without extra steps or
linking. Now instead of feeling stuck at the bird’s eye view of the &lt;em&gt;entire&lt;/em&gt;
Zig source, it’s much easier to quickly compare and contrast the small nudges
and curiosities.&lt;/p&gt;
&lt;p&gt;Just call:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;zsh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;zig&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; build&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --zig-lib-dir&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ../zig-master/lib&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Those familiar with the &lt;a href=&quot;https://github.com/ziglang/zig&quot;&gt;ziglang codebase&lt;/a&gt; may
note that the directory for the standard library isn’t &lt;code&gt;lib/&lt;/code&gt;, it’s &lt;code&gt;lib/std/&lt;/code&gt;.
This means that &lt;code&gt;--zig-lib-dir&lt;/code&gt; allows us specify a lot more than &lt;em&gt;just&lt;/em&gt; the
standard library for injection, we’re just scratching the surface here&lt;sup&gt;&lt;span data-footnote-ref=&quot;&quot;&gt;2&lt;/span&gt;&lt;/sup&gt;.&lt;/p&gt;&lt;aside id=&quot;sidecar-footnote-2&quot; class=&quot;sidecar-box sidecar-box--right sidecar-footnote&quot;&gt;&lt;p class=&quot;sidecar-box__title&quot;&gt;Note 2&lt;/p&gt;&lt;div class=&quot;sidecar-box__body&quot;&gt;
&lt;p&gt;Have a cool use for this flag in your workflow? Send me an message! &lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Benchmarking changes is much smoother now. I simply point my script to the
appropriate &lt;code&gt;git worktree&lt;/code&gt; directory for each version and away we go!&lt;/p&gt;
</content:encoded><category>Notes</category><category>zig</category><category>TIL</category><category>programming</category><author>Eli Grubb</author></item><item><title>Odd tcsh issue on alpine linux [UPDATED]</title><link>https://eligrubb.com/writings/notes/2018/tcsh-and-alpine-linux-bug/</link><guid isPermaLink="true">https://eligrubb.com/writings/notes/2018/tcsh-and-alpine-linux-bug/</guid><description>Odd tcsh issue on alpine linux [UPDATED]</description><pubDate>Mon, 05 Feb 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’m currently working with &lt;a href=&quot;https://alpinelinux.org/&quot;&gt;alpine linux&lt;/a&gt;, trying to
port some existing systems over to this minimal OS. It’s not an easy task.
Currently my issue is with &lt;a href=&quot;http://www.tcsh.org/&quot;&gt;&lt;code&gt;tcsh&lt;/code&gt;&lt;/a&gt;. It seems that &lt;code&gt;tcsh&lt;/code&gt;
is triggering some kind of core dump every time it is called. Here’s the output
when it’s called:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;(nil) current memory allocation:                                                                                &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;free:       0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0                       &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;used:       0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0                       &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        Total in use: 0, total free: 0                                                                          &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        Allocated memory from 0x55bd1509d000 to 0xffffffffffffffff.  Real top at 0x55bd1509d000                 &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;nbytes=64: Out of memory                                                                                        &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I’ve been googling and going through alpine’s &lt;a href=&quot;https://bugs.alpinelinux.org/projects/alpine/search?utf8=%E2%9C%93&amp;#x26;q=tcsh&amp;#x26;scope=all&amp;#x26;all_words=&amp;#x26;all_words=1&amp;#x26;titles_only=&amp;#x26;issues=1&amp;#x26;news=1&amp;#x26;documents=1&amp;#x26;changesets=1&amp;#x26;wiki_pages=1&amp;#x26;messages=1&amp;#x26;projects=1&amp;#x26;attachments=0&amp;#x26;options=0&amp;#x26;commit=Submit&quot;&gt;bug
tracker&lt;/a&gt;
but there’s no mention of &lt;code&gt;tcsh&lt;/code&gt; in there system beside the day they committed
it to their repository. It is worth noting that the package is &lt;a href=&quot;https://pkgs.alpinelinux.org/package/edge/testing/x86/tcsh&quot;&gt;currently in
the testing branch&lt;/a&gt;
of their apk package manager so there were no guarantees. It is interesting
that there seems to be literally no evidence anyone else has run into this
issue. Also somewhat intriguing is the fact that the alpine maintainers have no
documented interest in moving &lt;code&gt;tcsh&lt;/code&gt; to a stable branch anytime soon. I agree
that it’s probably an outdated tool, but still popular enough it should have
higher priority.&lt;/p&gt;
&lt;p&gt;If anyone has any potential solutions &lt;a href=&quot;mailto:grubb@cs.utah.edu&quot;&gt;shoot me an email&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE (February 12, 2018):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Having submitted the bug to the Alpine Linux issue tracker, I received a
&lt;a href=&quot;https://bugs.alpinelinux.org/issues/8483&quot;&gt;pointer to a patch&lt;/a&gt; in the
&lt;a href=&quot;https://github.com/openwrt/packages/blob/master/utils/tcsh/patches/001-sysmalloc.patch&quot;&gt;openwrt&lt;/a&gt;
project that seems to fix this issue. At the very least, &lt;code&gt;tcsh&lt;/code&gt; actually boots
and seems to function as a shell once it’s applied. I’m going to work on either
getting the patch committed to the actual alpine package repo or build a custom
&lt;code&gt;tcsh&lt;/code&gt; for my system with the patch.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 2 (February 27, 2018):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This patch has now been &lt;a href=&quot;https://github.com/alpinelinux/aports/pull/3302&quot;&gt;committed to alpine’s apk
repository&lt;/a&gt;. This took a
little more effort than expected, and there’s definitely still some open issues
with the package before it can be moved from the edge branch to the main
package repo branch. As referenced in the linked github PR, the musl libc
appears to break a lot of basic functionality in &lt;code&gt;tcsh&lt;/code&gt;. As you can see
&lt;a href=&quot;http://tpaste.us/L6R4&quot;&gt;here&lt;/a&gt; the number and nature of regression tests failed
is somewhat alarming. However, by hand testing shows that basic functionality
needed for my project works. Who knows, maybe it will convince some old-timers
to switch to a more modern shell like &lt;code&gt;bash&lt;/code&gt; ;).&lt;/p&gt;
&lt;p&gt;It does however, bring up an interesting conversation about whether there is
sufficient motivation for these issues to ever be fixed. The last few remaining
active &lt;code&gt;tcsh&lt;/code&gt; developers have no desire to work to get their package working
with an upstart libc like &lt;code&gt;musl&lt;/code&gt; and &lt;code&gt;musl&lt;/code&gt; developers have no motivation to
work on supporting a shell none of their target users actively rely on. I think
my work has fallen into a rather small demographic.&lt;/p&gt;</content:encoded><category>Notes</category><category>archive</category><category>Software</category><category>Programming</category><category>linux</category><author>Eli Grubb</author></item><item><title>Alpine Package Names</title><link>https://eligrubb.com/writings/notes/2017/alpine-package-names/</link><guid isPermaLink="true">https://eligrubb.com/writings/notes/2017/alpine-package-names/</guid><description>Alpine Package Names</description><pubDate>Wed, 08 Nov 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As part of my research work in the &lt;a href=&quot;http://www.flux.utah.edu&quot;&gt;Flux Research
Group&lt;/a&gt; I’ve been working very closely with &lt;a href=&quot;https://www.alpinelinux.org&quot;&gt;Alpine
Linux&lt;/a&gt;. My current project involves translating a
bunch of scripts for building a particular Ubuntu image into the same process
for an Alpine image. As such, I’ve had the fun of finding packages in Alpine’s
&lt;a href=&quot;https://pkgs.alpinelinux.org/packages&quot;&gt;apk&lt;/a&gt; package manager that are currently
being installed through apt-get. This is just a quick post to serve as a
reference for inconsistencies I’ve found across the two, and the packages I
installed instead.&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;center&quot;&gt;Ubuntu (16.04)&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;Alpine (3.6)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;libtool-bin&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;libtool&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;libssl-dev&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;openssl-dev&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;libboost-dev&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;boost-dev&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;iputils-ping&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;iputils&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;perl-modules&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;???&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;libwww-perl&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;perl-libwww&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;tcsh&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;tsch@testing*&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;ksh&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;mksh&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;brctl&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;bridge-utils&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;* tcsh is currently only found in the testing branch of apk. You have to add
the link to the testing branch to /etc/apk/repositories as described
&lt;a href=&quot;https://wiki.alpinelinux.org/wiki/Alpine_Linux_package_management#Add_a_Package&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If anyone has any corrections, questions or additions to this short list feel
free to reach out to me on &lt;a href=&quot;https://twitter.com/judgegrubb&quot;&gt;twitter&lt;/a&gt; or by
&lt;a href=&quot;mailto:grubb@cs.utah.edu&quot;&gt;email&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Notes</category><category>archive</category><category>Programming</category><category>Software</category><category>linux</category><author>Eli Grubb</author></item><item><title>gitignore_global</title><link>https://eligrubb.com/writings/notes/2015/gitignore-global/</link><guid isPermaLink="true">https://eligrubb.com/writings/notes/2015/gitignore-global/</guid><description>gitignore_global</description><pubDate>Fri, 02 Oct 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I need git for every change I make anywhere on my computer apparently.&lt;/p&gt;
&lt;p&gt;Today while working on a project for CS 3500 I ran into a curious bug that made me wonder what in the world I was thinking at the time.&lt;/p&gt;
&lt;p&gt;In trying to commit some .dll files as resources to my Visual C# app in Visual Studio I came to the odd realization that they weren’t actually included in my repo. Curious.&lt;/p&gt;
&lt;p&gt;It got even weirder when I manually right-clicked and added it to my git. Yet when I clicked commit I got an error claiming that I wasn’t committing any files even though they were both RIGHT THERE. Curiouser and curiouser.&lt;/p&gt;
&lt;p&gt;Finally I was able to debug my issues when I happened upon some extremely helpful git commands thanks to &lt;a href=&quot;http://stackoverflow.com/questions/32417729/an-error-occurred-detailed-message-no-changes-nothing-to-commit-visual-studi&quot;&gt;this&lt;/a&gt; stack overflow post.&lt;/p&gt;
&lt;p&gt;Using the described techniques I found a file in my Documents folder (no where near or associated with my C# development) titled “gitignore_global”. This document explicitly set git to ignore several visual studio specific files including, you guessed it, *.dll.&lt;/p&gt;
&lt;p&gt;I renamed the file and what do you know? It all committed nice and easy now! WOO HOO!&lt;/p&gt;
&lt;p&gt;I still have no idea why I created that file in the first place. And why in my Documents folder that has nothing to do with any of my development projects??&lt;/p&gt;
&lt;p&gt;I’m still scratching my head. Oh well. I guess that’s better then banging it against my desk in frustration.&lt;/p&gt;
&lt;p&gt;Sometimes even the best technologies are just plain dumb.&lt;/p&gt;</content:encoded><category>Notes</category><category>archive</category><category>Software</category><category>Programming</category><author>Eli Grubb</author></item><item><title>Testing Class Libraries with C# in Visual Studio</title><link>https://eligrubb.com/writings/notes/2015/testing-class-libraries/</link><guid isPermaLink="true">https://eligrubb.com/writings/notes/2015/testing-class-libraries/</guid><description>Testing Class Libraries with C# in Visual Studio</description><pubDate>Tue, 08 Sep 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When building a Class Library for my CS 3500 class we are required to build our own little testing suites on our machines. These tests aren’t to be uploaded to the GitHub repository for our project, but obviously it is necessary if we want to build a functioning program. As this is my first foray into the world of C# and, more importantly, Visual Studio, I found it slightly difficult to figure out out to write even rudementary Console Application tests for my Class Library. This post is to act as a reminder as to how to successfully add a ConsoleApplication Project to a solution and use it to test a Class Library.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: This was done using Visual Studio 2015 Enterprise and any differences in your setup is probably a result of this&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Once you have your initial Class Library created with a class and method you would like to test, you will find yourself to run any tests within the same project. Due to Class Librarys compiling down to .dll files and not something like a .exe there is no way to run that project directly. Instead you need to create another project that &lt;em&gt;does&lt;/em&gt; compile down to a .exe and have it reference your Class Library&lt;/p&gt;
&lt;p&gt;The first thing you will do is select File -&gt; New -&gt; Project…&lt;/p&gt;
&lt;p&gt;In this case I am testing my project using a Console Application so I will choose Visual C# -&gt; Windows -&gt; Console Application as my application type.&lt;/p&gt;
&lt;p&gt;It doesn’t matter what your project’s name is, but for simplicity I suggest using the format &lt;classlibraryprojectname&gt;Test. In this case since I’m working on a Class Library called Formula Evaluator I’m naming my Console Application FormulaEvaluatorTest.&lt;/classlibraryprojectname&gt;&lt;/p&gt;
&lt;p&gt;Make sure it’s in the same location as your Class Library Project and add to the existing solution to ensure continuity.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;New Project&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1413&quot; height=&quot;806&quot; src=&quot;https://eligrubb.com/_astro/new-project.DVkt1BIL_Z2eGiVz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;After you create this new project it will open up it’s Program.cs file which contains what this whole process is about, the Main Function. Now you have a program that can actually execute operations. However, you are not quite done.&lt;/p&gt;
&lt;p&gt;To ensure you have access to your Class Library in your new project, in the Solution Explorer right-click on your Console Application and select Add -&gt; Reference…&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Add Reference&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1055&quot; height=&quot;1019&quot; src=&quot;https://eligrubb.com/_astro/add-reference.BayhkUYi_yIgSY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Select Projects -&gt; Solution from the left hand column and find your Class Library in the center pane. Make sure that it’s checkbox is checked, then hit OK. You should now be able to write the line using MyClassLibrary in your console application without any errors.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Reference Manager&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1180&quot; height=&quot;815&quot; src=&quot;https://eligrubb.com/_astro/reference-manager.BA33YTIN_Zy1Acq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;You are just about done. But wait! When you attempt to run your Console Application, you probably end up with this error:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Startup Error&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;663&quot; height=&quot;364&quot; src=&quot;https://eligrubb.com/_astro/start-up-error.UpVPlm7e_Zaqlpq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Your solution is automatically choosing your Class Library to run when you run the solution as a whole and this just doesn’t work. Like we discussed earlier, since Class Libraries compile down to a .dll file you cannot run it. You need to run the .exe file that your Console Application compiles down to.&lt;/p&gt;
&lt;p&gt;To change this you simple right-click on your Console Application and select Set as StartUp Project&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Set as StartUp Project&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;727&quot; height=&quot;1018&quot; src=&quot;https://eligrubb.com/_astro/set-as-start-up.CKbzuF78_Z2q1n3U.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now when you hit the Start button on the top toolbar to run your solution, it is your Console Application that will run.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;It&amp;#x27;s Working!&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1021&quot; src=&quot;https://eligrubb.com/_astro/its-working.Dn6I395h_1vQS6P.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Happy (C#) Hacking!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 9/16:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I finally learned how to do this with unit tests. And I feel rather silly now that I’ve been taught. Simply replicate my process but instead of selecting a console application, select the “Tests” category on the left and choose a Unit Test Application. Unit Tests are so much better than testing with a Console Application and I’m not looking back. But that’s mainly because of how silly I feel not knowing how to use unit tests before.&lt;/p&gt;</content:encoded><category>Notes</category><category>Programming</category><category>Testing</category><category>Software</category><category>archive</category><author>Eli Grubb</author></item></channel></rss>