您的位置:首页 > 其它

sprintf做字符串拼接的问题分析

2010-09-03 00:24 295 查看
调试之前写的一段代码,其中使用sprintf做字符串拼接:

sprintf(sql, "select * from TEST_TABLE");

......

sprintf(sql, "%s%s", sql, " where (RELY_TYPE='S')");

使用auto tools生成Makfile,编译,运行出错:执行完第二句sprintf后sql=“ where (RELY_TYPE='S')”而非预料中的“select * from TEST_TABLE where (RELY_TYPE='S')”

问题分析:

1》

automake生成的gcc编译命令为:

gcc -DHAVE_CONFIG_H -I. -I. -I../src/include -g -fmessage-length=0 -D_FORTIFY_SOURCE=2 -Wall -g -O2 -MT sprintf_test -MD -MP -MF -c -o sprintf_test sprintf_test.c

将该命令简化为:

gcc -D_FORTIFY_SOURCE=2 -g -O2 -o sprintf_test sprintf_test.c

后问题依旧,但是去掉选项 gcc -D_FORTIFY_SOURCE=2 或 -O 2后编译,运行结果sql=“select * from TEST_TABLE where (RELY_TYPE='S')”

2》

对比分析不同选项情况下gcc编译出的汇编代码:

gcc -D_FORTIFY_SOURCE=2 -g -O2 -o sprintf_test sprintf_test.c

汇编代码中sprintf被编译成__sprintf_chk函数调用,由于__sprintf_chk

gcc -g -O2 -o sprintf_test sprintf_test.c 或 gcc -D_FORTIFY_SOURCE=2 -g -o sprintf_test sprintf_test.c

汇编代码中sprintf被编译成sprintf函数调用

__sprintf_chk和sprintf的实现差异导致了上述问题的出现,__sprintf_chk的描述如下:

The interface __sprintf_chk() shall function in the same way as the interface sprintf(), except that __sprintf_chk() shall check for stack overflow before computing a result, depending on the value of the flag parameter. If an overflow is anticipated, the function shall abort and the program calling it shall exit.

The __sprintf_chk() function is not in the source standard; it is only in the binary standard.

3》

-D_FORTIFY_SOURCE=2 和-O2一起使用会导致编译器使用做内存边界检验等“安全”的方式实现,从而采用了__sprintf_chk函数调用:

-D_FORTIFY_SOURCE=2 First enabled in Ubuntu 8.10. Provides compile-time best-practices errors for certain libc functions, and provides run-time checks of buffer lengths and memory regions. Only activated when compiled with -O2 or higher. Most problems are related to common unsafe uses of certain libc functions.

结论:

sprintf实现字符串拼接,尤其是本例中自身拼接,是不安全的实现,建议使用strcat或strncat实现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: