如何安全使用strnlen?

时间:2018-07-11 13:58:57

标签: c strlen

我正在尝试了解使用strnlen的正确方法是什么,以便即使考虑到边缘情况也可以安全地使用它。

例如,以非空终止的字符串作为输入。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    void* data = malloc(5);

    size_t len = strnlen((const char*)data, 10);
    printf("len = %zu\n", len);

    return 0;
}

如果我期望一个最大大小为10的字符串,但是该字符串在这10个字符中不包含空字符,strnlen将读取越界字节(输入指针可能指向分配的堆)数据)。这种行为是不确定的吗?如果是,是否有一种方法可以安全地使用strnlen计算字符串的长度,而这种长度考虑了这种情况,并且不会导致未定义的行为?

3 个答案:

答案 0 :(得分:5)

为了安全地使用strnlen,您需要

  1. 自己跟踪输入缓冲区的大小(在您的情况下为5),并传递 that 作为第二个参数, not 大于该数字

  2. 确保输入的指针不是NULL

  3. 确保另一个线程未将其写入缓冲区。

从形式上讲,您不需要初始化缓冲区的内容,因为从概念上讲,该函数将读取缓冲区,就好像它们是char类型一样。

答案 1 :(得分:1)

此代码很可能会调用undefined behavior

malloc返回的字节具有不确定的值。如果在返回的5个字节中没有空字节,则strnlen将读取超过这些字节的值,因为它最多传递了10个字节,读取超过分配的内存末尾将引发未定义的行为。

仅读取返回的字节,但是应该 not 未定义。尽管不确定的值可以包含陷阱表示,但是strnlen使用char *读取字节,并且字符类型 not 没有陷阱表示,因此这些值只是未指定并读取它们是安全的。

如果传递给strnlen的值不大于分配的内存大小,则使用它是安全的。

答案 2 :(得分:0)

由于数据的实际长度为5,并且您很可能没有在其中的'\ 0',它将开始读取未分配的内存(从data [5]开始),这可能有点不愉快。 / p>