|
48 | 48 | // CVE ID used: |
49 | 49 | static const CWE CWE119(119U); // Improper Restriction of Operations within the Bounds of a Memory Buffer |
50 | 50 | static const CWE CWE398(398U); // Indicator of Poor Code Quality |
| 51 | +static const CWE CWE474(474U); // Use of Function with Inconsistent Implementations |
51 | 52 | static const CWE CWE664(664U); // Improper Control of a Resource Through its Lifetime |
52 | 53 | static const CWE CWE685(685U); // Function Call With Incorrect Number of Arguments |
53 | 54 | static const CWE CWE686(686U); // Function Call With Incorrect Argument Type |
@@ -111,6 +112,8 @@ namespace { |
111 | 112 | nonneg int op_indent{}; |
112 | 113 | enum class AppendMode : std::uint8_t { UNKNOWN_AM, APPEND, APPEND_EX }; |
113 | 114 | AppendMode append_mode = AppendMode::UNKNOWN_AM; |
| 115 | + enum class ReadMode : std::uint8_t { READ_TEXT, READ_BIN }; |
| 116 | + ReadMode read_mode = ReadMode::READ_BIN; |
114 | 117 | std::string filename; |
115 | 118 | explicit Filepointer(OpenMode mode_ = OpenMode::UNKNOWN_OM) |
116 | 119 | : mode(mode_) {} |
@@ -183,6 +186,7 @@ void CheckIO::checkFileUsage() |
183 | 186 | } |
184 | 187 | } else if (Token::Match(tok, "%name% (") && tok->previous() && (!tok->previous()->isName() || Token::Match(tok->previous(), "return|throw"))) { |
185 | 188 | std::string mode; |
| 189 | + bool isftell = false; |
186 | 190 | const Token* fileTok = nullptr; |
187 | 191 | const Token* fileNameTok = nullptr; |
188 | 192 | Filepointer::Operation operation = Filepointer::Operation::NONE; |
@@ -266,6 +270,9 @@ void CheckIO::checkFileUsage() |
266 | 270 | fileTok = tok->tokAt(2); |
267 | 271 | if ((tok->str() == "ungetc" || tok->str() == "ungetwc") && fileTok) |
268 | 272 | fileTok = fileTok->nextArgument(); |
| 273 | + else if (tok->str() == "ftell") { |
| 274 | + isftell = true; |
| 275 | + } |
269 | 276 | operation = Filepointer::Operation::UNIMPORTANT; |
270 | 277 | } else if (!Token::Match(tok, "if|for|while|catch|switch") && !mSettings->library.isFunctionConst(tok->str(), true)) { |
271 | 278 | const Token* const end2 = tok->linkAt(1); |
@@ -321,10 +328,15 @@ void CheckIO::checkFileUsage() |
321 | 328 | f.append_mode = Filepointer::AppendMode::APPEND_EX; |
322 | 329 | else |
323 | 330 | f.append_mode = Filepointer::AppendMode::APPEND; |
| 331 | + } |
| 332 | + else if (mode.find('r') != std::string::npos && |
| 333 | + mode.find('t') != std::string::npos) { |
| 334 | + f.read_mode = Filepointer::ReadMode::READ_TEXT; |
324 | 335 | } else |
325 | 336 | f.append_mode = Filepointer::AppendMode::UNKNOWN_AM; |
326 | 337 | f.mode_indent = indent; |
327 | 338 | break; |
| 339 | + |
328 | 340 | case Filepointer::Operation::POSITIONING: |
329 | 341 | if (f.mode == OpenMode::CLOSED) |
330 | 342 | useClosedFileError(tok); |
@@ -357,6 +369,8 @@ void CheckIO::checkFileUsage() |
357 | 369 | case Filepointer::Operation::UNIMPORTANT: |
358 | 370 | if (f.mode == OpenMode::CLOSED) |
359 | 371 | useClosedFileError(tok); |
| 372 | + if (isftell && f.read_mode == Filepointer::ReadMode::READ_TEXT && printPortability) |
| 373 | + ftellFileError(tok); |
360 | 374 | break; |
361 | 375 | case Filepointer::Operation::UNKNOWN_OP: |
362 | 376 | f.mode = OpenMode::UNKNOWN_OM; |
@@ -424,6 +438,12 @@ void CheckIO::seekOnAppendedFileError(const Token *tok) |
424 | 438 | "seekOnAppendedFile", "Repositioning operation performed on a file opened in append mode has no effect.", CWE398, Certainty::normal); |
425 | 439 | } |
426 | 440 |
|
| 441 | +void CheckIO::ftellFileError(const Token *tok) |
| 442 | +{ |
| 443 | + reportError(tok, Severity::portability, |
| 444 | + "ftellTextModeFile", "ftell() result is unspecified when file is opened in mode \"t\"", CWE474, Certainty::normal); |
| 445 | +} |
| 446 | + |
427 | 447 | void CheckIO::incompatibleFileOpenError(const Token *tok, const std::string &filename) |
428 | 448 | { |
429 | 449 | reportError(tok, Severity::warning, |
|
0 commit comments