(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