RSSAmplifier

Blog

Matthias Görgens

Notes on OCaml, Rust, property-based testing, zero-knowledge VMs, and breaking the occasional cipher.

paquari.comRSS feed ↗14 posts

Latest posts

Claude Code permissions: parse the command, don't match the string

Anthropic made auto mode the default in Claude Code, and the Hacker News thread about it is full of a complaint I recognise: These models generate the most unreadable bash commands I’ve ever seen. Utilising every single option available and piping the result through multiple layers of regex and junk. The mental load of having to actually review these commands beyond the most surface level glance…

Anatomy of a LinkedIn "fake job" malware drop: the DeFi_share.zip git-hook trap

A LinkedIn “recruiter” pitching an AI-DeFi job sent me a project archive ( DeFi_share.zip ). The archive contains a git repository in which every working-tree file is truncated to zero bytes and a .git/hooks/post-checkout script is planted. Anyone who tries to “fix” the apparently broken checkout with git checkout . or git switch dev automatically executes the hook, which pipes a remote…

Point UBSan at your existing test suite

I have a bit of an obsession with undefined behaviour in C, and this year, some time on my hands due to paternity leave. So I spent a stretch of it finding easy bugs in mature C codebases — CPython, glibc, the Linux kernel. The method takes much less cleverness than the results suggest: build the project with sanitisers turned on, and run the test suite it already has. That really is all of it. No…

Find My said 'Nearby'. The iPad said nothing.

This one was, essentially, a one-shot AI solution, so let me lead with that. I told Claude Code: Find My says my iPad mini is in the house, I’ve pressed Play Sound, I can’t hear anything — can we do Bluetooth, make the MacBook beep hotter and colder as I move towards or away from it? It wrote 266 lines of Swift around CoreBluetooth. The first time macOS let the binary touch the radio, the first…

The heuristic that lied about the ceiling

The ITA Software hiring puzzles , preserved on the Internet Archive — Sling Blade Runner is among them. Sling Blade Runner asks: how long a chain of overlapping movie titles can you find? The end of one title has to overlap the start of the next — Sling Blade Blade Runner — and each title is used once. You get a list of 6561 titles and a note that heuristic answers are fine, “a reasonable tradeoff…

Exact running quantiles in linear expected time, if the input is shuffled

Everyone who runs a service has the dashboard: p50, p95, p99 latency. Almost everyone computes those percentiles with a sketch — t-digest, DDSketch, Greenwald–Khanna, KLL — trading exactness for tiny memory. This post is about refusing that trade. You want the exact 95th percentile of a stream, recomputed after every element, in the comparison model. And you know one helpful thing: the elements…

The shy heap: priority queues in linear time, if you promise not to peek

Comparison-based priority queues cost logarithmic time per operation, and that is not an engineering shortfall, it is a theorem. Feed n items into any exact heap and pop them all: the pops come out sorted, so the operations together must pay the Ω(n log n) that comparison sorting costs. If you want to go faster, you must give something up. The famous way to do that is Chazelle’s soft heap , which…

What the borrow checker won't review

A recurring theme on this blog is handing your code to a compiler and letting it find the bug. I still believe in that. But I spent last week on bcachefs (swap files on a copy-on-write filesystem, and the hardening that keeps them from deadlocking) and I want to be honest about where “let the compiler review it” runs out. It’s a live question for the project, not a rhetorical one. bcachefs is in…

How a frozen `ls` turned into swap on bcachefs

I’ve run bcachefs as my desktop root filesystem for a couple of years now. Five devices (one NVMe as an SSD tier, four spinning disks as the cold tier) with data written to the fast tier and quietly migrated to the HDDs with compression in the background. It is a genuinely nice setup to live on: you get SSD latency for the working set and HDD capacity for everything else, and mostly you forget…

A solution in search of a problem

A few years ago I was CTO of Mozak, and we built a RISC-V zkVM: write Rust (or anything that compiles to RISC-V), run it, get a zero-knowledge proof that it ran correctly. The company is dormant now, and some of our best design ideas were never written up. This post starts paying down that debt with the one I had the most trouble explaining while it mattered: how independent programs coordinate.…

The two-time pad wanted a 5-gram, not a neural net

The original puzzle, preserved on the Internet Archive: Decrypting the Two-Time Pad — scroll down past the other puzzles to find it. ITA ran a whole collection of these hiring puzzles ; the archive page above holds the retired ones. There is an old ITA Software hiring puzzle from around 2004: you intercept two messages, both encrypted with a one-time pad over a 46-character alphabet (space, A–Z ,…

A proof that 0 = 1, in a real zk-VM

A zero-knowledge VM makes one promise to a verifier: I ran the program whose hash is H, on this input, and got this output, and here is a proof you can check without re-running anything. The whole edifice rests on it being computationally infeasible to find a different program with the same hash. In December 2022 I built a Miden Assembly program that outputs a stack of zeros, together with a valid…

The mode checker reviewed my code

My property-testing engine for base_quickcheck had a global. I knew it was there. It was the convenient kind of global: a single Tape.t option ref that the random-state shim consulted on every draw, so the engine could install a recording tape without threading it through any signatures. It worked, all my tests passed, and I had already written the comment apologising for it. Then I wanted…

Your generators already know how to shrink

Here is a line from base_quickcheck that surprised me: (* shrinker.ml *) let int = atomic atomic means “never produce any shrink candidate”. The same goes for int32 , int64 , float , char , and bool . When your property fails on 766135 , base_quickcheck reports 766135 . Only structure shrinks: lists drop elements, but the elements themselves stay whatever they were. I do not think this is a bug. I…