前回、strcpy()は __builtin_strcpy_chk() を使っていて。。という話を書いたので、コンパイラが専用にサポートしている関数しかコンパイル時ワーニングを出せないと理解されてしまう恐れがあると思いここで、補足しておく

以下の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 の専用サポートなしで構築されている。