如何根据参数列表验证用户提供的 printf 格式字符串?
我有一个数字列表,希望为我的用户提供输入 printf 样式格式字符串的选项,以指定如何输出数字。
如何根据我的参数列表验证用户提供的格式字符串?格式错误的输入不应使程序崩溃,并且我想避免任何格式字符串攻击。
我不关心验证是否只处理 POSIX 中指定的格式选项或编译器特定的超集。是否有任何库调用可以执行此操作,或者我必须自己编写它?
澄清: 我需要的是这样的:
float var1, var2, var3, var4;
// var1 .. var2 are given by the program
const char * userSupplied = getFormatStringFromUser();
if( isValidFormat( userSupplied, "float", "float", "float", "float" ) )
printf( userSupplied, var1, var2, var3, var4 );
else
printf( "The format you gave was invalid!\n" );
在这个例子中,我知道我有四个浮点数。 我想允许任何仅引用零到四个浮点数的格式。
因此 isValidFormat() 应该允许以下格式字符串:
- "%f %g %e %.1f"
- "Foo is %g, Bar is %g"
- "Nothing"
而以下应该是被拒绝:
- “%s”
- “Foo 是 %d”
I have a list of numbers and want to give my users the option to enter a printf-style format string to specify how the numbers should be output.
How can I validate the user-supplied format string against my parameter list? Malformed input should not crash the program, and I want to avoid any format string attacks.
I do not care if the validation handles just the format options specified in POSIX or the compiler specific superset. Is there any library call to do this, or will I have to write it myself?
Clarification:
What I need is something like this:
float var1, var2, var3, var4;
// var1 .. var2 are given by the program
const char * userSupplied = getFormatStringFromUser();
if( isValidFormat( userSupplied, "float", "float", "float", "float" ) )
printf( userSupplied, var1, var2, var3, var4 );
else
printf( "The format you gave was invalid!\n" );
In this example, I know that I have four floats.
I want to allow any format that only references zero to four floats.
So the following format strings should be allowed by isValidFormat():
- "%f %g %e %.1f"
- "Foo is %g, Bar is %g"
- "Nothing"
While the following should be rejected:
- "%s"
- "Foo is %d"
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
不要将用户输入的字符串传递到
printf
中。printf
的格式字符串接口是为代码设计的,而不是为人类输入设计的。您会发现,如果您只是制定自己的格式字符串规范,您将可以自由地针对用户进行设计。您是否有理由将完全混淆的
printf
格式字符串规范强加给您的用户?本质上,您是在请求帮助编写一些内容来将格式字符串规范转换为
printf
格式字符串规范。相反,我建议您编写代码来根据用户输入的内容构造printf
格式字符串。这样更安全,并为您提供更大的灵活性。即使代码更多,也不会那么麻烦。Do not pass user-inputted strings into
printf
.printf
's format string interface is designed for code, not for human input. You will find that if you just make your own format string spec, you will have the freedom to design it towards the users.Is there a reason you want to impose the completely obfuscated
printf
format string spec on your users?Essentially you are asking help writing something to convert your format string spec to the
printf
format string spec. I would instead suggest you write code to construct theprintf
format string from the one the user types in. This is safer, and gives you more flexibility. Even if it's more code, it's less hacky.为您编写代码的工作量太大,但我会给您一个很好的方法。为需要支持的每种类型的有效格式说明符设计正则表达式,然后使用它们为整个格式字符串构造更大的正则表达式并查看它是否匹配。例如,浮点 (
double
) 参数的正则表达式将类似于:可能出现在格式说明符之间任何位置的文字文本的正则表达式将类似于:
确保匹配您坚持的格式字符串时整个字符串与正则表达式匹配(在末尾使用
^
和$
锚点),而不仅仅是子字符串。Writing the code for you is too much work, but I'll give you a good approach. Design regular expressions for the valid format specifiers for each type you need to support, then use them to construct a larger regular expression for the entire format string and see if it matches. For example, a floating point (
double
) argument's regex would look something like:And a regex for literal text that could appear anywhere between format specifiers would look something like:
Make sure when matching the format string you insist that the whole string match the regex (use
^
and$
anchors at the ends) and not just a substring.没有标准(POSIX 或 C)方式,而且我知道没有库提供这种方式。所以你必须自己写或者做比我更好的搜索。请注意,您必须仅检查那些对您有用的内容。
There is no standard (POSIX or C) way and I know of no library providing this. So you will have to write your own or do a better search than me. Note that you have to check only those which are useful for your.
如果您有预定义的输入参数,请使用 switch case。
If you have pre-defined input parameters, use switch case.
在 RRDtool 中,我使用这样的代码来检查各种格式模式。
In RRDtool I use code like this to check various format patterns.
最简单的方法是使用 sprintf(而不是 printf)来计算字符串中的结果并测试 sprintf 返回的错误代码。
The easiest would be to use sprintf (instead of printf) to compute the result in a string and the test the error code returned by sprintf.