仔细检查缓冲区的大小

时间:2015-06-03 16:10:10

标签: c printf overflow

我对我开发的库中存在潜在的缓冲区溢出存在疑问,其中存在可从外部应用程序调用的以下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是否是正确的大小?

谢谢大家!

1 个答案:

答案 0 :(得分: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;
}

这样,您可以控制内存分配,从而可以防止缓冲区溢出

相关问题