Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/selfcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ jobs:

- name: Self check (unusedFunction / no test / no gui)
run: |
supprs="--suppress=unusedFunction:lib/errorlogger.h:197 --suppress=unusedFunction:lib/importproject.cpp:1671 --suppress=unusedFunction:lib/importproject.cpp:1695"
supprs="--suppress=unusedFunction:lib/errorlogger.h:197 --suppress=unusedFunction:lib/importproject.cpp:1695 --suppress=unusedFunction:lib/importproject.cpp:1719"
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr $supprs
env:
DISABLE_VALUEFLOW: 1
Expand Down
46 changes: 35 additions & 11 deletions lib/importproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,27 +529,51 @@ bool ImportProject::importSlnx(const std::string& filename, const std::vector<st
return false;
}

if (std::strcmp(rootnode->Name(), "Solution") != 0) {
errors.emplace_back("Invalid Visual Studio solution file format");
return false;
}

std::map<std::string, std::string, cppcheck::stricmp> variables;
variables["SolutionDir"] = Path::simplifyPath(Path::getPathFromFilename(filename));

bool found = false;
std::vector<SharedItemsProject> sharedItemsProjects;

auto processProject = [&](const tinyxml2::XMLElement* projectNode) {
const char* pathAttribute = projectNode->Attribute("Path");
if (pathAttribute == nullptr)
return true;

std::string vcxproj(pathAttribute);
vcxproj = Path::toNativeSeparators(std::move(vcxproj));

if (Path::getFilenameExtensionInLowerCase(vcxproj) != ".vcxproj")
return true; // skip other project types

if (!Path::isAbsolute(vcxproj))
vcxproj = variables["SolutionDir"] + vcxproj;

vcxproj = Path::fromNativeSeparators(std::move(vcxproj));
if (!importVcxproj(vcxproj, variables, "", fileFilters, sharedItemsProjects)) {
errors.emplace_back("failed to load '" + vcxproj + "' from Visual Studio solution");
return false;
}
found = true;
return true;
};

for (const tinyxml2::XMLElement* node = rootnode->FirstChildElement(); node; node = node->NextSiblingElement()) {
const char* name = node->Name();
if (std::strcmp(name, "Project") == 0) {
const char* labelAttribute = node->Attribute("Path");
if (labelAttribute) {
std::string vcxproj(labelAttribute);
vcxproj = Path::toNativeSeparators(std::move(vcxproj));
if (!Path::isAbsolute(vcxproj))
vcxproj = variables["SolutionDir"] + vcxproj;
vcxproj = Path::fromNativeSeparators(std::move(vcxproj));
if (!importVcxproj(vcxproj, variables, "", fileFilters, sharedItemsProjects)) {
errors.emplace_back("failed to load '" + vcxproj + "' from Visual Studio solution");
return false;
if (!processProject(node))
return false;
} else if (std::strcmp(name, "Folder") == 0) {
for (const tinyxml2::XMLElement* childNode = node->FirstChildElement(); childNode; childNode = childNode->NextSiblingElement()) {
if (std::strcmp(childNode->Name(), "Project") == 0) {
if (!processProject(childNode))
return false;
}
found = true;
}
}
}
Expand Down
20 changes: 20 additions & 0 deletions test/cli/project_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,26 @@ def test_slnx_project_file_not_found(tmpdir):
__test_project_error(tmpdir, "slnx", content, expected)


def test_slnx_project_file_in_folder_not_found(tmpdir):
content = '<?xml version="1.0" encoding="UTF-8"?>\r\n' \
"<Solution>\r\n" \
" <Configurations>\r\n" \
' <Platform Name="x64" />\r\n' \
' <Platform Name="x86" />\r\n' \
" </Configurations>\r\n" \
' <Folder Name="/common/">\r\n' \
' <Project Path="common/test.vcxproj" />\r\n' \
' </Folder>\r\n' \
"</Solution>\r\n"

expected = "Visual Studio project file is not a valid XML - XML_ERROR_FILE_NOT_FOUND\n" \
"cppcheck: error: failed to load '{}' from Visual Studio solution".format(os.path.join(tmpdir, "common/test.vcxproj"))
if sys.platform == "win32":
expected = expected.replace('\\', '/')

__test_project_error(tmpdir, "slnx", content, expected)


def test_vcxproj_no_xml_root(tmpdir):
content = '<?xml version="1.0" encoding="utf-8"?>'

Expand Down
Loading