何时量化 C sscanf 函数中忽略的模式匹配?
总是量化可能是个好主意(见下文),但过度量化也可能会分散您的意图。在上述情况下,必须跳过单个分隔符字符,量化肯定是有用的。
缓冲区溢出是否可能存在问题?...也许在幕后?
您的代码不会导致崩溃。至于处理“幕后”问题,我尝试了大输入字符串。在我测试的 C 库中,没有内部缓冲区溢出。我尝试了 Borland C++ 5.6.4 附带的 C lib,发现我无法触发大输入(超过 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 15 -1) 个字符。
对于那些感兴趣的人,这里是跟踪输出:
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