(try 3) msi: queue dynamically allocated strings in cond.y

Nathan Gallaher ngallaher at deepthought.org
Tue Jan 5 22:36:42 CST 2010


From 155bd3e8a0c253082645a86b723156fb1a399ce7 Mon Sep 17 00:00:00 2001
From: Nathan Gallaher <ngallaher at deepthought.org>
Date: Tue, 5 Jan 2010 23:30:51 -0500
Subject: msi: queue dynamically allocated strings in cond.y for garbage collection

Previously, if parsing failed, any dynamically allocated string would
be leaked.
---
 dlls/msi/cond.y |  130 ++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 100 insertions(+), 30 deletions(-)

diff --git a/dlls/msi/cond.y b/dlls/msi/cond.y
index c2a1737..ae312a1 100644
--- a/dlls/msi/cond.y
+++ b/dlls/msi/cond.y
@@ -40,6 +40,7 @@
 #include "msiserver.h"
 #include "wine/debug.h"
 #include "wine/unicode.h"
+#include "wine/list.h"
 
 #define YYLEX_PARAM info
 #define YYPARSE_PARAM info
@@ -54,6 +55,7 @@ typedef struct tag_yyinput
     LPCWSTR str;
     INT    n;
     MSICONDITION result;
+    struct list mem;
 } COND_input;
 
 struct cond_str {
@@ -61,20 +63,25 @@ struct cond_str {
     INT len;
 };
 
-static LPWSTR COND_GetString( const struct cond_str *str );
-static LPWSTR COND_GetLiteral( const struct cond_str *str );
+static LPWSTR COND_GetString( void *info, const struct cond_str *str );
+static LPWSTR COND_GetLiteral( void *info, const struct cond_str *str );
 static int cond_lex( void *COND_lval, COND_input *info);
 
+static void *cond_alloc( void *info, unsigned int sz );
+static void *cond_track_mem( void *info, void *ptr, unsigned int sz );
+static void cond_free( void *ptr );
+
 static INT compare_int( INT a, INT operator, INT b );
 static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b, BOOL convert );
 
-static INT compare_and_free_strings( LPWSTR a, INT op, LPWSTR b, BOOL convert )
+static INT compare_and_free_strings( void *info, LPWSTR a, INT op, LPWSTR b,
+                                     BOOL convert )
 {
     INT r;
 
     r = compare_string( a, op, b, convert );
-    msi_free( a );
-    msi_free( b );
+    cond_free( a );
+    cond_free( b );
     return r;
 }
 
@@ -189,7 +196,7 @@ boolean_factor:
   | value_s
         {
             $$ = ($1 && $1[0]) ? 1 : 0;
-            msi_free($1);
+            cond_free( $1 );
         }
   | value_i operator value_i
         {
@@ -202,7 +209,7 @@ boolean_factor:
                 $$ = compare_int( num, $2, $3 );
             else 
                 $$ = ($2 == COND_NE || $2 == COND_INE );
-            msi_free($1);
+            cond_free( $1 );
         }
   | value_i operator symbol_s
         {
@@ -211,33 +218,33 @@ boolean_factor:
                 $$ = compare_int( $1, $2, num );
             else 
                 $$ = ($2 == COND_NE || $2 == COND_INE );
-            msi_free($3);
+            cond_free( $3 );
         }
   | symbol_s operator symbol_s
         {
-            $$ = compare_and_free_strings( $1, $2, $3, TRUE );
+            $$ = compare_and_free_strings( info, $1, $2, $3, TRUE );
         }
   | symbol_s operator literal
         {
-            $$ = compare_and_free_strings( $1, $2, $3, TRUE );
+            $$ = compare_and_free_strings( info, $1, $2, $3, TRUE );
         }
   | literal operator symbol_s
         {
-            $$ = compare_and_free_strings( $1, $2, $3, TRUE );
+            $$ = compare_and_free_strings( info, $1, $2, $3, TRUE );
         }
   | literal operator literal
         {
-            $$ = compare_and_free_strings( $1, $2, $3, FALSE );
+            $$ = compare_and_free_strings( info, $1, $2, $3, FALSE );
         }
   | literal operator value_i
         {
             $$ = 0;
-            msi_free($1);
+            cond_free( $1 );
         }
   | value_i operator literal
         {
             $$ = 0;
-            msi_free($3);
+            cond_free( $3 );
         }
   | COND_LPAR expression COND_RPAR
         {
@@ -281,7 +288,7 @@ value_s:
 literal:
     COND_LITER
         {
-            $$ = COND_GetLiteral(&$1);
+            $$ = COND_GetLiteral( info, &$1 );
             if( !$$ )
                 YYABORT;
         }
@@ -299,7 +306,7 @@ value_i:
       
             MSI_GetComponentStateW(cond->package, $2, &install, &action );
             $$ = action;
-            msi_free( $2 );
+            cond_free( $2 );
         }
   | COND_QUESTION identifier
         {
@@ -308,7 +315,7 @@ value_i:
       
             MSI_GetComponentStateW(cond->package, $2, &install, &action );
             $$ = install;
-            msi_free( $2 );
+            cond_free( $2 );
         }
   | COND_AMPER identifier
         {
@@ -321,7 +328,7 @@ value_i:
             else
                 $$ = action;
 
-            msi_free( $2 );
+            cond_free( $2 );
         }
   | COND_EXCLAM identifier
         {
@@ -330,7 +337,7 @@ value_i:
       
             MSI_GetFeatureStateW(cond->package, $2, &install, &action );
             $$ = install;
-            msi_free( $2 );
+            cond_free( $2 );
         }
     ;
 
@@ -338,9 +345,15 @@ symbol_s:
     identifier
         {
             COND_input* cond = (COND_input*) info;
+            UINT len;
 
             $$ = msi_dup_property( cond->package, $1 );
-            msi_free( $1 );
+            if ($$)
+            {
+                len = (lstrlenW($$) + 1) * sizeof (WCHAR);
+                $$ = cond_track_mem( info, $$, len );
+            }
+            cond_free( $1 );
         }
     | COND_PERCENT identifier
         {
@@ -348,17 +361,19 @@ symbol_s:
             $$ = NULL;
             if (len++)
             {
-                $$ = msi_alloc( len*sizeof (WCHAR) );
+                $$ = cond_alloc( info, len*sizeof (WCHAR) );
+                if( !$$ )
+                    YYABORT;
                 GetEnvironmentVariableW( $2, $$, len );
             }
-            msi_free( $2 );
+            cond_free( $2 );
         }
     ;
 
 identifier:
     COND_IDENT
         {
-            $$ = COND_GetString(&$1);
+            $$ = COND_GetString( info, &$1 );
             if( !$$ )
                 YYABORT;
         }
@@ -367,11 +382,11 @@ identifier:
 integer:
     COND_NUMBER
         {
-            LPWSTR szNum = COND_GetString(&$1);
+            LPWSTR szNum = COND_GetString( info, &$1 );
             if( !szNum )
                 YYABORT;
             $$ = atoiW( szNum );
-            msi_free( szNum );
+            cond_free( szNum );
         }
     ;
 
@@ -691,11 +706,11 @@ static int cond_lex( void *COND_lval, COND_input *cond )
     return rc;
 }
 
-static LPWSTR COND_GetString( const struct cond_str *str )
+static LPWSTR COND_GetString( void *info, const struct cond_str *str )
 {
     LPWSTR ret;
 
-    ret = msi_alloc( (str->len+1) * sizeof (WCHAR) );
+    ret = cond_alloc( info, (str->len+1) * sizeof (WCHAR) );
     if( ret )
     {
         memcpy( ret, str->data, str->len * sizeof(WCHAR));
@@ -705,11 +720,11 @@ static LPWSTR COND_GetString( const struct cond_str *str )
     return ret;
 }
 
-static LPWSTR COND_GetLiteral( const struct cond_str *str )
+static LPWSTR COND_GetLiteral( void *info, const struct cond_str *str )
 {
     LPWSTR ret;
 
-    ret = msi_alloc( (str->len-1) * sizeof (WCHAR) );
+    ret = cond_alloc( info, (str->len-1) * sizeof (WCHAR) );
     if( ret )
     {
         memcpy( ret, str->data+1, (str->len-2) * sizeof(WCHAR) );
@@ -719,6 +734,49 @@ static LPWSTR COND_GetLiteral( const struct cond_str *str )
     return ret;
 }
 
+static void *cond_alloc( void *info, unsigned int sz )
+{
+    COND_input *cond = (COND_input*) info;
+    struct list *mem;
+
+    mem = msi_alloc( sizeof (struct list) + sz );
+    if( !mem )
+        return NULL;
+
+    list_add_head( &(cond->mem), mem );
+    return mem + 1;
+}
+
+static void *cond_track_mem( void *info, void *ptr, unsigned int sz )
+{
+    void *new_ptr;
+
+    if( !ptr )
+        return ptr;
+
+    new_ptr = cond_alloc( info, sz );
+    if( !new_ptr )
+    {
+        msi_free( ptr );
+        return NULL;
+    }
+
+    memcpy( new_ptr, ptr, sz );
+    msi_free( ptr );
+    return new_ptr;
+}
+
+static void cond_free( void *ptr )
+{
+    struct list *mem = (struct list *)ptr - 1;
+
+    if( ptr )
+    {
+        list_remove( mem );
+        msi_free( mem );
+    }
+}
+
 static int cond_error(const char *str)
 {
     TRACE("%s\n", str );
@@ -729,6 +787,7 @@ MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *package, LPCWSTR szCondition )
 {
     COND_input cond;
     MSICONDITION r;
+    struct list *mem, *safety;
 
     TRACE("%s\n", debugstr_w( szCondition ) );
 
@@ -739,12 +798,23 @@ MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *package, LPCWSTR szCondition )
     cond.str   = szCondition;
     cond.n     = 0;
     cond.result = MSICONDITION_ERROR;
-    
+
+    list_init( &cond.mem );
+
     if ( !cond_parse( &cond ) )
         r = cond.result;
     else
         r = MSICONDITION_ERROR;
 
+    LIST_FOR_EACH_SAFE( mem, safety, &cond.mem )
+    {
+        /* The tracked memory lives directly after the list struct */
+        void *ptr = mem + 1;
+        if ( r != MSICONDITION_ERROR )
+            WARN( "condition parser failed to free up some memory: %p\n", ptr );
+        cond_free( ptr );
+    }
+
     TRACE("%i <- %s\n", r, debugstr_w(szCondition));
     return r;
 }
-- 
1.6.0.4



More information about the wine-patches mailing list