型情報を値に付加するために使用しているCプログラムで使用される特定のデータ構造があります。簡単な例は次のようになります。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct teststruct
{
char type;
union {
char s;
int i;
float f;
} value;
};
int main()
{
struct teststruct *t = malloc(sizeof(struct teststruct)+10);
t->type = 'i';
t->value.i = 42;
free(t);
t = malloc(sizeof(struct teststruct)+10);
t->type = 's';
strcpy(&t->value.s, "test");
free(t);
printf("Finished without errors.\n");
}
ご覧のとおり、私の意図は、フィールドを使用type
して値のタイプを識別し、フィールドを使用しvalue
て可能な値の和集合を含めることです。データが文字列の場合、アイデアはより多くのメモリを割り当ててからsizeof(struct teststruct)
、で文字列にアクセスすること&t->value.s
です。
これは機能しますが、オプティマイザーにとっては明らかに問題があります。バージョン4.7.2を使用するgcc
と、最適化されていない状態で次のようになります。
$ gcc -O0 -o test test.c
$ ./test
Finished without errors.
問題ない。ただし、オプティマイザーの下では、警告が表示されます。
$ gcc -O2 -o test test.c
In file included from /usr/include/string.h:642:0,
from test.c:4:
In function ‘strcpy’,
inlined from ‘main’ at test.c:25:15:
/usr/include/i386-linux-gnu/bits/string3.h:105:3: warning: call to __builtin___memcpy_chk will always overflow destination buffer [enabled by default]
本当に、
$ ./test
*** buffer overflow detected ***: ./test terminated
ただし、に置き換えるstrcpy
と、これは正常に機能し、-loopmemcpy
に置き換えるとうまく機能します。ただし、と同じようにクラッシュします。私はメモリの外では絶対に上書きされないので、なぜこれがクラッシュするのかわかりません。strcpy
for
strncpy
strcpy
malloc
データ構造の奇妙なオフセットにコピーすることはそれほど一般的ではないことに気付いたので、問題は、のセマンティックコントラクトに違反しているのかstrcpy
、それともコンパイラのバグなのかということです。
ありがとう。