前回、strcpy()は __builtin_strcpy_chk() を使っていて。。という話を書いたので、コンパイラが専用にサポートしている関数しかコンパイル時ワーニングを出せないと理解されてしまう恐れがあると思いここで、補足しておく
以下のgist をみるとわかるように大抵のコンパイル時処理は自前でできる。今のところコンパイル時にstrlen()をする方法が思いつかないので __builtin_strcpy_chk()は無理かもしれないが。
https://gist.github.com/kosaki/5515798
ポイントは
attribute((alias))を使うと、my_memcpy_warnをmy_memcpy_chkのエイリアスとして登録できる。
その上で、関数宣言のほうで、
__attribute__((warning))を使って、 my_memcpy_warnのほうだけ呼ばれたら、コンパイル時にwarning出すようにコンパイル時の扱いを変更できる。
んでもって、
コンパイル時に一意にきまるということは __builtin_constant_p() が trueになるはずなので、場合分けが
出来るのである。
実際、libcのなかではほとんどのFORTIFY_SOURCEの処理はこんな感じで gcc の専用サポートなしで構築されている。
以下のgist をみるとわかるように大抵のコンパイル時処理は自前でできる。今のところコンパイル時にstrlen()をする方法が思いつかないので __builtin_strcpy_chk()は無理かもしれないが。
https://gist.github.com/kosaki/5515798
ポイントは
char* my_memcpy_warn () __attribute__ ((alias("my_memcpy_chk")));
attribute((alias))を使うと、my_memcpy_warnをmy_memcpy_chkのエイリアスとして登録できる。
その上で、関数宣言のほうで、
char* my_memcpy_chk (char *dest, const char *src, size_t len, size_t destlen);
char* my_memcpy_warn (char *dest, const char *src, size_t len, size_t destlen)
__attribute__((__warning__ ("my warning")));
__attribute__((warning))を使って、 my_memcpy_warnのほうだけ呼ばれたら、コンパイル時にwarning出すようにコンパイル時の扱いを変更できる。
んでもって、
static char* my_memcpy(char* dst, const char* src, size_t len)
{
size_t d = __builtin_object_size(dst, 0);
if (d != (size_t) -1) {
if (__builtin_constant_p(len) && len > d)
return my_memcpy_warn(dst, src, len, d);
else
return my_memcpy_chk(dst, src, len, d);
} else
return memcpy (dst, src, len);
}
コンパイル時に一意にきまるということは __builtin_constant_p() が trueになるはずなので、場合分けが
出来るのである。
実際、libcのなかではほとんどのFORTIFY_SOURCEの処理はこんな感じで gcc の専用サポートなしで構築されている。
コメント