Browse Source

Genex: Fix stack overflow in transitive property evaluation.

Commit v2.8.11~156^2~2 (Expand includes and defines transitively
in 'external' genexes., 2013-02-13) introduced a recursive loop
and a stack overflow during evaluation of a link implementation
which depends on a transitive property, such as

 add_library(empty1 ...)
 add_library(empty2 ...)
 target_link_libraries(empty1
   PRIVATE
     $<$<STREQUAL:$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>,/foo/bar>:empty2>
 )

There is no use-case for code like that currently, but it should not
cause a stack overflow.

Avoid the recursion by reporting an error early if a case like this
is found.
Stephen Kelly 11 years ago
parent
commit
61ce654742
21 changed files with 141 additions and 0 deletions
  1. 13 0
      Source/cmGeneratorExpressionEvaluator.cxx
  2. 1 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1-result.txt
  3. 10 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1-stderr.txt
  4. 8 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1.cmake
  5. 1 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2-result.txt
  6. 10 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2-stderr.txt
  7. 8 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2.cmake
  8. 1 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3-result.txt
  9. 1 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3-stderr.txt
  10. 10 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3.cmake
  11. 1 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4-result.txt
  12. 8 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4-stderr.txt
  13. 14 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4.cmake
  14. 1 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5-result.txt
  15. 8 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5-stderr.txt
  16. 10 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5.cmake
  17. 1 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6-result.txt
  18. 8 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6-stderr.txt
  19. 14 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6.cmake
  20. 6 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
  21. 7 0
      Tests/RunCMake/TargetPropertyGeneratorExpressions/empty.cpp

+ 13 - 0
Source/cmGeneratorExpressionEvaluator.cxx

@@ -1028,6 +1028,19 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
       {
       if (dagCheckerParent->EvaluatingLinkLibraries())
         {
+#define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \
+    (#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) ||
+        if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_COMPARE)
+            false)
+          {
+          reportError(context, content->GetOriginalExpression(),
+              "$<TARGET_PROPERTY:...> expression in link libraries "
+              "evaluation depends on target property which is transitive "
+              "over the link libraries, creating a recursion.");
+          return std::string();
+          }
+#undef TRANSITIVE_PROPERTY_COMPARE
+
         if(!prop)
           {
           return std::string();

+ 1 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error at LinkImplementationCycle1.cmake:5 \(target_link_libraries\):
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>
+
+  \$<TARGET_PROPERTY:...> expression in link libraries evaluation depends on
+  target property which is transitive over the link libraries, creating a
+  recursion.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:8 \(include\)

+ 8 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1.cmake

@@ -0,0 +1,8 @@
+
+add_library(empty1 empty.cpp)
+add_library(empty2 empty.cpp)
+
+target_link_libraries(empty1
+  LINK_PUBLIC
+    $<$<STREQUAL:$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>,/foo/bar>:empty2>
+)

+ 1 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error at LinkImplementationCycle2.cmake:5 \(target_link_libraries\):
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>
+
+  \$<TARGET_PROPERTY:...> expression in link libraries evaluation depends on
+  target property which is transitive over the link libraries, creating a
+  recursion.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:8 \(include\)

+ 8 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2.cmake

@@ -0,0 +1,8 @@
+
+add_library(empty1 empty.cpp)
+add_library(empty2 empty.cpp)
+
+target_link_libraries(empty1
+  LINK_PUBLIC
+    $<$<STREQUAL:$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>,/foo/bar>:empty2>
+)

+ 1 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3-result.txt

@@ -0,0 +1 @@
+0

+ 1 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3-stderr.txt

@@ -0,0 +1 @@
+^$

+ 10 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3.cmake

@@ -0,0 +1,10 @@
+
+add_library(empty1 empty.cpp)
+add_library(empty2 empty.cpp)
+
+# This is OK, because evaluating the INCLUDE_DIRECTORIES is not affected by
+# the content of the INTERFACE_LINK_LIBRARIES.
+target_link_libraries(empty1
+  INTERFACE
+    $<$<STREQUAL:$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>,/foo/bar>:empty2>
+)

+ 1 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4-stderr.txt

@@ -0,0 +1,8 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>
+
+  \$<TARGET_PROPERTY:...> expression in link libraries evaluation depends on
+  target property which is transitive over the link libraries, creating a
+  recursion.

+ 14 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4.cmake

@@ -0,0 +1,14 @@
+
+add_library(empty1 empty.cpp)
+add_library(empty2 empty.cpp)
+
+# The INTERFACE_INCLUDE_DIRECTORIES do not depend on the link interface.
+# On its own, this is fine. It is only when used by empty3 that an error
+# is appropriately issued.
+target_link_libraries(empty1
+  INTERFACE
+    $<$<STREQUAL:$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>,/foo/bar>:empty2>
+)
+
+add_library(empty3 empty.cpp)
+target_link_libraries(empty3 empty1)

+ 1 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5-stderr.txt

@@ -0,0 +1,8 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>
+
+  \$<TARGET_PROPERTY:...> expression in link libraries evaluation depends on
+  target property which is transitive over the link libraries, creating a
+  recursion.

+ 10 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5.cmake

@@ -0,0 +1,10 @@
+
+add_library(empty1 INTERFACE IMPORTED)
+add_library(empty2 INTERFACE IMPORTED)
+
+set_property(TARGET empty1 PROPERTY INTERFACE_LINK_LIBRARIES
+  $<$<STREQUAL:$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>,/foo/bar>:empty2>
+)
+
+add_library(empty3 empty.cpp)
+target_link_libraries(empty3 empty1)

+ 1 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6-stderr.txt

@@ -0,0 +1,8 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>
+
+  \$<TARGET_PROPERTY:...> expression in link libraries evaluation depends on
+  target property which is transitive over the link libraries, creating a
+  recursion.

+ 14 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6.cmake

@@ -0,0 +1,14 @@
+
+add_library(empty1 SHARED empty.cpp)
+add_library(empty2 SHARED empty.cpp)
+
+# The INTERFACE_INCLUDE_DIRECTORIES do not depend on the link interface.
+# On its own, this is fine. It is only when used by empty3 that an error
+# is appropriately issued.
+target_link_libraries(empty1
+  INTERFACE
+    $<$<STREQUAL:$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>,/foo/bar>:empty2>
+)
+
+add_library(empty3 SHARED empty.cpp)
+target_link_libraries(empty3 empty1)

+ 6 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake

@@ -15,3 +15,9 @@ run_cmake(BadInvalidName5)
 run_cmake(BadInvalidName6)
 run_cmake(BadInvalidName7)
 run_cmake(BadInvalidName8)
+run_cmake(LinkImplementationCycle1)
+run_cmake(LinkImplementationCycle2)
+run_cmake(LinkImplementationCycle3)
+run_cmake(LinkImplementationCycle4)
+run_cmake(LinkImplementationCycle5)
+run_cmake(LinkImplementationCycle6)

+ 7 - 0
Tests/RunCMake/TargetPropertyGeneratorExpressions/empty.cpp

@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty()
+{
+  return 0;
+}