我有一个数字列表,并希望为我的用户提供输入printf样式格式字符串的选项,以指定数字的输出方式。
如何根据参数列表validation用户提供的格式字符串? 格式错误的输入不应该使程序崩溃,我想避免任何格式字符串攻击。
我不关心validation是否仅处理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" );
在这个例子中,我知道我有四个花车。 我想允许任何只引用0到4个浮点数的格式。
因此isValidFormat()应允许以下格式字符串:
虽然应拒绝以下内容:
不要将用户输入的字符串传递给printf
。 printf
的格式字符串接口是为代码而设计的,不是为人类输入而设计的。 你会发现,如果你只是制作自己的格式字符串规范,你就可以自由地为用户设计它。
您是否有理由要对用户强制使用完全混淆的printf
格式字符串规范?
基本上你是在寻求帮助写一些东西来将格式字符串规范转换为printf
格式的字符串规范。 我建议你编写代码来从用户输入的字符串构造 printf
格式字符串。这样更安全,并为您提供更大的灵活性。 即使它是更多的代码,它也不那么hacky。
为你编写代码太多了,但我会给你一个很好的方法。 为您需要支持的每种类型设计有效格式说明符的正则表达式,然后使用它们为整个格式字符串构造一个更大的正则表达式,并查看它是否匹配。 例如,浮点( double
)参数的正则表达式看起来像:
%[+- 0#]*[0-9]*([.][0-9]+)?[aefgAEFG]
并且可以出现在格式说明符之间的文本文本的正则表达式如下所示:
([^%]|%%)*
确保在匹配格式字符串时,您坚持要求整个字符串与正则表达式匹配(在末尾使用^
和$
anchors)而不仅仅是子字符串。
没有标准(POSIX或C)方式,我知道没有提供此function的库。 因此,您必须自己编写或搜索比我更好的搜索。 请注意,您只需要检查对您有用的那些。
如果您有预定义的输入参数,请使用switch case。
switch ( ) { case accetable-value_1: Code to execute if == accetable-value_1 break; case accetable-value_2: Code to execute if == accetable-value_2 break; ... default: error: This is not a valid value, please enter a valid value break; }
在RRDtool中,我使用这样的代码来检查各种格式模式。
#include static int bad_format_check(const char *pattern, char *fmt) { GError *gerr = NULL; GRegex *re = g_regex_new(pattern, G_REGEX_EXTENDED, 0, &gerr); GMatchInfo *mi; if (gerr != NULL) { // rrd_set_error("cannot compile regular expression: %s (%s)", gerr->message,pattern); return 1; } int m = g_regex_match(re, fmt, 0, &mi); g_match_info_free (mi); g_regex_unref(re); if (!m) { // rrd_set_error("invalid format string '%s' (should match '%s')",fmt,pattern); return 1; } return 0; } #define SAFE_STRING "(?:[^%]+|%%)*" int bad_format_imginfo(char *fmt){ return bad_format_check("^" SAFE_STRING "%s" SAFE_STRING "%lu" SAFE_STRING "%lu" SAFE_STRING "$",fmt); } #define FLOAT_STRING "%[-+ 0#]?[0-9]*(?:[.][0-9]+)?l[eEfF]" int bad_format_axis(char *fmt){ return bad_format_check("^" SAFE_STRING FLOAT_STRING SAFE_STRING "$",fmt); } int bad_format_print(char *fmt){ return bad_format_check("^" SAFE_STRING FLOAT_STRING SAFE_STRING "%s" SAFE_STRING "$",fmt); }
最简单的方法是使用sprintf(而不是printf)来计算字符串中的结果,并测试sprintf返回的错误代码。
以上就是c/c++开发分享如何根据参数列表validation用户提供的printf格式字符串?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/541791.html