如何安全地调用 vsnprintf() ?

2023-11-30

我正在将一些非常古老(> 10 年)的 C 代码移植到现代 Linux。我在自定义编写的 vsnprintf() 包装器中遇到分段错误(显然它的任务是检测重复的输出字符串并实习它们):

char* strVPrintf(const String fmt, va_list ap)
{
  /* Guess we need no more than 50 bytes. */
  int n, size = 50;
  char* p = (char*)memMalloc(size), q;

  while (1) {
    /* Try to print in the allocated space. */
    n = vsnprintf(p, size, fmt, ap);
    /* If that worked, return the string. */
    if (n > -1 && n < size) {
      break;
    }
    /* Else try again with more space. */
    if (n > -1)                /* glibc 2.1 */
      size = n + 1;            /* precisely what is needed */
    else                   /* glibc 2.0 */
      size *= 2;               /* twice the old size */
    p = memRealloc(p, size);
  }

  q =  strRegister(p);
  memFree(p);
  return q;
}

作者似乎假设标准vsnprintf()函数返回写入的字符数,如果没有收到足够的空间来格式化所有参数,则简单地返回一个哨兵值。这意味着您可以猜测缓冲区大小并在必要时增加它。

但在我的系统(Ubuntu 14.04、glibc 2.19)上,当调用提供的空间的参数过多时,vnprintf 会导致分段错误。的语义是否snprintf()与此同时,家庭发生了巨大的变化?确保您提供足够缓冲空间的现代方法是什么?


这才是正确的使用方法snprintf and vsnprintf除了 SunOS 4(它已经过时了 20 年)之外的每个操作系统上都有,所以你的问题出在其他地方。

我会做一个纯粹的猜测,并说我几乎可以肯定你的问题是你传递了 va_listap into vsnprintf它会消耗它,然后您希望它在下次调用时重置。这是不正确的,并且许多年前已经在 gcc 中停止工作(因为它只在某些体系结构上工作)。

Change:

n = vsnprintf(p, size, fmt, ap);

To:

va_list apc;
va_copy(apc, ap);
n = vsnprintf(p, size, fmt, apc);
va_end(apc);

看看是否有帮助。

这是一个简单的测试,看看发生了什么:

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

void
foo(const char *fmt, va_list ap)
{
#ifdef BAD
    vprintf(fmt, ap);
#else
    va_list apc;
    va_copy(apc, ap);
    vprintf(fmt, apc);
    va_end(apc);
#endif
    vprintf(fmt, ap);
}

void
bar(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    foo(fmt, ap);
    va_end(ap);
}

int
main(int argc, char **argv)
{
    bar("foo %s\n", "bar");
    return 0;
}

运行时我得到这个:

$ cc -o foo foo.c && ./foo
foo bar
foo bar
$ cc -DBAD -o foo foo.c && ./foo
foo bar
foo ����
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何安全地调用 vsnprintf() ? 的相关文章

  • 为什么 std::vector 可以处理类定义中的不完整类型?

    出现了以下问题 C 标准似乎说 std vector需要一个完整的类型才能工作 看https en cppreference com w cpp container vector https en cppreference com w cp
  • 带有 ASP.NET 按钮回发的 jQuery UI 对话框

    我的 ASP NET 页面上有一个运行良好的 jQuery UI 对话框 jQuery function jQuery dialog dialog draggable true resizable true show Transfer hi
  • 如何使用不同的基本路径托管 Blazor WebAssembly 应用程序

    我有一个 Blazor Webassemble NET 托管应用程序 在我们托管它的服务器上 应用程序的基本路径将是mydomain com coolapp 因此 为了尝试让应用程序在服务器上正确呈现 我一直遵循本页 应用程序基本路径 部分
  • 使用 POST 的 HttpWebRequest 的性能

    我有一个用于测试网络服务的小工具 它可以使用 POST 或 GET 调用 Web 服务 使用POST的代码是 public void PerformRequest WebRequest webRequest WebRequest Creat
  • 如何从经过身份验证的 SecurityToken 中获取声明

    我将令牌作为字符串传递到 SOAP 服务中 并验证了该令牌是否有效 我现在有一个 SecurityToken 在调试模式下我可以看到所有声明 特别是我想传递到另一个方法的 userId 声明 我似乎不知道如何获得这些索赔 现在 我解码了令牌
  • 如何在 C# 中以编程方式将行添加到 DataGrid?

    正如标题所述 我正在尝试使用 C 以编程方式将行添加到 DataGrid 但我似乎无法使其工作 这是我到目前为止所拥有的 I have a DataGrid declared as dg in the XAML foreach string
  • 加载 QPixmap 数据的更好方法

    更好的方法来做到这一点 没有QImage QImage image width height QImage Format RGB888 memcpy image bits m frameRGB gt data 0 height width
  • 大量互斥体对性能的影响

    假设我有一个包含 1 000 000 个元素的数组 以及多个工作线程 每个线程都操作该数组中的数据 工作线程可能会使用新数据更新已填充的元素 但每个操作仅限于单个数组元素 并且独立于任何其他元素的值 使用单个互斥锁来保护整个数组显然会导致高
  • 如何在 C 中链接目标文件?失败并显示“架构 x86_64 的未定义符号”

    因此 我尝试在我的文件 file2 c 中使用另一个 C file1 c 文件中定义的函数 为了做到这一点 我包含了 file1 file1 h 的标头 但是 每当我尝试使用 gcc 编译文件时 我都会收到以下错误 Undefined sy
  • ASP.NET - Crystal Report Viewer 打印按钮在 ASP.NET 中不起作用

    我正在使用 Visual Studio 2008 但我遇到了水晶报告问题 当我单击打印按钮时 它会将我带到弹出窗口 但未找到页面 弹出的网址是 http localhost aspnet client System Web 2 0 5072
  • 运行实体框架自定义工具,它有什么作用?

    在 Visual Studio 中 当使用实体框架并为 tt 和 Context tt 文件应用运行自定义工具时 它是什么以及它有什么作用 为什么它解决数据库同步问题 有时 为什么我应该在运行 tt 之前运行它 Context tt 它被称
  • 如何在Windows窗体中打开进程

    我想在我的 Windows 窗体应用程序中打开进程 例如 我希望当用户按下 Windows 窗体容器之一中的按钮时 mstsc exe 将打开 如果他按下按钮 它将在另一个容器上打开 IE DllImport user32 dll SetL
  • 在 Visual Studio 2012 Express 中设置 C++ 调试环境

    我需要调试的应用程序需要设置环境变量 这在 Visual Studio 2012 中似乎非常复杂 我想做类似的事情 set path c foo c bar c windows c program files application set
  • 让 Windows 尝试读取文件

    我正在对 Windows 文件系统进行某种封装 当用户请求打开文件时 Windows 调用我的驱动程序来提供数据 在正常操作中 驱动程序返回缓存的文件内容 但是 在某些情况下 实际文件没有缓存 我需要从网络下载它 问题是是否有可能让 Win
  • 为什么我可以在另一个函数中定义一个函数?

    请参阅下面的代码 我在另一个函数中定义了一个函数 void test1 void void test2 void printf test2 n printf test1 n int main void test1 return 0 这个用法
  • 在多线程环境中捕获信号

    我有一个大型程序 需要尽可能具有弹性 并且有大量线程 我需要捕获所有信号SIGBUS SIGSEGV 并在必要时重新初始化有问题的线程 或者禁用该线程以继续减少功能 我的第一个想法是做一个setjump 然后设置信号处理程序 可以记录问题
  • 将同步 zip 操作转换为异步

    我们有一个现有的库 其中一些方法需要转换为异步方法 但是我不确定如何使用以下方法执行此操作 错误处理已被删除 该方法的目的是压缩文件并将其保存到磁盘 请注意 zip 类不公开任何异步方法 public static bool ZipAndS
  • Adobe Illustrator 中的折线简化如何工作?

    我正在开发一个记录笔划的应用程序 您可以使用定点设备来绘制笔划 在上图中 我绘制了一个笔划 其中包含 453 个数据点 我的目标是大幅减少数据点的数量 同时仍然保持原始笔画的形状 对于那些感兴趣的人 上图笔画的坐标可以作为GitHub 上的
  • NHibernate:无状态会话错误消息无法获取代理

    我正在使用 nHibernate 无状态会话来获取对象 更新一个属性并将对象保存回数据库 我不断收到错误消息 无状态会话无法获取代理 我在其他地方有类似的代码 所以我不明白为什么这不起作用 有谁知道问题可能是什么 我正在尝试更新Screen
  • 如何使用 Microsoft Graph API 更新 MailboxSettings

    我想从不同的日历更新邮箱设置 如何构建可以通过 Microsoft Graph 更新 MailboxSetting 的请求 这是我的代码示例 但有例外 代码示例 User obj GraphServiceClient Users roomC

随机推荐

  • 如何限制上传图片的宽度或高度

    我想以类似的方式操作 调整图像大小兴趣但我不确定解决这个问题的最佳方法是什么 目标是允许混合纵向和横向图像 但对最大高度和宽度施加一些限制 我看到的问题是 如果我调整宽度 肖像图像可能会变得太薄 而风景图像则相反 关于如何使用 PHP 实现
  • 重构 JSON

    我现在有来自服务器的 JSON 响应 但我想根据日期重组它 例如我现在有 items A name a date 2 10 2010 sales 100 name b date 6 10 2010 sales 400
  • “git分支”和“git checkout -b”有什么区别?

    I used git checkout b创建一个新分支 我觉得git branch做同样的事情 如果这两个命令有不同的话 它们有何不同 git checkout b BRANCH NAME创建一个新分支并签出新分支 同时git branc
  • 我应该设计一个主键为 varchar 还是 int 的表?

    我知道这是主观的 但我想了解人们的意见 并希望在设计 sql server 表结构时可以应用一些最佳实践 我个人认为 在固定 最大 长度的 varchar 上键入表是不行的 因为这意味着必须在使用它作为外键的任何其他表上传播相同的固定长度
  • 如何读取/流式传输文件而不将整个文件加载到内存中?

    如何读取任意文件并 逐个 处理它 意味着逐字节或其他一些可以提供最佳读取性能的块大小 而不将整个文件加载到内存中 处理的一个示例是生成文件的 MD5 哈希值 尽管答案可以适用于任何操作 我想拥有或编写这个 但如果我可以获得现有的代码 那就太
  • PDO 使用键作为列名插入数组

    我正在使用 PDO 将 PHP 数组的 POST 内容插入到表中 我正在查看以下代码行 我有一个 必须有更好的方法来做到这一点 的时刻 如果键名与表中的列名匹配 是否有更简单的方法来插入所有键名 代码例如 statement db gt p
  • 下划线:基于多个属性的sortBy()

    我正在尝试根据多个属性对包含对象的数组进行排序 即 如果两个对象之间的第一个属性相同 则应使用第二个属性来比较这两个对象 例如 考虑以下数组 var patients name John roomNumber 1 bedNumber 1 n
  • 与 AVX/AVX2 一起使用的最低 OS X 版本是什么?

    我有一个图像绘制例程 为 SSE SSE2 SSE3 SSE4 1 SSE4 2 AVX 和 AVX2 编译多次 我的程序通过检查 CPUID 标志来动态调度这些二进制变体之一 在 Windows 上 我检查 Windows 版本 如果操作
  • 在 C 中设置位

    我正在尝试执行以下操作 写一个函数setbits x p n y 返回x with n开始于的位 位置p设置到最右边n的位y 留下其他位 不变 我这样尝试但没有得到正确的答案 谁能告诉我哪里错了 unsigned setbits unsig
  • Android 键盘隐藏 EditText

    当我尝试在屏幕底部的 EditText 中写入内容时 软键盘会隐藏 EditText 我该如何解决这个问题 下面是我的 xml 代码 我在片段中使用它
  • 如何检索 Android 中可用/已安装字体的列表?

    在Java中我会做类似的事情 java awt GraphicsEnvironment ge java awt GraphicsEnvironment getLocalGraphicsEnvironment Font fonts ge ge
  • 命令行参数太多 Terraform 计划

    我是地形新手 我正在尝试通过天蓝色管道创建一个简单的存储帐户 但是当我运行管道时 我收到错误 命令行参数太多 我很震惊 我不知道我做错了什么 有人可以帮忙吗 这是我的计划脚本 script terraform plan out plan t
  • 如何使用占位符将列名值作为 SQL 参数传递

    如何使用参数占位符将列名值作为 SQL 参数传递 目标是让这个工作 var sql SELECT FROM Condos WHERE 0 LIKE 1 var sqlData db Query sql choice searchString
  • 如何从java应用程序创建Windows服务

    我刚刚继承了一个java应用程序 需要将其作为服务安装在XP和vista上 自从我以任何形式使用 Windows 以来 已经有大约 8 年了 我从来没有创建过服务 更不用说像 Java 应用程序这样的东西了 我有一个应用程序的 jar 和一
  • Android 连接至已配对的蓝牙耳机

    我想模拟通过 设置 gt 无线 gt 蓝牙 的操作 并以编程方式连接配对的蓝牙耳机 我在 Stackoverflow 和 Google 上进行了一些搜索 两者都表明在 API 级别 11 之前没有可用的解决方案 但是 我有兴趣通过查看 An
  • 使用 python 和 pandas 按季节对数据进行分组

    我想使用 Pandas 和 Python 迭代我的 csv 文件 并按季节对数据进行分组 计算一年中每个季节的平均值 目前 季度脚本为一月至三月 四月至六月等 我希望季节与月份相关联 11 冬季 12 冬季 1 冬季 2 春季 3 春天 4
  • 解析复杂的肥皂响应

    我正在 android 中构建我的第一个应用程序 该应用程序使用 wcf 服务 我正在使用 ksoap2 来解析响应 响应实际上是 C 中定义的对象数组 我这样做了 这非常有帮助guide现在我的问题是我需要使用一个 wcf 服务 它再次返
  • 如何在 OPENGL 中旋转或平移单个对象实例?

    假设我有一个有四个立方体的场景 我该如何说在 OpenGL 中仅旋转 平移其中两个立方体而不使用 glrotatef 和 f gltranslate 更改其他立方体 我不想定义我自己的齐次坐标 像往常一样绘制前两个立方体 推入视图模型矩阵
  • iPhone 上的点击延迟和抑制输入焦点

    iPhone 上的 webkit 浏览器在用户进行触摸和 javascript 获取单击事件之间有 300 毫秒的延迟 发生这种情况是因为浏览器需要检查用户是否进行了双击 我的应用程序不允许缩放 因此双击对我来说毫无用处 有不少人有提出的解
  • 如何安全地调用 vsnprintf() ?

    我正在将一些非常古老 gt 10 年 的 C 代码移植到现代 Linux 我在自定义编写的 vsnprintf 包装器中遇到分段错误 显然它的任务是检测重复的输出字符串并实习它们 char strVPrintf const String f