Skip to content

Commit 14d63ab

Browse files
committed
1 parent 922bb96 commit 14d63ab

3 files changed

Lines changed: 37 additions & 0 deletions

File tree

lib/checkio.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ namespace {
5353
// CVE ID used:
5454
static const CWE CWE119(119U); // Improper Restriction of Operations within the Bounds of a Memory Buffer
5555
static const CWE CWE398(398U); // Indicator of Poor Code Quality
56+
static const CWE CWE474(474U); // Use of Function with Inconsistent Implementations
5657
static const CWE CWE664(664U); // Improper Control of a Resource Through its Lifetime
5758
static const CWE CWE685(685U); // Function Call With Incorrect Number of Arguments
5859
static const CWE CWE686(686U); // Function Call With Incorrect Argument Type
@@ -116,6 +117,8 @@ namespace {
116117
nonneg int op_indent{};
117118
enum class AppendMode : std::uint8_t { UNKNOWN_AM, APPEND, APPEND_EX };
118119
AppendMode append_mode = AppendMode::UNKNOWN_AM;
120+
enum class ReadMode : std::uint8_t { READ_TEXT, READ_BIN };
121+
ReadMode read_mode = ReadMode::READ_BIN;
119122
std::string filename;
120123
explicit Filepointer(OpenMode mode_ = OpenMode::UNKNOWN_OM)
121124
: mode(mode_) {}
@@ -188,6 +191,7 @@ void CheckIO::checkFileUsage()
188191
}
189192
} else if (Token::Match(tok, "%name% (") && tok->previous() && (!tok->previous()->isName() || Token::Match(tok->previous(), "return|throw"))) {
190193
std::string mode;
194+
bool isftell = false;
191195
const Token* fileTok = nullptr;
192196
const Token* fileNameTok = nullptr;
193197
Filepointer::Operation operation = Filepointer::Operation::NONE;
@@ -249,6 +253,9 @@ void CheckIO::checkFileUsage()
249253
fileTok = tok->tokAt(2);
250254
if ((tok->str() == "ungetc" || tok->str() == "ungetwc") && fileTok)
251255
fileTok = fileTok->nextArgument();
256+
else if (tok->str() == "ftell") {
257+
isftell = true;
258+
}
252259
operation = Filepointer::Operation::UNIMPORTANT;
253260
} else if (!Token::Match(tok, "if|for|while|catch|switch") && !mSettings->library.isFunctionConst(tok->str(), true)) {
254261
const Token* const end2 = tok->linkAt(1);
@@ -304,10 +311,15 @@ void CheckIO::checkFileUsage()
304311
f.append_mode = Filepointer::AppendMode::APPEND_EX;
305312
else
306313
f.append_mode = Filepointer::AppendMode::APPEND;
314+
}
315+
else if (mode.find('r') != std::string::npos &&
316+
mode.find('t') != std::string::npos) {
317+
f.read_mode = Filepointer::ReadMode::READ_TEXT;
307318
} else
308319
f.append_mode = Filepointer::AppendMode::UNKNOWN_AM;
309320
f.mode_indent = indent;
310321
break;
322+
311323
case Filepointer::Operation::POSITIONING:
312324
if (f.mode == OpenMode::CLOSED)
313325
useClosedFileError(tok);
@@ -340,6 +352,8 @@ void CheckIO::checkFileUsage()
340352
case Filepointer::Operation::UNIMPORTANT:
341353
if (f.mode == OpenMode::CLOSED)
342354
useClosedFileError(tok);
355+
if (isftell && windows && f.read_mode == Filepointer::ReadMode::READ_TEXT && printPortability)
356+
ftellFileError(tok);
343357
break;
344358
case Filepointer::Operation::UNKNOWN_OP:
345359
f.mode = OpenMode::UNKNOWN_OM;
@@ -398,6 +412,12 @@ void CheckIO::seekOnAppendedFileError(const Token *tok)
398412
"seekOnAppendedFile", "Repositioning operation performed on a file opened in append mode has no effect.", CWE398, Certainty::normal);
399413
}
400414

415+
void CheckIO::ftellFileError(const Token *tok)
416+
{
417+
reportError(tok, Severity::portability,
418+
"ftellTextModeFile", "For a text stream, its file position indicator contains unspecified information. See Section 7.21.9.4p2 of the C11 standard", CWE474, Certainty::normal);
419+
}
420+
401421
void CheckIO::incompatibleFileOpenError(const Token *tok, const std::string &filename)
402422
{
403423
reportError(tok, Severity::warning,

lib/checkio.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class CPPCHECKLIB CheckIO : public Check {
106106
void writeReadOnlyFileError(const Token *tok);
107107
void useClosedFileError(const Token *tok);
108108
void seekOnAppendedFileError(const Token *tok);
109+
void ftellFileError(const Token *tok);
109110
void incompatibleFileOpenError(const Token *tok, const std::string &filename);
110111
void invalidScanfError(const Token *tok);
111112
void wrongPrintfScanfArgumentsError(const Token* tok,

test/testio.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class TestIO : public TestFixture {
4444
TEST_CASE(fileIOwithoutPositioning);
4545
TEST_CASE(seekOnAppendedFile);
4646
TEST_CASE(fflushOnInputStream);
47+
TEST_CASE(ftellCompatibility);
4748
TEST_CASE(incompatibleFileOpen);
4849

4950
TEST_CASE(testScanf1); // Scanf without field limiters
@@ -704,6 +705,21 @@ class TestIO : public TestFixture {
704705
ASSERT_EQUALS("", errout_str()); // #6566
705706
}
706707

708+
void ftellCompatibility() {
709+
710+
check("void foo() {\n"
711+
" FILE *f = fopen(\"\", \"rt\");\n"
712+
" if (f)\n"
713+
" {\n"
714+
" fseek(f, 0, SEEK_END);\n"
715+
" (void)ftell(f);\n"
716+
" fclose(f);\n"
717+
" }\n"
718+
"}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A, $.portability = true));
719+
ASSERT_EQUALS("[test.cpp:6:16]: (portability) For a text stream, its file position indicator contains unspecified information. See Section 7.21.9.4p2 of the C11 standard [ftellTextModeFile]\n", errout_str());
720+
}
721+
722+
707723
void fflushOnInputStream() {
708724
check("void foo()\n"
709725
"{\n"

0 commit comments

Comments
 (0)