为什么vsnprintf是安全的

Why is vsnprintf safe?

本文关键字:安全 vsnprintf 为什么      更新时间:2023-10-16

我已经看了这个问题以及PDF的1和2,这个页面,非常了解如果我做这个printf(SOME_TEST_STRING)会发生什么。但我不明白的是,为什么通过确保缓冲区vsnprintf的大小与vsprintf相比是安全的?

在这两种情况下会发生什么?

案例1

char buf[3];
vsprint(buf, "%s", args);

案例2

char buf[3];
vsnprint(buf, sizeof buf, "%s", args);

在情况1中,如果正在格式化的字符串长度为3或更大,则缓冲区溢出,vsprintf可能会在buf数组的存储区之后写入内存,这是未定义的行为,可能会导致严重破坏/安全问题/崩溃等。

在情况2。vsnprintf知道将包含结果的缓冲区有多大,它将确保不会超过这个缓冲区(而是截断结果以适合buf)。

这是因为vsnprintf有一个vsprintf(和其他非n*sprintf方法)没有的额外size_t count参数。该实现使用它来确保它写入缓冲区的数据不会在最后运行。

缓冲区末端的数据可能会导致数据损坏,或者当被恶意利用时,可能会被用作缓冲区溢出攻击。

vsnprintf()中的"n"表示它采用输出字符串的最大大小来避免缓冲区溢出。这样可以避免缓冲区溢出,但如果格式字符串来自未初始化的用户输入,则不能确保安全。如果用户给你一个巨大的格式字符串,你可以避免目标字符串溢出,但如果用户给了你%s,而你在编译时没有在参数列表中传递C字符串,你仍然会有未定义的行为。

我不确定问题是什么,因为你的问题基本上已经包含了答案。

通过将缓冲区大小传递给vsnprintf,可以为该函数提供有关缓冲区大小的信息。该函数现在知道缓冲区的结束位置,并可以确保它不会写过缓冲区的末尾。

vsprintf没有关于缓冲区大小的信息,这就是为什么它不知道缓冲区结束在哪里,并且不能防止缓冲区溢出。