2026-07-12

週次オープンソース:ゲストカーネルのない Linux サンドボックスと、ゼロから書いたバーコードライブラリ

コミット数で見ると、今週も重い週だった。3,000 コミットを少し超えた。新しいプロジェクトが二つ始まった。 nixvm は Linux カーネルを起動せずに本物の Linux ユーザランドを 動かすサンドボックス、anydcode はゼロから書いたバーコード ライブラリだ。これまでの大きなエンジン三つも動き続けた。z3rs は一週間かけて本物の Z3 と自分を突き合わせ、graphitesql は 最初の 0.1 リリースをタグ付けし、kataan は Temporal API を 丸ごと実装した。

nixvm:Linux カーネルなしで Linux システムコールを

nixvm は「ハードウェア ではなく Linux システムコールを直接エミュレートすることで、本物の Linux ユーザランドを動かすポータブルな VM 風サンドボックス」だ。 gVisor 型のやり方を取り、ゲストカーネルが存在しない。素の Alpine ユーザランドは、ホスト CPU 上かソフトウェアインタプリタ上で 動く。ゲストのプロセスが syscall や svc を実行すると、制御は トラップして nixvm 自身の Rust 製カーネルに移る。ファイル、メモリ、 プロセス、スレッド、シグナル、ネットワークは、すべてこのカーネルが ユーザ空間で扱う。狙いは npm install、pip install、信頼できない ビルドスクリプトといった危うい作業を隔離して動かすことで、 ハードウェア仮想化はあってもなくてもよい。

リポジトリは金曜に作られ、日曜までに 188 コミットに達した。 おおよそ次の順で組み上がった:

  • CPU インタプリタ。 aarch64 インタプリタは「hello world」 から始まり、本物の busybox が動くところまで ISA を広げた。NEON、 スカラ/ベクタの浮動小数点、LSE アトミック、CRC32、AES/SHA 命令。 続いて x86-64 インタプリタが、SSE/SSE2、x87 のサブセット、 CPUID/RDRAND、LOCK アトミックとともに加わった。
  • ローダ。 静的 ELF、次に static-PIE、そして 動的リンク。 本物の ld-musl が素の Alpine のバイナリを起動する。
  • カーネル。 スケジューラ付きの fork/exec/wait4(これで パイプラインが動く)、本物の futex を持つアドレス空間共有の スレッド、vCPU ホストスレッドの SMP プール、 poll/epoll/eventfd/timerfd、シグナル、ファイルバックと コピーオンライトのメモリ、そして仮想ネットワークスタック。 AF_UNIX、TCP/UDP ループバック、netlink のスタブ、最後に ホストへの外向き通信 が入り、apk update && apk add が本物の インターネット越しに動く。
  • ファイルシステム。 tmpfs、コピーオンライトのオーバーレイ、 fstool による読み取り専用 squashfs のルート、合成した /dev・ /proc・/sys、ホストのディレクトリを通す「穴」。穴は、ゲストの シンボリックリンクがマウントルートの外へ出られないよう固めてある。
  • ハードウェアバックエンド。 macOS の Hypervisor.framework (EL0 で実行し、svc でトラップ)と、x86-64 ゲスト向けの KVM。KVM ではフルの Alpine ユーザランドが起動する。 インタプリタは引き続きフォールバックとして残る。

インタプリタもカーネルもポータブルな Rust なので、全体は WebAssembly にもコンパイルできる。GitHub Pages 上の Vue + xterm の ページが、どちらのアーキテクチャでも Alpine をブラウザ内で起動する。 ルートファイルシステムはメモリ上の squashfs から読み込む。rootfs の tarball はプロセス内で compcol を使って展開しており、ここでもまた 同じ no-C スタックだ。Node.js は共有ライブラリのグラフ全体を 読み込むが、イベントループがまだ futex/epoll でビジースピンする ことがコミットに記録されている。

anydcode:50 以上のバーコード方式、往復で厳密

anydcode(クレート名 anyd)は「1D と 2D のバーコードを復号・符号化する、ゼロから 書いた Rust ライブラリ」だ。設計目標は ロスレスな往復。復号した シンボルはペイロード と 符号化時のすべての決定(セグメント分割、 バージョン、EC レベル、マスク)を保持し、そのまま符号化し直すと 元のシンボルがバイト単位で再現される。検出は、軽いフレームごとの パス(位置特定と分類)と重い復号パスに分かれていて、ライブ映像に 向く。

土曜に作られ、一気にカタログを進めて、週末には モデル化した すべての方式が実装済み になった:

  • 2D マトリクス: QR、Micro QR、rMQR、Data Matrix、Aztec と Aztec Runes、MaxiCode、Han Xin、DotCode、Grid Matrix、そして Apple App Clip Code。
  • スタック型: PDF417、MicroPDF417、Code 16K、Code 49、 Codablock F、GS1 DataBar のスタック型各種。
  • リニアと郵便: Code 128 / GS1-128、アドオン付き EAN/UPC、 Code 39/93/11、ITF と 2-of-5、Codabar、MSI、Telepen、 Pharmacode、DataBar、POSTNET/PLANET/IMb、RM4SCC/KIX、 Australia Post、日本郵便、Mailmark、DX フィルムエッジ。

続いて実際の写真に取り組んだ。QR のサンプラには、適応的な 二値化、曲面向けの thin-plate-spline による歪み補正(曲がってぼけた ボトルの写真がいまは回帰テスト用のフィクスチャになっている)、 タイミングパターンを基準にしたモジュール単位のサンプリングが 入った。EAN/UPC は、実際のカメラ画像向けにエッジ幅による復号へ 移った。wasm-bindgen を使わずに作った WASM デモは、51 方式すべてを 生成し、画像を復号し、Web Worker でターゲットを追跡しながら ライブカメラからスキャンする。v0.1.1 として出荷された。

z3rs:Z3 と自分を突き合わせる

先週の Pure-Rust 版 Z3 移植である z3rs は、今週最多の 426 コミットだった。その大半は本物との差を埋める作業だ。週の 始めに PARITY.md v2 と、Z3 自身の回帰テストコーパスに対する 差分ハーネス が入った。その後の作業のほとんどは、このハーネスと 差分ファジングが見つけたものへの対応だ:

  • 文字列とシーケンス(QF_S) には約 100 コミット。単語方程式を 反駁する Nielsen 変換、str.contains の正規表現による反駁、Z3 の seq_rewriter の replace 規則の移植、そして prefixof・ str.at・str.indexof・連結の分割を結びつける小さな公理が多数。
  • 量化子: 整数の ∀x∃y に対する完全な Presburger 量化子消去 (Cooper)、線形実数の入れ子 QE、幅の狭いビットベクタの有限領域 展開。
  • 算術、配列、データ型: QF_LIA の dark-shadow ウィットネス、 本物のモデルを伴う非線形整数ウィットネス、配列の外延性と (_ map f) の等式、列挙型の鳩の巣による反駁、再帰的 CHC の 両方向の判定。
  • 健全性。 約 45 コミットが、不健全な答えや誤った答えを直す。 データ型の非巡回性、0^0 の畳み込み、unknown ゲートをすり抜ける FP マーカー、CHC エンジンの誤った unsat。差分スイープでしか 見つからない種類のバグだ。

出力形式は z3 と一致するようになり(ビットベクタの数値表記、 モデルの体裁、unsat コア、get-objectives の MaxSAT ペナルティ)、 v0.0.6 から v0.0.8 まで三つのリリースが出た。

graphitesql:v0.1.0 と C ABI

Pure-Rust の SQLite である graphitesql は 341 コミットで v0.1.0 をタグ付けした。いちばん変わったのは カバー範囲の広さだ:

  • graphitesql-capi:libsqlite3 互換の C ABI を持つ兄弟 クレート。sqlite3_create_function、ウィンドウ関数、update・ commit・rollback の各フック、sqlite3_error_offset を含む。 既存の C の呼び出し側がこれにリンクできる。
  • sqlite3_session の changeset:生成、反転、連結、そして カスタムの競合ハンドラ付きの適用。
  • FTS5:外部コンテンツテーブル、メンテナンスコマンド、 プレフィクスインデックス、トゥームストーンセグメントによる インクリメンタルな削除・更新。
  • 並行性。 複数接続の WAL リーダ向けに共有の wal-index、 トランザクションの最初の読み取りで取る読み取りロック。
  • プランナと VDBE。 相関サブクエリ、集約を伴う結合、 インデックスによるソートの省略が、バイトコードエンジン上で 動くようになった。
  • 厳密さの修正も長く続いた。テキスト値はバイト列として保持される ようになり、UTF-8 でないテキストも SQLite と同じように往復する。 シェルには .mode、.import、.show と、SQLite 風のエラー キャレットが加わった。

kataan:Temporal と汎用 JIT 層

argus ブラウザ用の JavaScript エンジンである kataan は、test262 を 一件ずつ潰す段階から先へ進んだ。今週 Temporal の骨組みを作り、 そのまま全体を実装した。七つの plain 型、タイムゾーンデータ付きの ZonedDateTime、ISO 以外の暦と暦を意識した算術、Duration の 丸め。その一連の作業の終わりに、built-ins/Temporal の失敗 0 を報告するコミットがある。Intl は Pure-Rust の ICU 相当である intlrs の CLDR データに 付け替えられ、Temporal は DateTimeFormat で書式化できるように なった。

ほかの作業:ShadowRealm の分離、Iterator.zip、import 属性と JSON モジュール、仮想時計上の Atomics wait/waitAsync、タイマー付きの イベントループ、node 風の Buffer・path・process。JIT では NaN-boxing の汎用層に、制御フロー、プロパティと要素のインライン 高速パス、JIT→JIT の直接呼び出しが入った。

今週その他

  • oxideav-av1 は エンコーダになった。適合レベルのキーフレームエンコーダに続き、 1/4 画素の動き、矩形パーティション、切り替え可能な補間フィルタ、 二参照の複合予測を備えた P フレームのインター符号化が入った。 自前で符号化したストリームが適合コーパスに加わった(39 → 50)。
  • puregit は ロードマップを完了した。HTTP 越しのプロトコル v2、shallow clone と partial clone、到達可能性ビットマップ、ssh-agent 認証、SSH と OpenPGP によるコミット署名とその検証、libgit2 風の C ABI。
  • puremp には、一般 数体篩、SEA による点の数え上げ、ECPP による素数証明、類群を伴う 代数体が加わった。
  • latticefoundry に RISC-V RV64IM ターゲットが加わった。C フロントエンドの lf-cc は いまや GNU gzip(出力はバイト単位で同一)、bzip2、make、bash を コンパイルする。
  • purecrypto は 性能改善に取り組んだ。ML-KEM・ML-DSA・SLH-DSA が共有する 4-way AVX2 の Keccak カーネル、AES-GCM のステッチ実装、P-256 と edwards25519 の comb テーブル。
  • libwallet は Rust への移植を続けた。稼働中の Spot リレー越しのデバイス間 鍵生成、RemoteKey のシェア、旧来の TSS 署名。
  • oxideav-ifc は ジオメトリのフェーズ 3(ブーリアン演算による切り抜き、 スイープソリッド、CSG)を進め、意味データ層に取りかかった。 プロパティセット、材料、単位、ジオリファレンス。
  • teamclaude には、 モデルごとのルーティングと、アカウント切り替え時に サンダリングハードを避けるストーム制御が加わった。

来週

nixvm は Alpine の起動から、実際の作業負荷を動かす段階へ進む。 まずは Node のイベントループからだ。anydcode は実際のカメラ入力での 復号をさらに進める。z3rs は差分スイープを続け、graphitesql は 0.1 の 上に積み上げていく。