c++ - 使用 std::ifstream 进行输入验证

标签 c++ validation ifstream coverity

我正在使用类似的方式读取文件:

    std::ifstream is( file_name );
    std::string s;

    if( !is.good() ) {
        std::cout << "error opening file: " << file_name << std::endl;
    } else {
        while( !is.eof() ) {
            s.clear();
            is >> s;
            if (s.empty())  continue;
            if (s.size() < 1 || s.size()>0x7FFFFFFF ) {
               std::cout << "implausible data" << std::endl;
               continue;
            }
            char *ss = new char[ s.size() + 1 ]; // COVERITY bails out
            // do something with the data
            delete[]ss;
        }
    }

当我用静态代码分析工具分析上面的代码时coverity (免费版),标有COVERITY bails out 的行抛出错误:

 Untrusted value as argument (TAINTED_SCALAR)
   tainted_data: Passing tainted variable > s.size() + 1UL to a tainted sink.

我知道我不能相信从文件中读取的任何数据,但我不知道在这个阶段如何验证数据。 我已经在检查 s.size() 是否在错误行上方的 if 子句中的合理(尽管相当大)范围内。

那么为什么 Coverity 会向我发出警告?

此外,我还应该应用哪些其他输入验证策略?

最佳答案

在接下来的部分

if (s.empty())
  continue;
if (s.size() < 1 || s.size() > 0x7FFFFFFF)
  {
    std::cout << "implausible data" << std::endl;
    continue;
  }
char * ss = new char[s.size() + 1];

验证逻辑依赖于 s.size() 每次调用时都会返回相同值这一重要事实。虽然在这种情况下,我们(人类)知道这是真的,但静态代码分析器可能无法意识到这一点。

作为解决方法,尝试引入一个局部变量并使用它。

const std::size_t length = s.size();
if (!length)
  continue;
if (length < 1 || length > 0x7FFFFFFF)
  {
    std::cout << "implausible data" << std::endl;
    continue;
  }
char * ss = new char[length + 1];

在这里,分析器很容易判断length 不会改变它的值。

围绕静态分析器工具的局限性编写此类代码是否值得存在争议。 GNU Coding Standards阻止它。

Don’t make the program ugly just to placate static analysis tools such as lint, clang, and GCC with extra warnings options such as -Wconversion and -Wundef. These tools can help find bugs and unclear code, but they can also generate so many false alarms that it hurts readability to silence them with unnecessary casts, wrappers, and other complications. For example, please don’t insert casts to void or calls to do-nothing functions merely to pacify a lint checker.

就我个人而言,只要代码的可读性不会受到太大影响,我不会觉得太糟糕。在极端情况下,添加一条注释来解释为什么事情会以这种方式完成可能是个好主意。

关于c++ - 使用 std::ifstream 进行输入验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27258993/

相关文章:

c++ - '�' 而不是文件中的普通文本

c++ - 模板化父类(super class)链接问题

javascript - 一步一步的 Angular JS 验证不起作用

c++ - 在函数中返回 ifstream

javascript - 多个 IP 的正则表达式,以逗号分隔,带或不带子网

java - 使用 Spring 3.1 在 JSP 页面中不显示表单验证错误

C++读取配置二进制文件

c++ - 私有(private)析构函数友元函数

c++ - Eigen 没有匹配函数调用.dot()?

c++ - 在 MFC 中更改 listcntrl 的方向时出错