-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Fix #1473: warn when fclose() is used as a while loop condition #8444
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
22917dd
8800ee5
2f52148
c2c3e53
28f2247
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -245,6 +245,35 @@ void CheckIO::checkFileUsage() | |
| } else if (tok->str() == "fclose") { | ||
| fileTok = tok->tokAt(2); | ||
| operation = Filepointer::Operation::CLOSE; | ||
|
|
||
| // #1473 Check if fclose is in a while loop condition | ||
| if (fileTok && fileTok->isVariable()) { | ||
| const Token* tmp = tok->astParent(); | ||
| const Token* loopTok = nullptr; | ||
| while (tmp) { | ||
| if (Token::simpleMatch(tmp->previous(), "while (")) { | ||
| loopTok = tmp->previous(); | ||
| break; | ||
| } | ||
| tmp = tmp->astParent(); | ||
| } | ||
| if (loopTok) { | ||
| const Token* bodyEnd = nullptr; | ||
| const Token* bodyStart = nullptr; | ||
|
|
||
| if (Token::simpleMatch(loopTok->previous(), "}") && Token::simpleMatch(loopTok->linkAt(-1)->previous(), "do")) { // Handle do-while loops | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would spontanously prefer that we look at the scope type. |
||
| bodyEnd = loopTok->previous(); | ||
| bodyStart = bodyEnd->link(); | ||
| } else { | ||
| bodyStart = loopTok->linkAt(1)->next(); | ||
| bodyEnd = bodyStart->link(); | ||
| } | ||
|
|
||
| // Do not trigger a warning if the loop always exits or if the file is opened again in the loop. | ||
| if (!isReturnScope(bodyEnd, mSettings->library) && Token::findmatch(bodyStart, "%var% =", bodyEnd, fileTok->varId()) == nullptr) | ||
| useClosedFileError(tok); | ||
| } | ||
| } | ||
| } else if (whitelist.find(tok->str()) != whitelist.end()) { | ||
| fileTok = tok->tokAt(2); | ||
| if ((tok->str() == "ungetc" || tok->str() == "ungetwc") && fileTok) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -544,7 +544,29 @@ class TestIO : public TestFixture { | |
| " FILE *a = fopen(\"aa\", \"r\");\n" | ||
| " while (fclose(a)) {}\n" | ||
| "}"); | ||
| TODO_ASSERT_EQUALS("[test.cpp:3:5]: (error) Used file that is not opened. [useClosedFile]\n", "", errout_str()); | ||
| ASSERT_EQUALS("[test.cpp:3:12]: (error) Used file that is not opened. [useClosedFile]\n", errout_str()); | ||
|
danmar marked this conversation as resolved.
|
||
|
|
||
| check("void foo() {\n" | ||
| " FILE *a = fopen(\"aa\", \"r\");\n" | ||
| " while (fclose(a)) {\n" | ||
| " break;\n" | ||
| " }\n" | ||
| "}"); | ||
| ASSERT_EQUALS("", errout_str()); | ||
|
|
||
| check("void foo() {\n" | ||
| " FILE *a = fopen(\"aa\", \"r\");\n" | ||
| " while (fclose(a)) {\n" | ||
| " a = fopen(\"aa\", \"r\");\n" | ||
| " }\n" | ||
| "}"); | ||
| ASSERT_EQUALS("", errout_str()); | ||
|
|
||
| check("void foo() {\n" | ||
| " FILE *a = fopen(\"aa\", \"r\");\n" | ||
| " do {} while (fclose(a));\n" | ||
| "}"); | ||
| ASSERT_EQUALS("[test.cpp:3:18]: (error) Used file that is not opened. [useClosedFile]\n", errout_str()); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure about the message. The file is opened but not in the loop. The first loop iteration it works fine. I don't know how I would like to phraze it... here is a rough idea:
Feel free to suggest something better. |
||
|
|
||
| // #6823 | ||
| check("void foo() {\n" | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we use
Token::astTop()here instead of the loop?