Francois Gouget : regedit: Make the dword and binary data parsing both more flexible and stricter.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Jun 14 07:47:07 CDT 2007


Module: wine
Branch: master
Commit: 804ec044727028892e76b74aeeda2c056482181c
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=804ec044727028892e76b74aeeda2c056482181c

Author: Francois Gouget <fgouget at codeweavers.com>
Date:   Thu Jun 14 11:46:29 2007 +0200

regedit: Make the dword and binary data parsing both more flexible and stricter.

Make sure it does not modify the value if the data is invalid.

---

 programs/regedit/regproc.c |  109 ++++++++++++++++++++------------------------
 1 files changed, 49 insertions(+), 60 deletions(-)

diff --git a/programs/regedit/regproc.c b/programs/regedit/regproc.c
index befa971..368f5c5 100644
--- a/programs/regedit/regproc.c
+++ b/programs/regedit/regproc.c
@@ -70,59 +70,55 @@ if (!(p)) \
 /******************************************************************************
  * Converts a hex representation of a DWORD into a DWORD.
  */
-static DWORD convertHexToDWord(char *str, BYTE *buf)
+static BOOL convertHexToDWord(char* str, DWORD *dw)
 {
-    DWORD dw;
-    char xbuf[9];
-
-    memcpy(xbuf,str,8);
-    xbuf[8]='\0';
-    sscanf(xbuf,"%08x",&dw);
-    memcpy(buf,&dw,sizeof(DWORD));
-    return sizeof(DWORD);
+    char dummy;
+    if (strlen(str) > 8 || sscanf(str, "%x%c", dw, &dummy) != 1) {
+        fprintf(stderr,"%s: ERROR, invalid hex value\n", getAppName());
+        return FALSE;
+    }
+    return TRUE;
 }
 
 /******************************************************************************
- * Converts a hex comma separated values list into a hex list.
- * The Hex input string must be in exactly the correct form.
+ * Converts a hex comma separated values list into a binary string.
  */
-static DWORD convertHexCSVToHex(char *str, BYTE *buf, ULONG bufLen)
+static BYTE* convertHexCSVToHex(char *str, DWORD *size)
 {
-    char *s = str;  /* Pointer to current */
-    char *b = (char*) buf;  /* Pointer to result  */
-
-    ULONG strLen    = strlen(str);
-    ULONG strPos    = 0;
-    DWORD byteCount = 0;
-
-    memset(buf, 0, bufLen);
-
-    /*
-     * warn the user if we are here with a string longer than 2 bytes that does
-     * not contains ",".  It is more likely because the data is invalid.
-     */
-    if ( ( strLen > 2) && ( strchr(str, ',') == NULL) )
-        fprintf(stderr,"%s: WARNING converting CSV hex stream with no comma, "
-                "input data seems invalid.\n", getAppName());
-    if (strLen > 3*bufLen)
-        fprintf(stderr,"%s: ERROR converting CSV hex stream.  Too long\n",
-                getAppName());
-
-    while (strPos < strLen) {
-        char xbuf[3];
+    char *s;
+    BYTE *d, *data;
+
+    /* The worst case is 1 digit + 1 comma per byte */
+    *size=(strlen(str)+1)/2;
+    data=HeapAlloc(GetProcessHeap(), 0, *size);
+    CHECK_ENOUGH_MEMORY(data);
+
+    s = str;
+    d = data;
+    *size=0;
+    while (*s != '\0') {
         UINT wc;
+        char dummy;
 
-        memcpy(xbuf,s,2); xbuf[2]='\0';
-        sscanf(xbuf,"%02x",&wc);
-        if (byteCount < bufLen)
-            *b++ =(unsigned char)wc;
+        if (s[1] != ',' && s[1] != '\0' && s[2] != ',' && s[2] != '\0') {
+            fprintf(stderr,"%s: ERROR converting CSV hex stream. Invalid sequence at '%s'\n",
+                    getAppName(), s);
+            HeapFree(GetProcessHeap(), 0, data);
+            return NULL;
+        }
+        if (sscanf(s, "%x%c", &wc, &dummy) < 1 || dummy != ',') {
+            fprintf(stderr,"%s: ERROR converting CSV hex stream. Invalid value at '%s'\n",
+                    getAppName(), s);
+            HeapFree(GetProcessHeap(), 0, data);
+            return NULL;
+        }
+        *d++ =(BYTE)wc;
+        (*size)++;
 
-        s+=3;
-        strPos+=3;
-        byteCount++;
+        s+=(wc < 0x10 ? 2 : 3);
     }
 
-    return byteCount;
+    return data;
 }
 
 /******************************************************************************
@@ -216,11 +212,9 @@ static void REGPROC_unescape_string(LPSTR str)
 static HRESULT setValue(LPSTR val_name, LPSTR val_data)
 {
     HRESULT hRes;
-    DWORD   dwDataType, dwParseType = 0;
+    DWORD  dwDataType, dwParseType;
     LPBYTE lpbData;
-    BYTE   convert[KEY_MAX_LEN];
-    BYTE *bBigBuffer = 0;
-    DWORD  dwLen;
+    DWORD  dwData, dwLen;
 
     if ( (val_name == NULL) || (val_data == NULL) )
         return ERROR_INVALID_PARAMETER;
@@ -248,21 +242,16 @@ static HRESULT setValue(LPSTR val_name, LPSTR val_data)
     }
     else if (dwParseType == REG_DWORD)  /* Convert the dword types */
     {
-        dwLen   = convertHexToDWord(val_data, convert);
-        lpbData = convert;
+        if (!convertHexToDWord(val_data, &dwData))
+            return ERROR_INVALID_DATA;
+        lpbData = (BYTE*)&dwData;
+        dwLen = sizeof(dwData);
     }
     else if (dwParseType == REG_BINARY) /* Convert the binary data */
     {
-        int b_len = strlen (val_data)+2/3;
-        if (b_len > KEY_MAX_LEN) {
-            bBigBuffer = HeapAlloc (GetProcessHeap(), 0, b_len);
-            CHECK_ENOUGH_MEMORY(bBigBuffer);
-            dwLen = convertHexCSVToHex(val_data, bBigBuffer, b_len);
-            lpbData = bBigBuffer;
-        } else {
-            dwLen   = convertHexCSVToHex(val_data, convert, KEY_MAX_LEN);
-            lpbData = convert;
-        }
+        lpbData = convertHexCSVToHex(val_data, &dwLen);
+        if (!lpbData)
+            return ERROR_INVALID_DATA;
     }
     else                                /* unknown format */
     {
@@ -277,8 +266,8 @@ static HRESULT setValue(LPSTR val_name, LPSTR val_data)
                dwDataType,
                lpbData,
                dwLen);
-
-    HeapFree (GetProcessHeap(), 0, bBigBuffer);
+    if (dwParseType == REG_BINARY)
+        HeapFree(GetProcessHeap(), 0, lpbData);
     return hRes;
 }
 




More information about the wine-cvs mailing list