仔细检查缓冲区的大小
Double check the size of a buffer
我怀疑我开发的库中可能存在缓冲区溢出,其中有以下 API 可以从外部应用程序调用。我试图找到一个可能的解决方案,但我还没有找到 "right" 那个。 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;
}
我需要提供对 "buffer overflow" 足够安全的代码。出于这个原因,我使用 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 大小是否正确?
谢谢大家!
简单地说 - 你不能...
无法确定您作为指针收到的内存地址的 "length",因为没有实体可以在运行时验证它。这就是您首先要求长度的原因!
在您的情况下,唯一的解决方案是自己分配内存,然后 return 分配给用户,将管理该内存的责任转移给用户:
char* strftime_ISO8601(uint64_t ns) {
//The standard format ISO 8601 is 20 bytes + 1 null
char datetime[21];
char *res = malloc(EXPECTED_SIZE)
struct tm tm;
struct timespec ts = //convert nanoseconds into timespec
gmtime_r(&ts.tv_sec, &tm);
strftime(datetime, sizeof(datetime), "+%FT%T", &tm);
snprintf(res, EXPECTED_SIZE, "%s.%.9ld", datetime, ts.tv_nsec);
return res;
}
这样,您就可以控制内存分配,从而防止缓冲区溢出
我怀疑我开发的库中可能存在缓冲区溢出,其中有以下 API 可以从外部应用程序调用。我试图找到一个可能的解决方案,但我还没有找到 "right" 那个。 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;
}
我需要提供对 "buffer overflow" 足够安全的代码。出于这个原因,我使用 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 大小是否正确?
谢谢大家!
简单地说 - 你不能...
无法确定您作为指针收到的内存地址的 "length",因为没有实体可以在运行时验证它。这就是您首先要求长度的原因!
在您的情况下,唯一的解决方案是自己分配内存,然后 return 分配给用户,将管理该内存的责任转移给用户:
char* strftime_ISO8601(uint64_t ns) {
//The standard format ISO 8601 is 20 bytes + 1 null
char datetime[21];
char *res = malloc(EXPECTED_SIZE)
struct tm tm;
struct timespec ts = //convert nanoseconds into timespec
gmtime_r(&ts.tv_sec, &tm);
strftime(datetime, sizeof(datetime), "+%FT%T", &tm);
snprintf(res, EXPECTED_SIZE, "%s.%.9ld", datetime, ts.tv_nsec);
return res;
}
这样,您就可以控制内存分配,从而防止缓冲区溢出