Skip to content

Commit 0cef648

Browse files
committed
guard against includes referencing themselves
1 parent 2e32634 commit 0cef648

File tree

2 files changed

+40
-25
lines changed

2 files changed

+40
-25
lines changed

ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2015-02-24 JJ Allaire <[email protected]>
2+
3+
* src/attributes.cpp: Guard against includes referencing themselves
4+
(and thus creating an endless loop of include processing).
5+
16
2015-02-20 Lionel Henry <[email protected]>
27

38
* inst/include/Rcpp/Function.h New Function constructors that will

src/attributes.cpp

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -738,9 +738,23 @@ namespace attributes {
738738
}
739739
}
740740

741-
// parse the local includes from the passed lines
742-
std::vector<FileInfo> parseLocalIncludes(
743-
const std::string& sourceFile) {
741+
bool addUniqueInclude(Rcpp::CharacterVector include,
742+
std::vector<FileInfo>* pLocalIncludes) {
743+
744+
// return false if we already have this include
745+
std::string path = Rcpp::as<std::string>(include);
746+
for (size_t i = 0; i<pLocalIncludes->size(); ++i) {
747+
if (pLocalIncludes->at(i).path() == path)
748+
return false;
749+
}
750+
751+
// add it and return true
752+
pLocalIncludes->push_back(FileInfo(path));
753+
return true;
754+
}
755+
756+
void parseLocalIncludes(const std::string& sourceFile,
757+
std::vector<FileInfo>* pLocalIncludes) {
744758

745759
// import R functions
746760
Rcpp::Environment baseEnv = Rcpp::Environment::base_env();
@@ -769,7 +783,7 @@ namespace attributes {
769783

770784
// accumulate local includes (skip commented sections)
771785
CommentState commentState;
772-
std::vector<FileInfo> localIncludes;
786+
std::vector<FileInfo> newIncludes;
773787
for (int i = 0; i<matches.size(); i++) {
774788
std::string line = lines[i];
775789
commentState.submitLine(line);
@@ -781,34 +795,30 @@ namespace attributes {
781795
Rcpp::CharacterVector include =
782796
filepath(sourceDir, std::string(match[1]));
783797
// if it exists then normalize and add to our list
784-
if (fileExists(include)) {
798+
LogicalVector exists = fileExists(include);
799+
if (exists[0]) {
785800
include = normalizePath(include);
786-
localIncludes.push_back(
787-
FileInfo(Rcpp::as<std::string>(include)));
801+
if (addUniqueInclude(include, pLocalIncludes)) {
802+
newIncludes.push_back(
803+
FileInfo(Rcpp::as<std::string>(include)));
804+
}
788805
}
789806
}
790807
}
791808
}
792809

793-
// look for local includes recursively (make a copy of the local
794-
// includes first so we can mutate it during iteration)
795-
std::vector<FileInfo> localIncludesCopy = localIncludes;
796-
for (size_t i = 0; i<localIncludesCopy.size(); i++) {
797-
FileInfo include = localIncludesCopy[i];
798-
std::vector<FileInfo> includes = parseLocalIncludes(
799-
include.path());
800-
std::copy(includes.begin(),
801-
includes.end(),
802-
std::back_inserter(localIncludes));
810+
// look for includes recursively
811+
for (size_t i = 0; i<newIncludes.size(); i++) {
812+
FileInfo include = newIncludes[i];
813+
parseLocalIncludes(include.path(), pLocalIncludes);
803814
}
804-
805-
// remove duplicates
806-
std::sort(localIncludes.begin(), localIncludes.end());
807-
std::vector<FileInfo>::iterator end =
808-
std::unique(localIncludes.begin(), localIncludes.end());
809-
localIncludes.erase(end, localIncludes.end());
810-
811-
// return includes
815+
}
816+
817+
// parse the local includes from the passed lines
818+
std::vector<FileInfo> parseLocalIncludes(
819+
const std::string& sourceFile) {
820+
std::vector<FileInfo> localIncludes;
821+
parseLocalIncludes(sourceFile, &localIncludes);
812822
return localIncludes;
813823
}
814824

0 commit comments

Comments
 (0)