【问题标题】:free percent character in format string for _vsnprintf and _vsnprintf_s_vsnprintf 和 _vsnprintf_s 格式字符串中的空闲百分比字符
【发布时间】:2015-05-20 19:44:47
【问题描述】:

格式字符串中的免费“%”行为非常令人惊讶。

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

void foo(const char *format, ...) {
  const size_t buffSize = 1024;
  char msg[buffSize];
  {
    va_list args;
    va_start(args, format);
    _vsnprintf(msg, buffSize, format, args);
    va_end(args);
    std::cout << msg << std::endl; // here you get a,b,,c,d,e
  }
  {
    va_list args;
    va_start(args, format);
    _vsnprintf_s(msg, buffSize, format, args); // and here you crash and burn
    va_end(args);
    std::cout << msg << std::endl;
  }
}

int _tmain(int argc, _TCHAR *argv[]) {
  foo("%s,b,%,c,d,%s", "a", "e");
  return 0;
}

这不是你期望得到的,尤其是当下面的is stated by Microsoft

如果百分号后面跟着一个没有意义的字符 格式字段,字符被复制到输出不变。

那么我们在这里看到了什么?一个错误?从何时起?是否为 msvc12/13 修复了?

EDIT01: 好的,我看错了声明,让我们专注于崩溃

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

void foo(const char *format, ...) {
  const size_t buffSize = 1024;
  char msg[buffSize];
  va_list args;
  va_start(args, format);
  _vsnprintf_s(msg, buffSize, format, args);
  va_end(args);
  std::cout << msg << std::endl;
}

int main(int argc, char *argv[]) {
  foo("b,%,c,d"); // crash here
  foo("%s,b,%,c,d,%s", "a", "e"); // there and everywhere
  return 0;
}

EDIT02:
从 Microsoft Connect 获得答案

感谢您就此问题与 Microsoft 联系。我们发现我们 遗漏了有关安全功能如何表现的重要信息 从格式规范语法页面。安全功能 格式字符串的附加验证,并调用无效的 如果在初始 % 之后出现意外字符,则参数处理程序 特点。默认情况下,这会使用 Dr. Watson 终止程序 报告。在调试模式下,它首先导致断言。更多信息是 在参数验证主题中可用 https://msdn.microsoft.com/en-us/library/ksazx244.aspx 。格式 正在使用此信息更新规范语法页面。 预计在下周看到 Visual Studio 2013 的更新页面 左右。

【问题讨论】:

  • 有什么问题?字符 (',') 被 原样复制到输出。如果要打印实际的百分号,请将其加倍:"%%"。不知道关于坠机的事。不确定您是否可以像这样重用参数列表。
  • 该死!我误读了声明......安全功能崩溃怎么办?想法?
  • 如果您希望% 可靠地出现在输出中,请在格式字符串中使用%%。 %,c 字符串可以解释为带有未知修饰符(标志)的%c;这可能意味着最后的%s 正在读取垃圾,然后崩溃。不要依赖未定义的行为。
  • 即使你不重复使用它也会崩溃
  • @JonathanLeffler 至于你的第一条评论 - 当格式字符串是免费的运行时字符串时,你如何管理你的双百分比转义,例如由用户提供,不,我不想构建格式验证器 :) 你能详细说明你的第二条评论吗?

标签: c++ visual-studio-2012 printf


【解决方案1】:

这实际上是一个文档错误。 Format Specification Syntax 主题中应该很快就会出现更正(给它一两天)。缺少的信息是格式化函数的安全版本(带有尾随 _s 的函数)对格式化字符串进行额外的验证,并且它们拒绝后跟一个意外字符的百分比字符。然后,它们会在这种情况下调用无效参数处理程序,而非安全版本则不会。默认情况下,这将终止程序并调用 Dr. Watson 报告机制。

如果您尝试处理任意格式字符串问题,您可以通过调用_set_invalid_parameter_handler 自行设置无效参数处理程序,以捕获此类情况并防止崩溃。在 DEBUG 构建中,此格式字符串应导致无效的参数断言。 Security Features in the CRT 下的Parameter Validation 主题有更多信息。

【讨论】:

  • 其实我在 MS Connect 中填了一个 bug。让我们拭目以待,看看接下来会发生什么
猜你喜欢
  • 2016-07-16
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-05
  • 1970-01-01
  • 2011-04-11
相关资源
最近更新 更多