为什么vsnprintf是安全的
Why is vsnprintf safe?
我已经看了这个问题以及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
没有关于缓冲区大小的信息,这就是为什么它不知道缓冲区结束在哪里,并且不能防止缓冲区溢出。
- 从不同线程使用int64的不同字节安全吗
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 虚拟决赛作为安全
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何将元素添加到数组的线程安全函数?
- C++中的线程安全删除
- 通过网络、跨平台传递std::变体是否安全
- 在std::thread中,joinable()然后join()线程安全吗
- 使用std::istream::peek()总是安全的吗
- 从值小于256的uint16到uint8的Endian安全转换
- 在c++队列中使用pop和visit实现线程安全
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- 全局变量 多读取器 一个写入器多线程安全?
- 安全到标准:移动会员?
- AcquireCredentialsHandleA() 返回 PFX 文件的0x8009030e(安全包中没有可用的凭据
- 共享队列的线程安全
- boost::文件系统::recursive_directory_iterator多线程安全
- 跨 DLL 边界访问虚拟方法是否安全/可能?
- 为什么vsnprintf是安全的