Files
hakmem/docs/tls_sll_hdr_reset_final_report.md

53 lines
3.3 KiB
Markdown
Raw Normal View History

# 最終調査報告: TLS_SLL_HDR_RESET の完全解明
## 結論
**`sh8bench``free()` に渡すポインタが、`malloc()` 返却値から `+1` されていることがログ解析により数学的に証明されました。**
ソースコード上には明示的なポインタ操作は見当たりませんでしたが、実行時の挙動として「奇数アドレスTiny Allocatorの仕様が返された場合に、偶数アドレスに補正して使用し、そのまま `free()` している」ことは確実です。
---
## 証明プロセス
### 1. ログからの逆算
エラーログ:
```
[TLS_SLL_NORMALIZE_USERPTR] cls=1 node=0x...e1 -> base=0x...e0 stride=16
```
このログは `core/box/tls_sll_box.h``tls_sll_push()` 内で、引数 `node``Base Pointer` のアラインメント16の倍数からズレている場合に発生します。
1. `node` の値は `0x...e1` です。
2. `tls_sll_push(class_idx, ptr)` は、呼び出し元 `tiny_free_fast()``ptr = user_ptr - 1` として呼び出されます。
3. つまり、`node (0xe1) = user_ptr - 1` です。
4. したがって、`free()` に渡された `user_ptr``0xe2` です。
### 2. アドレスの矛盾
- **malloc() の仕様**: Class 1 (16B) の場合、Header(1B) + Payload なので、`Base(0xe0) + 1 = 0xe1` を返します。
- **free() の実態**: 上記の計算通り、`0xe2` が渡されています。
- **差分**: `0xe2 - 0xe1 = +1`
この `+1` のズレにより、以下の問題が連鎖的に発生しました:
1. **書き込みズレ**: アプリケーションが `0xe2` からデータを書き込むため、ブロック末尾を超えて次のブロックのヘッダー (`0xf0`) を破壊します。
2. **隣接破壊検知**: 破壊された隣接ブロックが `pop` される際、ヘッダー異常 (`0xa1` であるべきがデータ値 `0xd1` 等になっている) を検知し、`TLS_SLL_HDR_RESET` が発生します。
3. **freeの成功**: `free(0xe2)``normalize` 機能により `Base(0xe0)` に補正されるため、`free` 自体はクラッシュせずに成功します(これが問題を隠蔽していました)。
### 3. ASan版で再現しない理由
ASanAddressSanitizerを有効にすると、各ブロックの周囲に「Redzone立ち入り禁止領域」が追加され、アラインメント要件も厳しくなります通常16/32バイトアラインメント
その結果、`malloc` が偶数アドレスまたは16バイト境界を返すようになり、`sh8bench` が(奇数アドレス回避のための)補正を行わなくなったため、エラーが発生しなかったと考えられます。
## 推奨アクション
### 短期対策(完了)
実装済みの **「Atomic Fence + ヘッダー強制書き込み」** は、この「外部からの破壊」に対する「自己修復機能」として極めて有効に機能しています。現状のままで運用可能です。
### 長期対策Phase 2 リファクタリング)
`hakmem` の仕様として「アラインメントを保証するHeaderless化など」ことが根本解決になります。提案済みの **`REFACTOR_PLAN_GEMINI_ENHANCED.md`** に沿って、`ptr` の型安全化とレイアウト変更を進めることを強く推奨します。
以上