sprintf/snprintf 陷阱

28 Dec 2008
最近 ubuntu/debian 正在讨论 sprintf/snprintf 的问题,我在这描述一遍。

sprintf 的原型为:
int sprintf(char *restrict s, const char *restrict format, ...);

其中 char* restrict s 的含义为通过s 指向的内存空间不得与其他指针参数指向的内存的空间重叠。比如如下的语句就是错误的用法, 因为参数1与参数3指向的内存重叠了。但这种做法作为增强版的 strcat 已被广泛使用。

sprintf(buf, "%s foo %d %d", buf, var1, var2);

在 ubuntu 8.10 所带的 gcc 中,如果编译时加入了优化选项(比如 -O1, -O2), 那么sprinf 会首先将 s 清空,比如如下的程序会输出 "fail", 而不是 "not fail"。

#include <stdio.h>

char buf[80] = "not ";

int main() {
  sprintf(buf, "%sfail", buf);
  puts(buf);
  return 0;
}
作为补救方案,可以使用如下的语句来代替:

sprintf(buf+strlen(buf), " foo %d %d", var1, var2);

snprintf 有类似的 bug.

很多 Debian/Ubuntu 包都有此 bug,可以参见如下两个 thread 中的具体内容

[1] https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/305901
[2] http://groups.google.com/group/linux.debian.devel/browse_thread/thread/c5bbda39f1a01bd4

Tags: ubuntu, debian, sprintf, snprintf

Related Posts:

comments powered by Disqus
Copyright © 2017 LI Daobing, Powered by github:pages, Jekyll, bootstrap, Designed by quanquan
Fork me on GitHub