[PATCH 1/2] msi: queue dynamically allocated strings in cond.y
Nathan Gallaher
ngallaher at deepthought.org
Sat Jan 2 12:36:33 CST 2010
From 21b72112278e17af05ce7193167c44fd7f1d1022 Mon Sep 17 00:00:00 2001
From: Nathan Gallaher <ngallaher at deepthought.org>
Date: Sat, 2 Jan 2010 10:21:29 -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 | 128 ++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 98 insertions(+), 30 deletions(-)
diff --git a/dlls/msi/cond.y b/dlls/msi/cond.y
index c2a1737..95a709b 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,30 @@ struct cond_str {
INT len;
};
-static LPWSTR COND_GetString( const struct cond_str *str );
-static LPWSTR COND_GetLiteral( const struct cond_str *str );
+struct cond_mem {
+ struct list entry;
+ void *ptr;
+};
+
+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 );
+static void cond_free( void *info, 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( info, a );
+ cond_free( info, b );
return r;
}
@@ -189,7 +201,7 @@ boolean_factor:
| value_s
{
$$ = ($1 && $1[0]) ? 1 : 0;
- msi_free($1);
+ cond_free( info, $1 );
}
| value_i operator value_i
{
@@ -202,7 +214,7 @@ boolean_factor:
$$ = compare_int( num, $2, $3 );
else
$$ = ($2 == COND_NE || $2 == COND_INE );
- msi_free($1);
+ cond_free( info, $1 );
}
| value_i operator symbol_s
{
@@ -211,33 +223,33 @@ boolean_factor:
$$ = compare_int( $1, $2, num );
else
$$ = ($2 == COND_NE || $2 == COND_INE );
- msi_free($3);
+ cond_free( info, $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( info, $1 );
}
| value_i operator literal
{
$$ = 0;
- msi_free($3);
+ cond_free( info, $3 );
}
| COND_LPAR expression COND_RPAR
{
@@ -281,7 +293,7 @@ value_s:
literal:
COND_LITER
{
- $$ = COND_GetLiteral(&$1);
+ $$ = COND_GetLiteral( info, &$1 );
if( !$$ )
YYABORT;
}
@@ -299,7 +311,7 @@ value_i:
MSI_GetComponentStateW(cond->package, $2, &install, &action );
$$ = action;
- msi_free( $2 );
+ cond_free( info, $2 );
}
| COND_QUESTION identifier
{
@@ -308,7 +320,7 @@ value_i:
MSI_GetComponentStateW(cond->package, $2, &install, &action );
$$ = install;
- msi_free( $2 );
+ cond_free( info, $2 );
}
| COND_AMPER identifier
{
@@ -321,7 +333,7 @@ value_i:
else
$$ = action;
- msi_free( $2 );
+ cond_free( info, $2 );
}
| COND_EXCLAM identifier
{
@@ -330,7 +342,7 @@ value_i:
MSI_GetFeatureStateW(cond->package, $2, &install, &action );
$$ = install;
- msi_free( $2 );
+ cond_free( info, $2 );
}
;
@@ -340,7 +352,8 @@ symbol_s:
COND_input* cond = (COND_input*) info;
$$ = msi_dup_property( cond->package, $1 );
- msi_free( $1 );
+ $$ = cond_track_mem( info, $$ );
+ cond_free( info, $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( info, $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( info, 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,51 @@ static LPWSTR COND_GetLiteral( const struct cond_str *str )
return ret;
}
+static void *cond_alloc( void *info, unsigned int sz )
+{
+ void *ptr = msi_alloc( sz );
+ return cond_track_mem( info, ptr );
+}
+
+static void *cond_track_mem( void *info, void *ptr )
+{
+ COND_input *cond = (COND_input*) info;
+ struct cond_mem *mem;
+
+ if( !ptr )
+ return ptr;
+
+ mem = msi_alloc( sizeof (struct cond_mem) );
+ if( !mem )
+ {
+ msi_free( ptr );
+ return NULL;
+ }
+
+ mem->ptr = ptr;
+
+ list_add_head( &(cond->mem), &(mem->entry) );
+ return ptr;
+}
+
+static void cond_free( void *info, void *ptr )
+{
+ COND_input *cond = (COND_input*) info;
+ struct cond_mem *mem, *safety;
+
+ LIST_FOR_EACH_ENTRY_SAFE( mem, safety, &cond->mem, struct cond_mem, entry )
+ {
+ if( mem->ptr == ptr )
+ {
+ msi_free( mem->ptr );
+ list_remove( &(mem->entry) );
+ msi_free( mem );
+ return;
+ }
+ }
+ ERR("Error freeing %p\n", ptr);
+}
+
static int cond_error(const char *str)
{
TRACE("%s\n", str );
@@ -729,6 +789,7 @@ MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *package, LPCWSTR szCondition )
{
COND_input cond;
MSICONDITION r;
+ struct cond_mem *mem, *safety;
TRACE("%s\n", debugstr_w( szCondition ) );
@@ -739,12 +800,19 @@ 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_ENTRY_SAFE( mem, safety, &cond.mem, struct cond_mem, entry )
+ {
+ cond_free( &cond, mem->ptr );
+ }
+
TRACE("%i <- %s\n", r, debugstr_w(szCondition));
return r;
}
--
1.6.0.4
More information about the wine-patches
mailing list