# 帳票設計書 12-HWASan Report

## 概要

本ドキュメントは、HardwareAddressSanitizer (HWASan) によるメモリエラー検出レポートの設計仕様を定義する。HWASanはハードウェア支援によるメモリ安全性検査ツールであり、ARM Memory Tagging Extension (MTE) やTop-Byte Ignore (TBI) 機能を活用してメモリエラーを効率的に検出する。

### 本帳票の処理概要

HWASan Reportは、プログラム実行時に検出されたメモリエラー（タグ不一致、無効な解放、テール上書き等）を詳細な診断情報とともに報告する帳票である。

**業務上の目的・背景**：メモリ安全性の問題（use-after-free、buffer overflow等）はセキュリティ脆弱性の主要な原因である。HWASanは従来のASanよりも低いオーバーヘッドでこれらの問題を検出でき、特にAndroidプラットフォームで広く活用されている。開発者がこれらの問題を早期に発見・修正することで、製品の安全性を向上させる。

**帳票の利用シーン**：HWASanを有効にしてビルドしたプログラム（特にAndroidアプリケーション）を実行した際、メモリエラーが検出されると自動的にレポートが生成される。開発・テスト環境でのデバッグ、CI/CDパイプラインでの品質検査に活用される。

**主要な出力内容**：
1. エラー種別（tag-mismatch、invalid-free、allocation-tail-overwritten）
2. アクセス種別（READ/WRITE）とアクセスサイズ
3. ポインタタグとメモリタグの不一致情報
4. アクセスを行ったスタックトレース
5. メモリアドレス周辺のタグダンプ（シャドウメモリ）
6. ヒープ割り当て/解放履歴（use-after-freeの場合）
7. スタック変数の候補（stack-buffer-overflowの場合）
8. CPUレジスタの値（クラッシュ時）

**帳票の出力タイミング**：HWASanが有効なプログラムの実行中にメモリエラーが検出された時点で出力。`halt_on_error`フラグによりプログラム終了または継続を制御可能。

**帳票の利用者**：Android/ARM向けアプリケーション開発者、セキュリティエンジニア、QAエンジニア

## 帳票種別

エラーレポート / セキュリティ診断レポート

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | コンソール/ターミナル | N/A | プログラム実行時に自動出力 |
| - | Android Logcat | N/A | Androidデバイスでの実行時 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（標準エラー出力） |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | N/A（標準エラー出力） |
| 出力方法 | コンソール出力 / Logcat / エラーレポートコールバック |
| 文字コード | システムロケール依存 |

### コンソール出力設定

| 項目 | 内容 |
|-----|------|
| カラー出力 | 有（ターミナル対応時） |
| エラーメッセージバッファ | 有（ScopedReportクラスで管理） |
| モジュールマップ出力 | 設定可能（`print_module_map`フラグ） |

## 帳票レイアウト

### レイアウト概要

HWASan Reportは検出されたエラーごとに以下の構成でテキスト出力される。

```
ERROR: HWAddressSanitizer: {エラー種別} on address {アドレス} at pc {PC}
{アクセス情報}

{スタックトレース}

Cause: {原因}
{アドレス詳細情報}

{割り当て/解放履歴（該当時）}

{タグダンプ}

{レジスタ情報（該当時）}

{ヘルプURL（Android時）}

SUMMARY: HWAddressSanitizer: {エラー種別}
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | エラーヘッダー | エラー種別とアドレス情報 | bug_type, untagged_addr, pc | `ERROR: HWAddressSanitizer: {type} on address {addr} at pc {pc}` |
| 2 | スレッドID | エラー発生スレッド | Thread::unique_id() | `on thread T{id}` |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 備考 |
|----|-------|------|-------------|---------|-----|
| 1 | アクセス種別 | READ/WRITE | is_store | `WRITE of size N` / `READ of size N` | - |
| 2 | タグ情報 | ポインタタグとメモリタグ | ptr_tag, mem_tag | `tags: XX/YY (ptr/mem)` | 16進数2桁 |
| 3 | ショートグラニュールタグ | 16バイト境界内のタグ | short_tag | `tags: XX/YY(ZZ) (ptr/mem)` | オプション |
| 4 | 原因 | エラーの原因分類 | 解析結果 | `Cause: {原因}` | - |
| 5 | 位置情報 | アドレスの詳細位置 | 解析結果 | ヒープ/グローバル/スタック情報 | - |
| 6 | 割り当てスタック | メモリ割り当て時のスタック | alloc_context_id | `allocated by thread TN here:` | ヒープ時 |
| 7 | 解放スタック | メモリ解放時のスタック | free_context_id | `freed by thread TN here:` | UAF時 |

### タグダンプ部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | タグダンプヘッダー | タグ情報の説明 | 固定 | `Memory tags around the buggy address...` |
| 2 | タグ行 | 16バイト×17行分のタグ | シャドウメモリ | `=>0x...: [XX] YY ZZ ...` |
| 3 | ショートグラニュールタグ | 短いグラニュールのタグ | メモリ末尾 | 3行分 |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | レジスタダンプ | CPUレジスタ値 | registers_frame | `x0  XXXXXXXX  x1  XXXXXXXX ...` |
| 2 | ヘルプURL | Androidドキュメントへのリンク | 固定（Android時） | URL文字列 |
| 3 | サマリー | エラーサマリー | bug_type | `SUMMARY: HWAddressSanitizer: {type}` |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| HWASan有効化 | `-fsanitize=hwaddress`オプションでビルド | Yes |
| ハードウェアサポート | ARM64プラットフォーム（TBI/MTE対応） | Yes |
| メモリエラー検出 | タグ不一致等が検出された | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | 検出順 | 検出された順序 |

### 改ページ条件

N/A（コンソール出力のため改ページなし）

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを使用せず、実行時のメモリ状態から情報を取得する。

| データソース | 用途 | 取得方法 |
|-------------|------|---------|
| シャドウメモリ | メモリタグ取得 | MemToShadow変換 |
| スタックアロケーションリングバッファ | スタック変数追跡 | Thread::stack_allocations() |
| ヒープアロケーションリングバッファ | ヒープ履歴追跡 | Thread::heap_allocations() |
| StackDepot | スタックトレース保存 | StackDepotGet() |
| Symbolizer | シンボル解決 | Symbolizer::GetOrInit() |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| mismatch_offset | `__hwasan_test_shadow()` | N/A | 不一致開始位置 |
| ptr_tag | `GetTagFromPointer(tagged_addr)` | N/A | ポインタ上位8ビット |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[メモリアクセス] --> B{タグ一致?}
    B -->|Yes| C[正常継続]
    B -->|No| D[エラー検出]
    D --> E[BaseReport構築]
    E --> F[HeapChunk取得]
    F --> G[Allocations取得]
    G --> H[OverflowCandidate検索]
    H --> I[Shadow Copy]
    I --> J[レポート出力]
    J --> K[PrintAddressDescription]
    K --> L[PrintTags]
    L --> M{fatal?}
    M -->|Yes| N[Die]
    M -->|No| O[継続]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| tag-mismatch | ポインタタグとメモリタグが不一致 | `ERROR: HWAddressSanitizer: tag-mismatch` | アクセス範囲の確認 |
| invalid-free | 無効なポインタの解放 | `ERROR: HWAddressSanitizer: invalid-free` | ダブルフリーの確認 |
| allocation-tail-overwritten | 割り当てサイズを超えた書き込み | `ERROR: HWAddressSanitizer: allocation-tail-overwritten` | バッファサイズの確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | エラー検出ごとに1レポート |
| 目標出力時間 | 数百ミリ秒（シンボル解決含む） |
| 同時出力数上限 | 1（error_message_lock_で排他制御） |

## セキュリティ考慮事項

- レポートにはメモリアドレス、タグ、レジスタ値が含まれる
- スタックトレースにはソースファイルパスが含まれる
- error_report_callback_を通じて外部にレポートを送信可能
- 本番環境では`halt_on_error`を有効にすることを推奨

## 備考

- HWASanはARM64アーキテクチャ専用（AArch64, RISC-V64）
- 16バイトのグラニュール単位でタグ付け
- ショートグラニュール（16バイト未満の割り当て）は特別な処理
- Android向けにヘルプURLを自動表示

---

## コードリーディングガイド

本帳票を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、レポート出力に使用されるデータ構造を把握することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | hwasan_report.h | `compiler-rt/lib/hwasan/hwasan_report.h` | 公開API（ReportTagMismatch, ReportInvalidFree, ReportTailOverwritten）を確認 |
| 1-2 | hwasan_report.cpp | `compiler-rt/lib/hwasan/hwasan_report.cpp` | BaseReportクラス（477-561行目）の構造を理解 |

**読解のコツ**:
- `ScopedReport`クラス（40-86行目）がレポート出力のライフサイクル管理
- `BaseReport`クラスが共通処理を提供し、派生クラスが個別エラーを処理

#### Step 2: エントリーポイントを理解する

処理の起点となる関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | hwasan_report.cpp | `compiler-rt/lib/hwasan/hwasan_report.cpp` | ReportTagMismatch（1090-1094行目）、ReportInvalidFree（1081-1083行目）、ReportTailOverwritten（1085-1088行目）が各エントリーポイント |

**主要処理フロー**:
1. **1090-1094行目**: TagMismatchReportオブジェクト作成でレポート出力
2. **1021-1078行目**: TagMismatchReport::~TagMismatchReport()でデストラクタ実行時に出力

#### Step 3: 各レポートクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | hwasan_report.cpp | `compiler-rt/lib/hwasan/hwasan_report.cpp` | TagMismatchReport（1021-1078行目）：タグ不一致レポート |
| 3-2 | hwasan_report.cpp | `compiler-rt/lib/hwasan/hwasan_report.cpp` | InvalidFreeReport（902-938行目）：無効な解放レポート |
| 3-3 | hwasan_report.cpp | `compiler-rt/lib/hwasan/hwasan_report.cpp` | TailOverwrittenReport（940-1019行目）：テール上書きレポート |

**主要処理フロー**:
- **791-892行目**: PrintAddressDescription()でアドレス詳細を出力
- **894-900行目**: PrintTags()でタグダンプを出力
- **415-469行目**: PrintTagsAroundAddr()でタグ周辺情報を整形

#### Step 4: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | hwasan_report.cpp | `compiler-rt/lib/hwasan/hwasan_report.cpp` | PrintStackAllocations（205-346行目）：スタック変数の検索と出力 |
| 4-2 | hwasan_report.cpp | `compiler-rt/lib/hwasan/hwasan_report.cpp` | FindHeapAllocation（166-203行目）：ヒープ履歴の検索 |
| 4-3 | hwasan_report.cpp | `compiler-rt/lib/hwasan/hwasan_report.cpp` | FindBufferOverflowCandidate（679-718行目）：バッファオーバーフロー候補検索 |

### プログラム呼び出し階層図

```
ReportTagMismatch (hwasan_report.cpp:1090)
    │
    └─ TagMismatchReport::~TagMismatchReport (hwasan_report.cpp:1036)
           │
           ├─ BaseReport (hwasan_report.cpp:477)
           │      ├─ FindMismatchOffset (hwasan_report.cpp:563)
           │      ├─ CopyHeapChunk (hwasan_report.cpp:632)
           │      ├─ CopyAllocations (hwasan_report.cpp:647)
           │      ├─ FindBufferOverflowCandidate (hwasan_report.cpp:679)
           │      └─ CopyShadow (hwasan_report.cpp:594)
           │
           ├─ PrintAddressDescription (hwasan_report.cpp:791)
           │      ├─ PrintStackAllocations (hwasan_report.cpp:205)
           │      ├─ PrintHeapOrGlobalCandidate (hwasan_report.cpp:720)
           │      └─ GetStackTraceFromId (hwasan_report.cpp:97)
           │
           ├─ PrintTags (hwasan_report.cpp:894)
           │      └─ PrintTagsAroundAddr (hwasan_report.cpp:434)
           │
           ├─ ReportRegisters (hwasan_report.cpp:1098)
           │
           └─ MaybePrintAndroidHelpUrl (hwasan_report.cpp:104)
```

### データフロー図

```
[入力]                       [処理]                              [出力]

tagged_addr ────────────▶ BaseReport構築 ─────────────────┐
                               │                          │
access_size ────────────▶ FindMismatchOffset ─────────────┤
                               │                          │
シャドウメモリ ──────────▶ CopyShadow ───────────────────┤
                               │                          ▼
ヒープリングバッファ ────▶ CopyAllocations ─────────▶ レポート出力 ──▶ stderr
                               │                          │
スタックリングバッファ ──▶ PrintStackAllocations ────────┤
                               │                          │
Symbolizer ──────────────▶ スタックトレース解決 ──────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| hwasan_report.h | `compiler-rt/lib/hwasan/hwasan_report.h` | ヘッダー | レポートAPI宣言 |
| hwasan_report.cpp | `compiler-rt/lib/hwasan/hwasan_report.cpp` | ソース | レポート出力実装 |
| hwasan.h | `compiler-rt/lib/hwasan/hwasan.h` | ヘッダー | HWASan基本定義 |
| hwasan_allocator.h | `compiler-rt/lib/hwasan/hwasan_allocator.h` | ヘッダー | ヒープアロケータ |
| hwasan_thread.h | `compiler-rt/lib/hwasan/hwasan_thread.h` | ヘッダー | スレッド管理 |
| hwasan_mapping.h | `compiler-rt/lib/hwasan/hwasan_mapping.h` | ヘッダー | シャドウメモリマッピング |
| sanitizer_stackdepot.h | `compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h` | ヘッダー | スタックトレース保存 |
