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实现。
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实现。
相关文章推荐
- c++拼接字符串效率比较(+=、append、stringstream、sprintf)
- JS字符串拼接的问题
- js拼接字符串时,字符串首出现undefined的问题
- 解决oracle数据库wm_concat()字符串拼接过长问题
- 字符串拼接的双引号和单引号问题,转义字符
- 整数与字符串的拼接问题的解决
- 拼接html字符串时单引号问题
- 拼接字符串时,单引号与双引号的问题
- Jquery的each函数拼接字符串传参问题
- android端上传后台数据 string字符串拼接问题
- 循环体中用“+”拼接字符串-代码典型缺陷分析
- python中str字符串和unicode对象字符串的拼接问题
- C++ 学习日常填坑---字符串拼接问题
- 从外部配置文件SHELL字符串拼接遇到的问题
- sqlite插入记录值为纯数字的字符串的问题以及sqlite语句中字符串的拼接
- php常用字符串输出方法分析(echo,print,printf及sprintf) 原创
- js中字符串拼接需注意的问题
- java字符串拼接与性能分析详解