From aa95731d6f03140d957c9ed36a3bcc2c802c5b7b Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Fri, 27 May 2005 19:23:29 +0000 Subject: [PATCH] Restrict deformating of nested index keys [[1]]. Introduce the beginning of group deformating {}. --- dlls/msi/format.c | 164 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 148 insertions(+), 16 deletions(-) diff --git a/dlls/msi/format.c b/dlls/msi/format.c index e6e82080eec..72be8d720c3 100644 --- a/dlls/msi/format.c +++ b/dlls/msi/format.c @@ -50,6 +50,11 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/msifo WINE_DEFAULT_DEBUG_CHANNEL(msi); +static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, + WCHAR** data, DWORD len, MSIRECORD* record, + BOOL* in_group); + + LPWSTR build_default_format(MSIRECORD* record) { int i; @@ -239,6 +244,45 @@ static LPWSTR deformat_property(MSIPACKAGE* package, LPCWSTR key, DWORD* chunk) return value; } +/* + * Groups cannot be nested. They are just treated as from { to next } + */ +static BOOL find_next_group(LPCWSTR source, DWORD len_remaining, + LPWSTR *group, LPCWSTR *mark, + LPCWSTR* mark2) +{ + int i; + BOOL found = FALSE; + + *mark = scanW(source,'{',len_remaining); + if (!*mark) + return FALSE; + + for (i = 1; (*mark - source) + i < len_remaining; i++) + { + if ((*mark)[i] == '}') + { + found = TRUE; + break; + } + } + if (! found) + return FALSE; + + *mark2 = &(*mark)[i]; + + i = *mark2 - *mark; + *group = HeapAlloc(GetProcessHeap(),0,i*sizeof(WCHAR)); + + i -= 1; + memcpy(*group,&(*mark)[1],i*sizeof(WCHAR)); + (*group)[i] = 0; + + TRACE("Found group %s\n",debugstr_w(*group)); + return TRUE; +} + + static BOOL find_next_outermost_key(LPCWSTR source, DWORD len_remaining, LPWSTR *key, LPCWSTR *mark, LPCWSTR* mark2, BOOL *nested) @@ -284,13 +328,71 @@ static BOOL find_next_outermost_key(LPCWSTR source, DWORD len_remaining, return TRUE; } +LPWSTR deformat_group(MSIPACKAGE* package, LPWSTR group, DWORD len, + MSIRECORD* record, DWORD* size) +{ + LPWSTR value; + LPCWSTR mark, mark2; + LPWSTR key; + BOOL nested; + INT failcount; + static const WCHAR fmt[] = {'{','%','s','}',0}; + UINT sz; + + if (!group || group[0] == 0) + { + *size = 0; + return NULL; + } + /* if no [] then group is returned as is */ + + if (!find_next_outermost_key(group, len, &key, &mark, &mark2, &nested)) + { + *size = (len+2)*sizeof(WCHAR); + value = HeapAlloc(GetProcessHeap(),0,*size); + sprintfW(value,fmt,group); + /* do not return size of the null at the end */ + *size = (len+1)*sizeof(WCHAR); + return value; + } + + HeapFree(GetProcessHeap(),0,key); + failcount = 0; + sz = deformat_string_internal(package, group, &value, strlenW(group), + record, &failcount); + if (failcount==0) + { + *size = sz * sizeof(WCHAR); + return value; + } + else if (failcount < 0) + { + LPWSTR v2; + + v2 = HeapAlloc(GetProcessHeap(),0,(sz+2)*sizeof(WCHAR)); + v2[0] = '{'; + memcpy(&v2[1],value,sz*sizeof(WCHAR)); + v2[sz+1]='}'; + HeapFree(GetProcessHeap(),0,value); + + *size = (sz+2)*sizeof(WCHAR); + return v2; + } + else + { + *size = 0; + return NULL; + } +} + /* * len is in WCHARs * return is also in WCHARs */ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, - WCHAR** data, DWORD len, MSIRECORD* record) + WCHAR** data, DWORD len, MSIRECORD* record, + INT* failcount) { LPCWSTR mark = NULL; LPCWSTR mark2 = NULL; @@ -313,7 +415,8 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, TRACE("Starting with %s\n",debugstr_w(ptr)); /* scan for special characters... fast exit */ - if (!scanW(ptr,'[',len) || (scanW(ptr,'[',len) && !scanW(ptr,']',len))) + if ((!scanW(ptr,'[',len) || (scanW(ptr,'[',len) && !scanW(ptr,']',len))) && + (scanW(ptr,'{',len) && !scanW(ptr,'}',len))) { /* not formatted */ *data = HeapAlloc(GetProcessHeap(),0,(len*sizeof(WCHAR))); @@ -326,9 +429,18 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, while (progress - ptr < len) { + /* seek out first group if existing */ + if (find_next_group(progress, len - (progress - ptr), &key, + &mark, &mark2)) + { + value = deformat_group(package, key, strlenW(key)+1, record, + &chunk); + key = NULL; + nested = FALSE; + } /* formatted string located */ - if (!find_next_outermost_key(progress, len - (progress - ptr), &key, - &mark, &mark2, &nested)) + else if (!find_next_outermost_key(progress, len - (progress - ptr), + &key, &mark, &mark2, &nested)) { LPBYTE nd2; @@ -368,7 +480,7 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, { TRACE("Nested key... %s\n",debugstr_w(key)); deformat_string_internal(package, key, &value, strlenW(key)+1, - record); + record, failcount); HeapFree(GetProcessHeap(),0,key); key = value; @@ -379,22 +491,31 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, if (!package) { /* only deformat number indexs */ - if (is_key_number(key)) + if (key && is_key_number(key)) + { value = deformat_index(record,key,&chunk); + if (!chunk && failcount && *failcount >= 0) + (*failcount)++; + } else { - DWORD keylen = strlenW(key); - chunk = (keylen + 2)*sizeof(WCHAR); - value = HeapAlloc(GetProcessHeap(),0,chunk); - value[0] = '['; - memcpy(&value[1],key,keylen*sizeof(WCHAR)); - value[1+keylen] = ']'; + if (failcount) + *failcount = -1; + if(key) + { + DWORD keylen = strlenW(key); + chunk = (keylen + 2)*sizeof(WCHAR); + value = HeapAlloc(GetProcessHeap(),0,chunk); + value[0] = '['; + memcpy(&value[1],key,keylen*sizeof(WCHAR)); + value[1+keylen] = ']'; + } } } else { sz = 0; - switch (key[0]) + if (key) switch (key[0]) { case '~': value = deformat_NULL(&chunk); @@ -415,8 +536,17 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, value = deformat_environment(package,&key[1],&chunk); break; default: + /* index keys cannot be nested */ if (is_key_number(key)) - value = deformat_index(record,key,&chunk); + if (!nested) + value = deformat_index(record,key,&chunk); + else + { + static const WCHAR fmt[] = {'[','%','s',']',0}; + value = HeapAlloc(GetProcessHeap(),0,10); + sprintfW(value,fmt,key); + chunk = strlenW(value)*sizeof(WCHAR); + } else value = deformat_property(package,key,&chunk); break; @@ -439,6 +569,8 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, size+=chunk; HeapFree(GetProcessHeap(),0,value); } + else if (failcount && *failcount >=0 ) + (*failcount)++; progress = mark2+1; } @@ -467,7 +599,7 @@ UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer, TRACE("(%s)\n",debugstr_w(rec)); len = deformat_string_internal(package,rec,&deformated,strlenW(rec), - record); + record, NULL); if (buffer) { @@ -514,7 +646,7 @@ UINT MSI_FormatRecordA( MSIPACKAGE* package, MSIRECORD* record, LPSTR buffer, TRACE("(%s)\n",debugstr_w(rec)); len = deformat_string_internal(package,rec,&deformated,strlenW(rec), - record); + record, NULL); lenA = WideCharToMultiByte(CP_ACP,0,deformated,len,NULL,0,NULL,NULL); if (buffer)