From 81071e7c69ad7aef5a908c64b219977a52442ff5 Mon Sep 17 00:00:00 2001 From: Kevin B Kenny Date: Sat, 17 Mar 2007 22:41:04 +0000 Subject: * win/tclWinReg.c (GetKeyNames): Size the buffer for enumerating key names correctly, so that Unicode names exceeding 127 chars can be retrieved without crashing. [Bug 1682211] * tests/registry.test (registry-4.9): Added test case for the above bug. --- ChangeLog | 8 +++++ tests/registry.test | 22 ++++++++++++- win/tclWinReg.c | 89 +++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 95 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index e76ab9e..d4ff293 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2007-03-17 Kevin Kenny + + * win/tclWinReg.c (GetKeyNames): Size the buffer for enumerating + key names correctly, so that Unicode names exceeding 127 chars + can be retrieved without crashing. [Bug 1682211] + * tests/registry.test (registry-4.9): Added test case for the + above bug. + 2007-03-13 Don Porter * generic/tclExecute.c (INST_FOREACH_STEP4): Re-fetch pointers for diff --git a/tests/registry.test b/tests/registry.test index 1b134b6..63ac403 100644 --- a/tests/registry.test +++ b/tests/registry.test @@ -10,7 +10,7 @@ # Copyright (c) 1997 by Sun Microsystems, Inc. All rights reserved. # Copyright (c) 1998-1999 by Scriptics Corporation. # -# RCS: @(#) $Id: registry.test,v 1.12.2.2 2003/03/19 05:24:22 dgp Exp $ +# RCS: @(#) $Id: registry.test,v 1.12.2.3 2007/03/17 22:41:05 kennykb Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 @@ -247,6 +247,20 @@ test registry-4.8 {GetKeyNames: Unicode} {pcOnly} { registry delete HKEY_CLASSES_ROOT\\TclFoobar set result } "baz\u30b7bar blat" +test registry-4.9 {GetKeyNames: very long key [Bug 1682211]} \ + -constraints {pcOnly} \ + -setup { + registry set HKEY_CLASSES_ROOT\\TclFoobar\\a + registry set HKEY_CLASSES_ROOT\\TclFoobar\\b[string repeat x 254] + registry set HKEY_CLASSES_ROOT\\TclFoobar\\c + } \ + -body { + lsort [registry keys HKEY_CLASSES_ROOT\\TclFoobar] + } \ + -cleanup { + registry delete HKEY_CLASSES_ROOT\\TclFoobar + } \ + -result [list a b[string repeat x 254] c] test registry-5.1 {GetType} {pcOnly english} { registry delete HKEY_CLASSES_ROOT\\TclFoobar @@ -598,3 +612,9 @@ test registry-12.5 {BroadcastValue} {pcOnly} { unset hostname ::tcltest::cleanupTests return + +# Local Variables: +# mode: tcl +# tcl-indent-level: 4 +# fill-column: 78 +# End: diff --git a/win/tclWinReg.c b/win/tclWinReg.c index ccd715a..fb6d2be 100644 --- a/win/tclWinReg.c +++ b/win/tclWinReg.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWinReg.c,v 1.21.2.5 2006/04/05 16:22:18 dgp Exp $ + * RCS: @(#) $Id: tclWinReg.c,v 1.21.2.6 2007/03/17 22:41:05 kennykb Exp $ */ #include @@ -513,21 +513,17 @@ GetKeyNames( Tcl_Obj *keyNameObj, /* Key to enumerate. */ Tcl_Obj *patternObj) /* Optional match pattern. */ { - HKEY key; - DWORD index; - char buffer[MAX_PATH+1], *pattern, *name; - Tcl_Obj *resultPtr; - int result = TCL_OK; - Tcl_DString ds; - - /* - * Attempt to open the key for enumeration. - */ - - if (OpenKey(interp, keyNameObj, KEY_ENUMERATE_SUB_KEYS, 0, &key) - != TCL_OK) { - return TCL_ERROR; - } + char *pattern; /* Pattern being matched against subkeys */ + HKEY key; /* Handle to the key being examined */ + DWORD subKeyCount; /* Number of subkeys to list */ + DWORD maxSubKeyLen; /* Maximum string length of any subkey */ + char *buffer; /* Buffer to hold the subkey name */ + DWORD bufSize; /* Size of the buffer */ + DWORD index; /* Position of the current subkey */ + char *name; /* Subkey name */ + Tcl_Obj *resultPtr; /* List of subkeys being accumulated */ + int result = TCL_OK; /* Return value from this command */ + Tcl_DString ds; /* Buffer to translate subkey name to UTF-8 */ if (patternObj) { pattern = Tcl_GetString(patternObj); @@ -535,15 +531,58 @@ GetKeyNames( pattern = NULL; } - /* - * Enumerate over the subkeys until we get an error, indicating the - * end of the list. + /* Attempt to open the key for enumeration. */ + + if (OpenKey(interp, keyNameObj, + KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, + 0, &key) != TCL_OK) { + return TCL_ERROR; + } + + /* + * Determine how big a buffer is needed for enumerating subkeys, and + * how many subkeys there are */ - resultPtr = Tcl_GetObjResult(interp); - for (index = 0; (*regWinProcs->regEnumKeyProc)(key, index, buffer, - MAX_PATH+1) == ERROR_SUCCESS; index++) { - Tcl_WinTCharToUtf((TCHAR *) buffer, -1, &ds); + result = (*regWinProcs->regQueryInfoKeyProc) + (key, NULL, NULL, NULL, &subKeyCount, &maxSubKeyLen, NULL, NULL, + NULL, NULL, NULL, NULL); + if (result != ERROR_SUCCESS) { + Tcl_SetObjResult(interp, Tcl_NewObj()); + Tcl_AppendResult(interp, "unable to query key \"", + Tcl_GetString(keyNameObj), "\": ", NULL); + AppendSystemError(interp, result); + RegCloseKey(key); + return TCL_ERROR; + } + if (regWinProcs->useWide) { + buffer = ckalloc((maxSubKeyLen+1) * sizeof(WCHAR)); + } else { + buffer = ckalloc(maxSubKeyLen+1); + } + + /* Enumerate the subkeys */ + + resultPtr = Tcl_NewObj(); + for (index = 0; index < subKeyCount; ++index) { + bufSize = maxSubKeyLen+1; + result = (*regWinProcs->regEnumKeyExProc) + (key, index, buffer, &bufSize, NULL, NULL, NULL, NULL); + if (result != ERROR_SUCCESS) { + Tcl_SetObjResult(interp, Tcl_NewObj()); + Tcl_AppendResult(interp, + "unable to enumerate subkeys of \"", + Tcl_GetString(keyNameObj), + "\": ", NULL); + AppendSystemError(interp, result); + result = TCL_ERROR; + break; + } + if (regWinProcs->useWide) { + Tcl_WinTCharToUtf((TCHAR *) buffer, bufSize * sizeof(WCHAR), &ds); + } else { + Tcl_WinTCharToUtf((TCHAR *) buffer, bufSize, &ds); + } name = Tcl_DStringValue(&ds); if (pattern && !Tcl_StringMatch(name, pattern)) { Tcl_DStringFree(&ds); @@ -556,7 +595,11 @@ GetKeyNames( break; } } + if (result == TCL_OK) { + Tcl_SetObjResult(interp, resultPtr); + } + ckfree(buffer); RegCloseKey(key); return result; } -- cgit v0.12