安全ではないマクロ関数
はじめに
安全なコーディング(セキュアコーディング)の勉強中である。
セキュアコーディングのサイトを見つけたので、勉強中に試したものを記事として残す。
記事概要
マクロ関数は、安全ではない1例が記載されていた(PRE31-C)ので、試してみた。
安全ではないマクロ関数
下記ソースは、引数に渡された値の絶対値を返却するマクロが含まれており、そのマクロを使って計算した結果を出力するものである。
しかし、想定どおりに動作しない。
(想定)引数の絶対値
(実際)?
安全ではないマクロを使ったソース andre@andre-VirtualBox:~/work/PRE/PRE31-C$ cat main.c #include#define ABS(x) ( ((x) < 0) ? -(x) : (x) ) // 展開後=> ( ((++n) < 0) ? -(++n) : (++n) ) ★ ? の左右で n が1回ずつインクリメントされる。 int main(void) { int m = 0; int n1 = 1; int n2 = -4; int n3 = 0; m = ABS( ++(n1) ); printf("m = %d\n", m); m = ABS( ++(n2) ); printf("m = %d\n", m); m = ABS( ++(n3) ); printf("m = %d\n", m); return 0; }
ビルドして、動作させてみた。
andre@andre-VirtualBox:~/work/PRE/PRE31-C$ gcc -o test_main main.c andre@andre-VirtualBox:~/work/PRE/PRE31-C$ ./test_main m = 3 (想定)m = 2 m = 2 (想定)m = 3 m = 2 (想定)m = 1
安全に(想定どおりに)動作させるには
inline もしくは static 関数として定義する。
下記に示す。
andre@andre-VirtualBox:~/work/PRE/PRE31-C$ cat main_legal.c #includeinline int abs( int x ) { return ( ((x) < 0) ? -(x) : (x) ); } int main(void) { int m = 0; int n1 = 1; int n2 = -4; int n3 = 0; m = abs( ++(n1) ); printf("m = %d\n", m); m = abs( ++(n2) ); printf("m = %d\n", m); m = abs( ++(n3) ); printf("m = %d\n", m); return 0; }
ビルドして、想定どおりに動作するか試した。
andre@andre-VirtualBox:~/work/PRE/PRE31-C$ gcc -o main_legal main_legal.c andre@andre-VirtualBox:~/work/PRE/PRE31-C$ ./main_legal m = 2 (想定)m = 2 m = 3 (想定)m = 3 m = 1 (想定)m = 1
結論
マクロは想定したとおりに動作しないことがあるので、基本的に使わないようにする。