Menu ▾ ▴

QFile::exists result reused across an unknown call

Long Huang
6 days ago
5 days ago
  • Long Huang

    Long Huang - 6 days ago

    cfg/qt.cfg marks QFile::exists as <pure/>. When the argument is a local const QString, cppcheck reuses the first call's result after a call to an unknown function, and then reports a later identical call as always true. But QFile::exists reads filesystem state, which any unknown call (or another
    process) can change, so the second result is not known.

    Either QFile::exists (and probably QFileInfo::exists/QDir::exists) should not be <pure/>, or value flow should drop a pure call's known result after a call to an unknown function.

    Reproduction

    Save as pure-exists.cpp:

    #include <QFile>
    #include <QString>
    
    void RemoveFile(const QString& path);
    
    void Check()
    {
       const QString path("x");
       if(!QFile::exists(path)) throw false;
       RemoveFile(path);
       if(QFile::exists(path))
       {
          throw 1;
       }
    }
    

    Actual:

    pure-exists.cpp:11:knownConditionTrueFalse:Condition 'QFile::exists(path)' is always true
    

    Expected:

    No warning. RemoveFile is unknown and may delete the file, so the second QFile::exists(path) can return false.

    Note:

    • With path as a const QString& function parameter instead of a local, no warning is emitted.
    • In googletest code the first call is usually ASSERT_TRUE(QFile::exists(p)). googletest.cfg expands it to {if (!(cond)) throw false;}, which produces the same pattern. A following retry loop such asfor(...; retries < 10 && !deleted; ...) { QTest::qWait(10); deleted = !QFile::exists(p); } is then reported as Condition '!deleted' is always true.
     
  • CHR

    CHR - 5 days ago

    Thanks for reporting, ticket is here: https://trac.cppcheck.net/ticket/15173

     

Log in to post a comment.