summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--tests/registry.test22
-rw-r--r--win/tclWinReg.c89
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 <kennykb@acm.org>
+
+ * 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 <dgp@users.sourceforge.net>
* 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 <tclPort.h>
@@ -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;
}