Skip to content

Commit 2b73c45

Browse files
committed
Includes of system headers are never relative to the source file
Sometimes, #include directives with angle-bracket filespec delimiters are used (or abused) to defeat the preprocessor's behaviour where it tries to find a header file at a path relative to the file containing the directive. Without this fix, any non-root header file, foo/bar.h, which does #include <bar.h> while intending to include a root-level header file, will instead enter an infinite inclusion loop, terminating when the inclusion stack overflows with a "#include nested too deeply" error.
1 parent 45db93b commit 2b73c45

File tree

2 files changed

+20
-3
lines changed

2 files changed

+20
-3
lines changed

simplecpp.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2894,8 +2894,8 @@ static std::string getFileName(const std::map<std::string, simplecpp::TokenList
28942894
return s;
28952895
}
28962896

2897-
if (filedata.find(relativeFilename) != filedata.end())
2898-
return relativeFilename;
2897+
if (systemheader && filedata.find(header) != filedata.end())
2898+
return header;
28992899

29002900
return "";
29012901
}
@@ -3223,7 +3223,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
32233223

32243224
const Token * const inctok = inc2.cfront();
32253225

3226-
const bool systemheader = (inctok->op == '<');
3226+
const bool systemheader = (inctok->str()[0] == '<');
32273227
const std::string header(realFilename(inctok->str().substr(1U, inctok->str().size() - 2U)));
32283228
std::string header2 = getFileName(filedata, rawtok->location.file(), header, dui, systemheader);
32293229
if (header2.empty()) {

test.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,6 +1653,22 @@ static void nestedInclude()
16531653
ASSERT_EQUALS("file0,1,include_nested_too_deeply,#include nested too deeply\n", toString(outputList));
16541654
}
16551655

1656+
static void systemInclude()
1657+
{
1658+
const char code[] = "#include <limits.h>\n";
1659+
std::vector<std::string> files;
1660+
simplecpp::TokenList rawtokens = makeTokenList(code,files,"local/limits.h");
1661+
std::map<std::string, simplecpp::TokenList*> filedata;
1662+
filedata["limits.h"] = nullptr;
1663+
filedata["local/limits.h"] = &rawtokens;
1664+
1665+
simplecpp::OutputList outputList;
1666+
simplecpp::TokenList tokens2(files);
1667+
simplecpp::preprocess(tokens2, rawtokens, files, filedata, simplecpp::DUI(), &outputList);
1668+
1669+
ASSERT_EQUALS("", toString(outputList));
1670+
}
1671+
16561672
static void multiline1()
16571673
{
16581674
const char code[] = "#define A \\\n"
@@ -2566,6 +2582,7 @@ int main(int argc, char **argv)
25662582
TEST_CASE(missingHeader2);
25672583
TEST_CASE(missingHeader3);
25682584
TEST_CASE(nestedInclude);
2585+
TEST_CASE(systemInclude);
25692586

25702587
TEST_CASE(nullDirective1);
25712588
TEST_CASE(nullDirective2);

0 commit comments

Comments
 (0)