diff --git a/lib/library.cpp b/lib/library.cpp index ae780f0ffe05..62e94876859d 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -94,13 +94,7 @@ Library::Error Library::load(const char exename[], const char path[], bool debug tinyxml2::XMLDocument doc; if (debug) std::cout << "looking for library '" + std::string(path) + "'" << std::endl; - tinyxml2::XMLError error = doc.LoadFile(path); - // TODO: do not ignore read errors - if (error == tinyxml2::XML_ERROR_FILE_READ_ERROR && Path::getFilenameExtension(path).empty()) - { - // Reading file failed, try again... - error = tinyxml2::XML_ERROR_FILE_NOT_FOUND; - } + tinyxml2::XMLError error = xml_LoadFile(doc, path); if (error == tinyxml2::XML_ERROR_FILE_NOT_FOUND) { // failed to open file.. is there no extension? std::string fullfilename(path); @@ -108,7 +102,7 @@ Library::Error Library::load(const char exename[], const char path[], bool debug fullfilename += ".cfg"; if (debug) std::cout << "looking for library '" + std::string(fullfilename) + "'" << std::endl; - error = doc.LoadFile(fullfilename.c_str()); + error = xml_LoadFile(doc, fullfilename.c_str()); if (error != tinyxml2::XML_ERROR_FILE_NOT_FOUND) absolute_path = Path::getAbsoluteFilePath(fullfilename); } @@ -134,7 +128,7 @@ Library::Error Library::load(const char exename[], const char path[], bool debug const std::string filename(cfgfolder + sep + fullfilename); if (debug) std::cout << "looking for library '" + std::string(filename) + "'" << std::endl; - error = doc.LoadFile(filename.c_str()); + error = xml_LoadFile(doc, filename.c_str()); if (error != tinyxml2::XML_ERROR_FILE_NOT_FOUND) absolute_path = Path::getAbsoluteFilePath(filename); } diff --git a/lib/xml.h b/lib/xml.h index c8c258d973a9..8c720466201b 100644 --- a/lib/xml.h +++ b/lib/xml.h @@ -20,6 +20,7 @@ #define xmlH #include "config.h" +#include "path.h" SUPPRESS_WARNING_CLANG_PUSH("-Wzero-as-null-pointer-constant") SUPPRESS_WARNING_CLANG_PUSH("-Wsuggest-destructor-override") @@ -31,4 +32,12 @@ SUPPRESS_WARNING_CLANG_POP SUPPRESS_WARNING_CLANG_POP SUPPRESS_WARNING_CLANG_POP +inline static tinyxml2::XMLError xml_LoadFile(tinyxml2::XMLDocument& doc, const char* filename) +{ + // tinyxml2 will fail with a misleading XML_ERROR_FILE_READ_ERROR when you try to load a directory as a XML file + if (Path::isDirectory(filename)) + return tinyxml2::XMLError::XML_ERROR_FILE_NOT_FOUND; + return doc.LoadFile(filename); +} + #endif // xmlH diff --git a/test/cli/other_test.py b/test/cli/other_test.py index 95199c15fc59..3502d3e0a361 100644 --- a/test/cli/other_test.py +++ b/test/cli/other_test.py @@ -1614,3 +1614,30 @@ def test_lib_lookup_absolute_notfound(tmpdir): "library not found: '{}'".format(cfg_file), "cppcheck: Failed to load library configuration file '{}'. File not found".format(cfg_file) ] + + +def test_lib_lookup_nofile(tmpdir): + test_file = os.path.join(tmpdir, 'test.c') + with open(test_file, 'wt'): + pass + + # make sure we do not produce an error when the attempted lookup path is a directory and not a file + gtk_dir = os.path.join(tmpdir, 'gtk') + os.mkdir(gtk_dir) + gtk_cfg_dir = os.path.join(tmpdir, 'gtk.cfg') + os.mkdir(gtk_cfg_dir) + + exitcode, stdout, _, exe = cppcheck_ex(['--library=gtk', '--debug-lookup', test_file], cwd=tmpdir) + exepath = os.path.dirname(exe) + if sys.platform == 'win32': + exepath = exepath.replace('\\', '/') + assert exitcode == 0, stdout + lines = __remove_std_lookup_log(stdout.splitlines(), exepath) + assert lines == [ + "looking for library 'gtk'", + "looking for library 'gtk.cfg'", + "looking for library '{}/gtk.cfg'".format(exepath), + "looking for library '{}/../cfg/gtk.cfg'".format(exepath), + "looking for library '{}/cfg/gtk.cfg'".format(exepath), + 'Checking {} ...'.format(test_file) + ]