Skip to content

fix(endian): ENDIAN_conv が size==0 で size_t アンダーフローし範囲外書き込み#487

Open
sksat (sksat) wants to merge 1 commit into
mainfrom
fix/endian-conv-size-underflow
Open

fix(endian): ENDIAN_conv が size==0 で size_t アンダーフローし範囲外書き込み#487
sksat (sksat) wants to merge 1 commit into
mainfrom
fix/endian-conv-size-underflow

Conversation

@sksat

@sksat sksat (sksat) commented Jun 10, 2026

Copy link
Copy Markdown
Member

概要

ENDIAN_conv(after, before, size)size == 0size_t アンダーフローを起こし、範囲外書き込みでクラッシュする。

if (size < 0) return;   // (a) size_t は符号なし → 常に false の死にコード
size--;                 // (b) size==0 で SIZE_MAX に折り返す
for (i = 0; i <= size; i++) *(aft + (size - i)) = *(bef + i);  // 範囲外書き込み

ENDIAN_convENDIAN_memcpyIS_LITTLE_ENDIAN 時の実体)が委譲する先。「エンディアン考慮版 memcpy」を謳うのに、memcpy(dst,src,0) なら no-op で済む入力でクラッシュする。

修正

size-- をやめ、アンダーフローしないループに書き換える(ガード追加ではなく失敗モードを構造的に除去)。

for (i = 0; i < size; i++) aft[size - 1 - i] = bef[i];
  • size==0 → ループが回らず no-op
  • size>0 → 従来と同じバイト反転(ビット単位で等価)
  • size-- 不在でアンダーフロー不可能、死にコード if (size < 0) も除去

size==0 を no-op にした理由

  • memcpy 準拠: memcpy(_,_,0) は well-defined な no-op。memcpy にエラー概念は無く、memcpy 互換を謳う以上 no-op が契約通り(エラー化すると互換から外れる)。
  • エラーを足さない: 葉プリミティブは引数だけでは NULL/長さ超過を検知できず、戻り値を増やしても危険ケースは捕まらない。「0 が来てはいけない」かは呼び出し側の関心事(現状 0 を渡す呼び出し元も ENDIAN_conv の直接呼び出し元も無い)。
  • 慣習: core は assert() を使わず葉関数は benign 値を返す(例: ascii2hex は不正文字に 0x00)。
  • 意図が消えないよう no-op の旨をコードコメントにも明記。

影響 / 検証

  • 発火は IS_LITTLE_ENDIAN(SILS/テスト)ビルドのみ。実機(big-endian)は ENDIAN_memcpy→memcpy で無関係。現状の呼び出し元は固定非ゼロサイズだが、可変長で 0 が来ると即死する地雷。
  • 再現: 実 library/endian.c をコンパイルした再現プログラムで、修正前 ENDIAN_conv(dst,src,0)SIGSEGV、修正後 → no-op(size=4 の反転は維持)、ASan+UBSan 警告なし

備考

library/ 葉関数の unit test 基盤は #473 で導入予定。本PRは実装修正のみ、リグレッションテストは #473 マージ後に同基盤上へ追加する。

🤖 Generated with Claude Code

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

library/endian.cENDIAN_conv における size_t の不正な空入力ガード(if (size < 0) が常に false)を修正し、size==0 時の size-- によるアンダーフローから発生する範囲外書き込み/クラッシュを防ぐPRです。ENDIAN_memcpy(little-endian ビルドで ENDIAN_conv を呼ぶ)経由でも、memcpy(..., 0) 相当の no-op を安全に扱えるようになります。

Changes:

  • ENDIAN_conv のガード条件を if (size == 0) return; に修正し、size==0 のアンダーフローを防止

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

The empty-input guard was `if (size < 0)`, which is always false for the
unsigned size_t parameter (dead code), and the following `size--` wrapped
to SIZE_MAX when size==0, making the reversal loop write far out of bounds
(observed SIGSEGV on little-endian builds where ENDIAN_memcpy delegates to
ENDIAN_conv).

Rewrite the loop as `for (i = 0; i < size; i++) aft[size-1-i] = bef[i];` so
that size==0 is a natural no-op and the size_t underflow is impossible by
construction. no-op on zero length matches memcpy(dst, src, 0) semantics,
which is the contract ENDIAN_memcpy advertises.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sksat sksat (sksat) force-pushed the fix/endian-conv-size-underflow branch from bc5c104 to b3b9453 Compare June 10, 2026 11:32
@sksat sksat (sksat) self-assigned this Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants