具体例1: サイズを指定して確保した領域を超えた書き込み
レポート結果
ログからわかること
・対象のプロセスIDは 26252
・アドレス 0x00010b998124 において、global-buffer-overflow を検出した
・PCレジスタが 0x00010b9ebd00, BPレジスタが 0x7ffee4268a00, SPレジスタが 0x7ffee42681a0 の状態だった
・スレッドT0(メインスレッドのこと)で発生
・5バイトの書き込みをしようとした時にアドレス0x00010b998124が違反した事を検知した(※00x00010b998124からの5バイトの書き込みという意味ではない)
・test21.cpp の 8行目から呼び出された strcpy で発生(※コンパイラが自動的に strcpyの代わりに wrap_strcpy を呼び出す処理に書き換えていた)
・アドレス 0x00010b998124 は、test21.cppの4行目で宣言されている 0x10b998120から4バイト分確保された’globalBuffer’という名前で確保されたグローバル変数の範囲外
【SUMMARY 以降】
・違反になったアドレスより前の4バイト分の領域は普通にアクセスできる(00)
・違反になったアドレスは4バイト確保された後のバッファとしてマークされている(04)
・さらに1バイト後のアドレスは確保されていないグローバル領域(f9)
【ログから推測できる不具合の内容】
・確保すべきバッファのサイズが小さい(確保サイズを間違えている)
・格納する内容が大きい(格納サイズを間違えている)
・先頭アドレスの計算を間違えている(オフセット計算)
参考)上記のログを発生させたソースコード
#include <string.h> // グローバル領域 char globalBuffer[4]; int main(int argc, char *argv[]) { // グローバル領域にある4バイト分の領域に(4+終端)文字の計5バイト格納 strcpy(globalBuffer, "ABCD"); return 0; }
参考)コンパイル・実行例
$ clang++ -g -O0 -o test21 -fsanitize=address test21.cpp $ ./test21
具体例2: 定義時のサイズより大きな型で参照
レポート結果
ログからわかること
・対象のプロセスIDは 26368
・アドレス 0x000102ead060 において、global-buffer-overflow を検出した
・PCレジスタが 0x000102eace7d, BPレジスタが 0x7ffeecd539f0, SPレジスタが 0x7ffeecd539e8 の状態だった
・スレッドT0(メインスレッドのこと)で発生
・4バイトの読み込みをしようとした時にアドレス0x000102ead060が違反した事を検知した ※違反アドレスは正しくは 0x000102ead062 のハズだが 4バイト分を一度に読み込むCPU命令で違反が起きたためにアドレスを誤認識していると思われる。
・test22.cpp の 10行目から呼び出された処理で発生
・アドレス 0x000102ead062 は、test22.cppの4行目で宣言されている 0x102ead060から2バイト分確保された’globalShortValue’という名前で確保されたグローバル変数の範囲外
【SUMMARY 以降】
・違反になったアドレスより前の領域は普通にアクセスできる(00)
・違反になったアドレスは2バイト確保された後のバッファとしてマークされている(02)
・さらに1バイト後のアドレスは確保されていないグローバル領域(f9)
【ログから推測できる不具合の内容】
・確保すべき変数のサイズが小さい(確保サイズを間違えている)
・参照する型が大きい(取得サイズを間違えている)
・先頭アドレスの計算を間違えている(オフセット計算)
参考)上記のログを発生させたソースコード
#include <string.h> // グローバル領域 short globalShortValue = 123; int main(int argc, char *argv[]) { // グローバル領域にある変数のポインタアドレス取得 void* ptr = &globalShortValue; // 無理やりint型の変数へのポインタとみなして値を取得 int value = *(int*)ptr; return 0; }
参考)コンパイル・実行例
$ clang++ -g -O0 -o test22 -fsanitize=address test22.cpp $ ./test22