Skip to content

fix(library): endian/crc の2件の潜在バグ修正 (size_t アンダーフロー / CRC-32 テーブル未初期化)#485

Closed
sksat (sksat) wants to merge 2 commits into
mainfrom
fix/library-endian-crc-underflow
Closed

fix(library): endian/crc の2件の潜在バグ修正 (size_t アンダーフロー / CRC-32 テーブル未初期化)#485
sksat (sksat) wants to merge 2 commits into
mainfrom
fix/library-endian-crc-underflow

Conversation

@sksat

Copy link
Copy Markdown
Member

概要

c2a-core 全体のバグ調査の中で、library/ の葉関数に再現可能な潜在バグを2件発見したので修正する。どちらも 1 行修正。実ソースを直接コンパイルした再現コードで「壊れる→直る」を確認済み。

1. endian.c ENDIAN_conv: size==0 で size_t アンダーフロー → 範囲外書き込み

if (size < 0) return;   // size_t は符号なしなので常に false(死にコード)
size--;                 // size==0 のとき SIZE_MAX に折り返す
for (i = 0; i <= size; i++) ...   // 巨大ループ + 範囲外書き込み

空入力ガードのつもりの size < 0 が符号なし型で常に false。size==0 を渡すと size--SIZE_MAX になり、反転ループが範囲外へ書き込む。ENDIAN_memcpy の実体であり「エンディアン考慮版 memcpy」と銘打たれているのに、memcpy(dst,src,0) なら no-op で済む入力でクラッシュする。

  • 影響: IS_LITTLE_ENDIAN 定義時(SILS/テストビルド)に ENDIAN_memcpy → ENDIAN_conv 経由で発火。現行のコア内呼び出し元は固定の非ゼロサイズのみだが、可変長を渡す将来の呼び出しで 0 になると即死する地雷。
  • 修正: if (size < 0)if (size == 0)

2. crc.c CRC_make_crc_32_table: オフバイワンで table[255] 未初期化

for (i = 0; i < 255; ++i)   // 8bit版・16bit版はどちらも i < 256

8bit/16bit 版は i < 256 なのに 32bit 版だけ 255 で、table[255] が未初期化のまま残る(crc.h のコメントも「sizeof(table) = 256」と明記)。

  • 影響: 現在 CRC_make_crc_32_table の呼び出し元はゼロのため実害は出ていないが、将来 CRC-32 を使い始めると 0xFF で終わるバイトの CRC が壊れる。
  • 修正: i < 255i < 256。修正後 table[255] は標準 CRC-32 の正規値 0x2d02ef8d になることを確認。

検証

実ソース(library/endian.c / library/crc.c)をそのままコンパイルした再現プログラムで確認:

  • endian: 修正前は ENDIAN_conv(dst,src,0)SIGSEGV → 修正後は no-op で正常リターン(size=4 のバイト反転は維持)
  • crc: 修正前は table[255] が未初期化のまま → 修正後は未初期化 0 件、table[255] = 0x2d02ef8d

備考

  • これらは library/ の葉関数(依存ほぼ無し)なので、本来は unit test を付けたいが、C コードの unit test 実行基盤は test: add DriverSuper unit tests #473 で導入予定。本PRは 2 行修正のみとし、リグレッションテストは test: add DriverSuper unit tests #473 マージ後に同じ cargo↔ctest 基盤の上へ追加する。

🤖 Generated with Claude Code

sksat (sksat) and others added 2 commits June 10, 2026 19:56
The 32-bit table generator looped `for (i = 0; i < 255; ++i)`, leaving
table[255] uninitialized, while the 8-bit and 16-bit variants correctly
loop to 256. crc.h documents the table as 256 entries. Any CRC-32 over a
byte ending in 0xff would have used a garbage table entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The empty-input guard was `if (size < 0)`, which is always false for the
unsigned size_t parameter. With size==0, the subsequent `size--` wraps to
SIZE_MAX and the reversal loop writes far out of bounds (observed SIGSEGV
on little-endian builds where ENDIAN_memcpy delegates to ENDIAN_conv).
Guard the empty case explicitly so it behaves like memcpy(dst, src, 0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 10, 2026 10:56

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/ 内の葉関数で見つかった再現可能な潜在バグ 2 件(size_t アンダーフローによる範囲外書き込み、および CRC-32 テーブルの未初期化要素)を、いずれも 1 行修正で是正するPRです。

Changes:

  • ENDIAN_convsize == 0 のガードを追加し、size-- による size_t アンダーフローと範囲外書き込みを防止
  • CRC_make_crc_32_table のループ条件を i < 256 に修正し、table[255] の未初期化を解消

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
library/endian.c size == 0 を早期 return してアンダーフローと OOB 書き込みを防止
library/crc.c CRC-32 テーブル生成の off-by-one を修正して 256 要素すべて初期化

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

@sksat

Copy link
Copy Markdown
Member Author

crc / endian の修正を個別PRに分割しました: #486 (crc), #487 (endian)。本PRはクローズします。

@sksat sksat (sksat) deleted the fix/library-endian-crc-underflow branch June 10, 2026 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants