【发布时间】:2015-06-03 16:10:10
【问题描述】:
我对我开发的库中潜在的缓冲区溢出存有疑问,其中可以从外部应用程序调用以下 API。我试图找到一个可能的解决方案,但我还没有找到“正确”的解决方案。 API如下:
char* strftime_ISO8601(uint64_t ns, char* buf, size_t buflen) {
if (buf) {
//The standard format ISO 8601 is 20 bytes + 1 null
char datetime[21];
struct tm tm;
struct timespec ts = //convert nanoseconds into timespec
gmtime_r(&ts.tv_sec, &tm);
strftime(datetime, sizeof(datetime), "+%FT%T", &tm);
snprintf(buf, buflen, "%s.%.9ld", datetime, ts.tv_nsec);
}
return buf;
}
我需要提供对“缓冲区溢出”足够安全的代码。出于这个原因,我使用了 snprintf,其中目标缓冲区的大小作为参数给出,结果字符串以 NULL 结尾。 我还使用一些静态分析工具(如 RATS)来突出潜在的漏洞。在这种情况下,我有以下通知:
Double check that your buffer is as big as you specify. When using functions that accept a number n of bytes to copy, such as strncpy, be aware that if the destination buffer size = n it may not NULL-terminate the string.
关于snprintf
snprintf(buf, buflen, "%s.%.9ld", datetime, ts.tv_nsec);
使用 snprintf 我确定字符串将以 NULL 结尾,但是我如何仔细检查输入中给出的缓冲区是否真的大小为 buflen?
我的意思是,如果用户以错误的大小调用 API,例如
...
char bad[5]
strftime_ISO8601(x, bad, 1024);
....
甚至最糟糕的是使用这样的未初始化缓冲区:
...
char *bad;
strftime_ISO8601(x, bad, 1024);
...
潜在的分段错误的一部分,我没有在上述 API 中看到任何特定的漏洞。但是如何验证 API 作为输入接收的 buflen 大小是否正确?
谢谢大家!
【问题讨论】:
-
Minor:为什么在
"+%FT%T"中有"+"?根据ISO8601,似乎+仅在年份值存在于0-9999 范围之外时才需要,在这种情况下char datetime[21];太小了。 -
次要:在试验
"%F"时,+或-已在需要时添加。建议删除+并使用更大的缓冲区。