何时量化C sscanf函数中忽略的模式匹配?
可能总是量化(见下文)可能是一个好主意,但过度量化也可能会分散您的意图。在上述情况下,必须跳过单个分隔符char,量化肯定会有用。
是否有缓冲区溢出问题? ......也许在幕后?
,将没有造成代码崩溃。至于处理“幕后”问题,我尝试了大量的输入字符串。在我测试的C库中,没有内部缓冲区溢出。我尝试了Borland C++ 5.6.4附带的C库,发现我无法触发缓冲区溢出带有大量输入(超过4亿个字符)。
出人意料的是,Cppcheck不是完全错误 - 有一个便携性问题,但不同的一个:
#include <stdio.h>
#include <assert.h>
#include <sstream>
int traced_sscanf_set(const int count, const bool limited)
{
const char sep = '.';
printf("\n");
std::stringstream ss;
ss << "123" << std::string(count, sep) << "456";
std::string s = ss.str();
printf("string of size %d with %d '%c's in it\n", s.size(), count, sep);
std::stringstream fs;
fs << "%d%";
if (limited) {
fs << count;
}
fs << "*["<< sep << "]%d";
std::string fmt = fs.str();
printf("fmt: \"%s\"\n", fmt.c_str());
int a = 0;
int b = 0;
const sscanfResult = sscanf(s.c_str(), fmt.c_str(), &a, &b);
printf("sscanfResult=%d, a=%d, b=%d\n", sscanfResult, a, b);
return sscanfResult;
}
void test_sscanf()
{
assert(traced_sscanf_set(0x7fff, true)==2);
assert(traced_sscanf_set(0x7fff, false)==2);
assert(traced_sscanf_set(0x8000, true)==2);
assert(traced_sscanf_set(0x8000, false)==1);
}
我查库,内部限制消耗的输入(和跳过)至32767(2 -1)字符,如果format参数中没有明确指定的限制。
对于那些有兴趣谁,这里是跟踪输出:
string of size 32773 with 32767 '.'s in it
fmt: "%d%32767*[.]%d"
sscanfResult=2, a=123, b=456
string of size 32773 with 32767 '.'s in it
fmt: "%d%*[.]%d"
sscanfResult=2, a=123, b=456
string of size 32774 with 32768 '.'s in it
fmt: "%d%32768*[.]%d"
sscanfResult=2, a=123, b=456
string of size 32774 with 32768 '.'s in it
fmt: "%d%*[.]%d"
sscanfResult=1, a=123, b=0
所以,你有一个工作正确的格式,并且将其更改为别的东西(?可能不是正确的),以抑制假阳性,没有成功?看起来更像是一个“inline-suppressions”的工作:在这里搜索http://cppcheck.sourceforge.net/manual.pdf – Deduplicator 2014-10-27 12:39:40
指出的信息没有意义,因为'%* [,;。]'不使用缓冲区。 – BLUEPIXY 2014-10-27 12:42:52
@Deduplicator不,我试图改进模式以满足Cppcheck帮助检测的*实际*需求。 – Wolf 2014-10-27 12:42:55