Browse Source

Merge topic 'fix-variable_watch-reallocation'

c6104028 Avoid occasional use-after-free when a variable watch is executed
Brad King 9 years ago
parent
commit
6d36fc8341
3 changed files with 19 additions and 10 deletions
  1. 15 8
      Source/cmMakefile.cxx
  2. 3 1
      Source/cmVariableWatch.cxx
  3. 1 1
      Source/cmVariableWatch.h

+ 15 - 8
Source/cmMakefile.cxx

@@ -2503,15 +2503,22 @@ const char* cmMakefile::GetDefinition(const std::string& name) const
   cmVariableWatch* vv = this->GetVariableWatch();
   if ( vv && !this->SuppressWatches )
     {
-    if ( def )
-      {
-      vv->VariableAccessed(name, cmVariableWatch::VARIABLE_READ_ACCESS,
-        def, this);
-      }
-    else
-      {
+    bool const watch_function_executed =
       vv->VariableAccessed(name,
-          cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS, def, this);
+                           def ? cmVariableWatch::VARIABLE_READ_ACCESS
+                           : cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS,
+                           def, this);
+
+    if (watch_function_executed)
+      {
+      // A callback was executed and may have caused re-allocation of the
+      // variable storage.  Look it up again for now.
+      // FIXME: Refactor variable storage to avoid this problem.
+      def = this->StateSnapshot.GetDefinition(name);
+      if(!def)
+        {
+        def = this->GetState()->GetInitializedCacheValue(name);
+        }
       }
     }
 #endif

+ 3 - 1
Source/cmVariableWatch.cxx

@@ -96,7 +96,7 @@ void cmVariableWatch::RemoveWatch(const std::string& variable,
     }
 }
 
-void  cmVariableWatch::VariableAccessed(const std::string& variable,
+bool  cmVariableWatch::VariableAccessed(const std::string& variable,
                                         int access_type,
                                         const char* newValue,
                                         const cmMakefile* mf) const
@@ -112,5 +112,7 @@ void  cmVariableWatch::VariableAccessed(const std::string& variable,
       (*it)->Method(variable, access_type, (*it)->ClientData,
         newValue, mf);
       }
+    return true;
     }
+  return false;
 }

+ 1 - 1
Source/cmVariableWatch.h

@@ -42,7 +42,7 @@ public:
   /**
    * This method is called when variable is accessed
    */
-  void VariableAccessed(const std::string& variable, int access_type,
+  bool VariableAccessed(const std::string& variable, int access_type,
     const char* newValue, const cmMakefile* mf) const;
 
   /**