【问题标题】:Double check the size of a buffer仔细检查缓冲区的大小
【发布时间】: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" 时,+- 已在需要时添加。建议删除 + 并使用更大的缓冲区。

标签: c printf overflow


【解决方案1】:

简单地说 - 你不能...
无法确定作为指针接收的内存地址的“长度”,因为没有实体可以在运行时验证它。这就是您首先要求长度的原因!

在您的情况下,唯一的解决方案是自己分配内存并将其返回给用户,将管理该内存的责任转移给用户:

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!
猜你喜欢
  • 1970-01-01
  • 2020-09-05
  • 2014-06-10
  • 1970-01-01
  • 2015-06-05
  • 2013-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多