如何安全使用strnlen?
How to use strnlen safely?
我试图了解什么是正确的使用方法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
来计算考虑到此类情况并且不会导致未定义行为的字符串的长度?
此代码很可能会调用 undefined behavior。
malloc
返回的字节具有不确定的值。如果返回的 5 个字节中没有空字节,则 strnlen
将读取超过这些字节,因为它最多传递了 10 个字节,并且读取超过已分配内存的末尾会调用未定义的行为。
只是读取返回的字节,但是应该不是未定义的。虽然不确定的值可能包含陷阱表示,但 strnlen
使用 char *
读取字节,而字符类型 没有 具有陷阱表示,因此这些值只是未指定阅读它们是安全的。
如果传递给strnlen
的值不大于分配内存的大小,那么它的使用是安全的。
为了安全地使用strnlen
,您需要
自己跟踪输入缓冲区的大小(在你的情况下为 5)并将 that 作为第二个参数传递,not 大于那个数。
确保输入指针不是NULL
.
确保另一个线程没有写入缓冲区。
形式上,您不需要初始化缓冲区的内容,因为从概念上讲,函数读取缓冲区就像它们是 char
类型一样。
由于数据的实际长度是 5,而且你很可能没有'\0',它会开始读取未分配的内存(从 data[5] 开始),这可能有点不愉快.
我试图了解什么是正确的使用方法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
来计算考虑到此类情况并且不会导致未定义行为的字符串的长度?
此代码很可能会调用 undefined behavior。
malloc
返回的字节具有不确定的值。如果返回的 5 个字节中没有空字节,则 strnlen
将读取超过这些字节,因为它最多传递了 10 个字节,并且读取超过已分配内存的末尾会调用未定义的行为。
只是读取返回的字节,但是应该不是未定义的。虽然不确定的值可能包含陷阱表示,但 strnlen
使用 char *
读取字节,而字符类型 没有 具有陷阱表示,因此这些值只是未指定阅读它们是安全的。
如果传递给strnlen
的值不大于分配内存的大小,那么它的使用是安全的。
为了安全地使用strnlen
,您需要
自己跟踪输入缓冲区的大小(在你的情况下为 5)并将 that 作为第二个参数传递,not 大于那个数。
确保输入指针不是
NULL
.确保另一个线程没有写入缓冲区。
形式上,您不需要初始化缓冲区的内容,因为从概念上讲,函数读取缓冲区就像它们是 char
类型一样。
由于数据的实际长度是 5,而且你很可能没有'\0',它会开始读取未分配的内存(从 data[5] 开始),这可能有点不愉快.