diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 17121edc7..f1d4bd935 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -128,21 +128,21 @@ void CheckIO::checkFileUsage() i->second.lastOperation = Filepointer::UNKNOWN_OP; } } - } else if (tok->varId() && Token::Match(tok, "%var% =") && (tok->strAt(2) != "fopen" && tok->strAt(2) != "tmpfile")) { + } else if (tok->varId() && Token::Match(tok, "%var% =") && (tok->strAt(2) != "fopen" && tok->strAt(2) != "freopen" && tok->strAt(2) != "tmpfile")) { std::map::iterator i = filepointers.find(tok->varId()); if (i != filepointers.end()) { i->second.mode = UNKNOWN; i->second.lastOperation = Filepointer::UNKNOWN_OP; } - } else if (Token::Match(tok, "%var% (")) { + } else if (Token::Match(tok, "%var% (") && tok->previous() && (!tok->previous()->isName() || Token::Match(tok->previous(), "return|throw"))) { std::string mode; const Token* fileTok = 0; Filepointer::Operation operation = Filepointer::NONE; - if (tok->str() == "fopen" || tok->str() == "freopen" || tok->str() == "tmpfile") { + if ((tok->str() == "fopen" || tok->str() == "freopen" || tok->str() == "tmpfile") && tok->strAt(-1) == "=") { if (tok->str() != "tmpfile") { const Token* modeTok = tok->tokAt(2)->nextArgument(); - if (modeTok) + if (modeTok && modeTok->type() == Token::eString) mode = modeTok->strValue(); } else mode = "wb+"; diff --git a/test/testio.cpp b/test/testio.cpp index 0a0b0bcd1..6ef863fd9 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -193,13 +193,14 @@ private: "}"); ASSERT_EQUALS("[test.cpp:3]: (error) Write operation on a file that was only opened for reading.\n", errout.str()); + // Crash tests check("void foo(FILE*& f) {\n" - " f = tmpfile();\n" // tmpfile opens as wb+ + " f = fopen(name, mode);\n" // No assertion failure (#3830) " fwrite(buffer, 5, 6, f);\n" - " rewind(f);\n" - " fread(buffer, 5, 6, f);\n" "}"); ASSERT_EQUALS("", errout.str()); + + check("void fopen(std::string const &filepath, std::string const &mode);"); // #3832 } void wrongMode_complex() {