Show HN: Tiny VM sandbox in C with apps in Rust, C and Zig

2025/12/13 7:02

Show HN: Tiny VM sandbox in C with apps in Rust, C and Zig

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

uvm32 は、単一の C ファイルで書かれたミニマリストで依存関係を持たない仮想マシンサンドボックスです。
STM32L0 のような非常に小型のマイクロコントローラ上で動作し、4 KB 未満のフラッシュと 1 KB の RAM を使用します。静的割り当てのみで非同期設計となっています。

この VM は RISC‑V のサブセットを実装しており、軽量な管理インタフェースを公開しています。「if‑this‑then‑that」ロジックのために Lua、Duktape、MicroPython などの軽量スクリプトエンジンを置き換え、信頼できないコンポーネントや不安定な部品をサンドボックス化し、ターゲットコンパイラなしでモダン言語の「一度書けばどこでも実行できる」スクリプトを書けるようにすることが目的です。

主な特徴:

  • バイトコードアプリは C、Zig、Rust、またはアセンブリで記述可能。
  • 非ブロッキングでシンプルな実行モデル。安全かつ最小限の型付けを備えた FFI を使用し、ホスト IO(stdio/ネットワーク)は想定していません。
  • デザインは高速よりも安全性を優先しています。
  • すべてのソースコードは
    uvm32/
    ディレクトリにあります。最小限のホスト例は
    host‑mini
    にあり、より高度なホストは
    host/
    host-parallel
    host-arduino
    にあります。

サンプルアプリケーションは VM の機能を示しています(C: helloworld, heap, conio, lissajous, maze, fib, sketch; Zig: zig‑mandel, zigtris, zigalloc, zigdoom; Rust: rust‑hello; アセンブリ: hello‑asm)。

ビルドとテスト用の Dockerfile が提供されており、

make dockerbuild
make dockershell
で構築・起動し、その後
make
を実行してサンプルをコンパイル・実行します。ドキュメントはヘッダファイル
uvm32/uvm32.h
doc/README.md
にあります。本プロジェクトは MIT ライセンスで公開されています。

本文

uvm32(ユーヴィーエムサンティ)

uvm32
は、マイクロコントローラやリソースが限られたデバイス向けに設計された、最小構成・依存関係のない仮想マシンサンドボックスです。
単一の C ファイルで構成され、動的メモリアロケーションは行わず、非同期設計を採用し、純粋な C99 で実装されています。
STM32L0(ARM Cortex‑M0+)上では、必要となるフットプリントは 4 KB 以下のフラッシュ / 1 KB の RAM に収まります。

uvm32
は管理インタフェースを備えた RISC‑V エミュレータで、内部で効率的に動作するコードをビルドできるツール一式が同梱されています。


何のためにあるか?

  • Lua・Duktape・MicroPython 等の埋め込みスクリプトエンジンのシンプルな代替として
  • 信頼性の低いコンポーネントを分離するサンドボックスとして
  • ターゲット用コンパイラが無い場合でも、モダンなシステム言語(例:Rust)で開発できるように
  • 「一度書けばどこでも実行」―複数のソフトウェアバリアントを維持する手間を省く

主な機能

機能内容
バイトコード例アプリ(C・Zig・Rust・アセンブリ)さまざまな言語で書かれたサンプルが含まれる
非ブロッキング設計VM が不正に動作してもホストは停止しない
ホスト IO 能力の前提なし(
stdio
等を想定しない)
単純で意図が明確な実行モデル
安全かつ最小限の型付き FFI
「if this then that」程度のスクリプト/プラグインに十分なサイズそれ以上も可能
スピードより安全性を重視VM 内で悪質なコードがホストをクラッシュさせないようにする

uvm32
はハードウェアシミュレーションではなく、カスタムスクリプトロジックを実行する CPU エミュレータです。


代替との比較

目的uvm32
小さいフットプリント(組み込み機器・ゲーム・アプリ)✔︎
VM コード用に知られた言語と品質の高い開発ツール✔︎
既存ソフトウェアへの統合容易性✔︎
イベント駆動・ポーリング・マルチプロセッサ等、多様なパラダイム✔︎
VM コードが不正に動作しても耐久性✔︎

uvm32 が目指さないこと

  • 直接的な FFI(ホスト–VM 間の関数呼び出し)を簡素化すること
  • 最大限の効率化
  • スクリプト経験がほとんど無い人向けのサポート(開発・コンパイル・実行は手動で行う)
  • 「バッテリー付き」ライブラリ(
    stdio
    、ネットワーク等)は提供しない

リポジトリ構成

全てのコードは

uvm32
ディレクトリにあります。
単一の実行ファイルを動かす最小ホストは
host‑mini
に置かれています。
他のホストやサンプルアプリはそれぞれ別フォルダに入っています。

例 – シンプル VM ホスト(
host‑mini

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "uvm32.h"
#include "uvm32_common_custom.h"

uint8_t rom[] = { /* mandel.bin */ 0x23, 0x26, 0x11, 0x00, 0xef, 0x00, 0c0, 0x00,
                  0xb7, 0x08, 0x00, 0x01 /* … */ };

int main(int argc, char *argv[]) {
    uvm32_state_t   vmst;
    uvm32_evt_t     evt;
    bool            isrunning = true;

    uvm32_init(&vmst);
    uvm32_load(&vmst, rom, sizeof(rom));

    while (isrunning) {
        uvm32_run(&vmst, &evt, 100);   /* VM が動作しているとみなす周期数 */

        switch (evt.typ) {
            case UVM32_EVT_END:
                isrunning = false;
                break;

            case UVM32_EVT_SYSCALL:          /* VM がシステムコールを呼んだ */
                switch (evt.data.syscall.code) {
                    case UVM32_SYSCALL_PUTC:
                        printf("%c", uvm32_arg_getval(&vmst, &evt, ARG0));
                        break;

                    case UVM32_SYSCALL_PRINTLN:
                        const char *str = uvm32_arg_getcstr(&vmst,
                                                          &evt, ARG0);
                        printf("%s\n", str);
                        break;

                    case UVM32_SYSCALL_YIELD:
                        /* 何もしない */ 
                        break;

                    default:
                        printf("Unhandled syscall 0x%08x\n",
                               evt.data.syscall.code);
                }
                break;

            case UVM32_EVT_ERR:
                printf("UVM32_EVT_ERR '%s' (%d)\n",
                       evt.data.err.errstr, (int)evt.data.err.errcode);
                break;

            default:
                break;
        }
    }

    return 0;
}

サンプルアプリ

カテゴリ
C
apps/helloworld
apps/heap
apps/conio
apps/lissajous
apps/maze
apps/fib
apps/sketch
Rust
apps/rust-hello
(公式 Rust インストーラを使用し、Homebrew ではない)
Zig
apps/zig-mandel
apps/zigtris
apps/zigalloc
apps/zigdoom
アセンブリ
apps/hello-asm

VM ホスト

  • host
    – バイナリをロードして完了まで実行し、複数のシステムコールに対応
  • host‑mini
    – 上記の最小ホスト(バイトコードは組み込み済み)
  • host-parallel
    – 複数 VM を同時に走らせる並列ホスト
  • host-arduino
    – QEMU で AVR コードをテストする Arduino スケッチ

クイックスタート(Docker)

make dockerbuild
make dockershell

シェル内で

make
./hosts/host/host apps/helloworld/helloworld.bin

host -h
でオプション一覧を確認してください。


さらに詳しく

  • ヘッダーファイル:
    uvm32/uvm32.h
  • テスト・ドキュメント:
    doc/README.md

ライセンス

本プロジェクトは MIT ライセンスの下で配布されています。研究・製品・組み込みデバイスに自由にご利用ください。

同じ日のほかのニュース

一覧に戻る →

2025/12/13 5:57

GNU Unifont

2025/12/13 5:15

Rats Play DOOM

## Japanese Translation: > **概要:** > 著者らは、ラットがDOOMをプレイできる完全にオープンソースの仮想現実装置をリリースしました。ゼロから構築されたこのシステムには、ハードウェア設計・ファームウェア・ソフトウェアがGitHubに掲載されており、他研究室でも簡単に再現または改良できます。バージョン 1(v1)はニューヨークのヴィクトール・トー氏によって開発され、ラットにDOOMコリドーを走行させるよう訓練しました。この実装はViceとPC Gamerで紹介されました。 > > 改良版(v2)はよりモジュラー化され、180°×80°の視野を持つ折りたたみ可能なAMOLEDスクリーン、新しいボールドライバー、強化された給餌器、ゲームイベントに同期した正確な10 µLの砂糖水投与が可能な改良リワード回路を備えています。追加センサーとランニングマシンのボール周囲に設置された光学フロー運動捕捉システムでトラッキング精度が向上しています。 > > ソフトウェアはPythonベースのモジュラースタック(arena_scenario.py)で、PC上で実行され、Raspberry PiとTCP経由で通信します。Piはリアルタイムセンサー読み取り・ボール駆動・リワード制御を担当します。すべてのコンポーネントはGitHubに文書化されており、3Dプリント可能なパーツや回路図も公開されています。 > > チーム(ヴィクトール・トー=ゲーマーラットコーチ、サンドル・マクラ=電気技師、アコス・ブラシュェク=ドキュメントリード)は、ラットが約2週間で慣れることを示しましたが、完全な訓練はまだ完了していません。 > > 現在の制限として、自動キャリブレーションスイートが無いため、ユーザーはセンサーの整列とリワードタイミングを手動で検証する必要があります。 > > 今後の課題は完全な訓練プロトコルの完成、キャリブレーションツールの改良、および他の行動タスクや種へ装置を拡張することです。低コストで完全にオープンなプラットフォームを提供することで、このプロジェクトは世界中の神経科学研究室の参入障壁を下げ、動物VR実験に依存する研究のスピードアップに寄与できる可能性があります。

2025/12/13 5:28

Security issues with electronic invoices

## Japanese Translation: --- ## 改訂要約 EUのe‑インボイス指令 (2014/55/EU) は、加盟国に電子請求書用の標準化されたXMLフォーマットを採用することを義務付けています。 この指令は越境取引の請求処理を円滑にするために設計されていますが、原生XMLとXSLT 2.0への依存が実際のセキュリティ問題を招いています:XML には「XML External Entity」(XXE)という欠陥があり、外部エンティティが無効化されていない場合、攻撃者は任意のファイルを読み取ることができます。e‑インボイスで使用されるライブラリ(Java のデフォルトパーサーと EN16931 バリデーションに必要な唯一の無料 XSLT 2.0 エンジンである Saxon)は、これらのデフォルト設定を有効にしたまま配布されており、脆弱性があります。 EU が公開しているセキュリティテストスイートは、**kivitendo**、**peppol‑py**、**ZUV** など実際の製品で XXE バグを検出しました。W3C の議論からは、XSLT 2.0 のサポートは広範な導入を想定していませんでしたが、それでも指令では EN16931 のバリデーションに XSLT 2.0 が必要とされています。 EN16931 のパート 1・2 は無料ですが、以降のパートは有料であり、CEN や国別機関(例:EVS)へのリンクが壊れているためアクセスが困難です。EU のテストスイートは <https://github.com/ebt‑eu/einvoice-security-tests> にホストされています。 既知の XXE 脆弱性は CVE‑2025‑66370(kivitendo)、CVE‑2025‑66371(peppol‑py)および CVE‑2025‑66372(Mustang < 2.16.3)として登録されています。現在、Mustang が推奨されますが、バージョン 2.16.3 以前も XXE 欠陥を抱えていました。 指令の複雑な要件がベンダーをこれらの脆弱なライブラリへと押し込むと、さらなる脆弱性が表面化する可能性があります。これは規制改定を招くか、市場をより安全な代替手段や新しい標準に向ける動きにつながります。結果として、データ漏洩リスクや請求書処理パイプラインのセキュリティ不備による罰金・評判損失といったリスクがユーザーと企業双方に及びます。簡単に言えば、現行の XML ベースのアプローチは EU e‑インボイスにおけるコンプライアンスとセキュリティの両面を脅かしています。