| Ticket UUID: | 805cffb017fde5baeb09ef1b8f4fccb980008cbb | |||
| Title: | segfault via Tk_ConfigureWidget | |||
| Type: | Bug | Version: | 8.5.111-8.6.4 | |
| Submitter: | aspect | Created on: | 2015-06-30 15:12:29 | |
| Subsystem: | 23. Option Parsing | Assigned To: | jan.nijtmans | |
| Priority: | 5 Medium | Severity: | Minor | |
| Status: | Closed | Last Modified: | 2015-07-07 15:28:17 | |
| Resolution: | Fixed | Closed By: | jan.nijtmans | |
| Closed on: | 2015-07-07 15:28:17 | |||
| Description: |
package require Tk
catch {canvas .c -bg #001 -width x}
canvas .d
causes a crash on the above versions (and core-8.5-branch) on Linux and Windows.
Note sure about OSX. 8.6 seems to be unaffected.
Removing either of the options from the first call avoids the crash. As does re-ordering
them, or specifying "-background" instead of "-bg", or replacing canvas with scrollbar.
The crash comes from the call to Tk_SetBackgroundFromBorder in ConfigureCanvas, which sees
NULL in canvasPtr->bgBorder when the 2nd canvas (.d) is being constructed.
The common element seems to be Tk_ConfigureWidget(): best hypothesis at this stage is:
* the first call to Tk_ConfigureWidget() with a bad -width leaves something related to
the previous option (-bg) in an inconsistent state
* the second call trips over this and returns TCL_OK, but NULL is in bgBorder illegally
See chat log from 2015-06-30T12:41:15Z for initial report and much discussion.
| |||
| User Comments: |
jan.nijtmans added on 2015-07-07 15:28:17:
Thanks for the patch! I was able to reproduce it (in Tk 8.6.4 too!), patch appears to work fine and looks good to me. anonymous added on 2015-07-03 14:53:38: Possible fix verified withTk 8.6.4 on AndroWish on ARM and plain SDL based Tk 8.6.4 on Linux x86_64:
--- old/generic/tkOldConfig.c 2014-08-26 06:41:06.248988059 +0200
+++ new/generic/tkOldConfig.c 2015-07-03 16:22:01.029610301 +0200
@@ -113,6 +113,10 @@
staticSpecs = GetCachedSpecs(interp, specs);
+ for (specPtr = staticSpecs; specPtr->type != TK_CONFIG_END; specPtr++) {
+ specPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED;
+ }
+
/*
* Pass one: scan through all of the arguments, processing those that
* match entries in the specs.
@@ -167,7 +171,6 @@
if ((specPtr->specFlags & TK_CONFIG_OPTION_SPECIFIED)
|| (specPtr->argvName == NULL)
|| (specPtr->type == TK_CONFIG_SYNONYM)) {
- specPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED;
continue;
}
if (((specPtr->specFlags & needFlags) != needFlags)
@@ -1126,7 +1129,6 @@
specPtr->defValue = Tk_GetUid(specPtr->defValue);
}
}
- specPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED;
}
} else {
cachedSpecs = Tcl_GetHashValue(entryPtr);
aspect added on 2015-07-01 00:32:02: scoofy has summarised key info from the chat at
http://morpheus.spectralhead.com/txt/wish-segfault.tcl.txt
Some of my intelligence above was gathered with the following patch applied:
Index: generic/tkCanvas.c
==================================================================
--- generic/tkCanvas.c
+++ generic/tkCanvas.c
@@ -488,10 +488,12 @@
|ButtonPressMask|ButtonReleaseMask|EnterWindowMask
|LeaveWindowMask|PointerMotionMask|VirtualEventMask,
CanvasBindProc, (ClientData) canvasPtr);
Tk_CreateSelHandler(canvasPtr->tkwin, XA_PRIMARY, XA_STRING,
CanvasFetchSelection, (ClientData) canvasPtr, XA_STRING);
+printf("Calling ConfigureCanvas(%p, %p, %d, %p)\n", interp, canvasPtr, argc, argv);
+printf("bgBorder = %p\n", canvasPtr->bgBorder);
if (ConfigureCanvas(interp, canvasPtr, argc-2, argv+2, 0) != TCL_OK) {
goto error;
}
Tcl_SetResult(interp, Tk_PathName(canvasPtr->tkwin), TCL_STATIC);
@@ -1885,21 +1887,32 @@
{
XGCValues gcValues;
GC newGC;
Tk_State old_canvas_state=canvasPtr->canvas_state;
+ printf("Entering Tk_ConfigureWidget(%p, %p, %p, %d, %p, %p, %x)\n",
+ interp, canvasPtr->tkwin, configSpecs,
+ objc, (CONST char **) objv, (char *) canvasPtr,
+ flags);
+ int i;
+ for(i=0; i < objc; ++i) {
+ printf("objv[%d] = '%s'\n", i, Tcl_GetString(objv[i]));
+ }
if (Tk_ConfigureWidget(interp, canvasPtr->tkwin, configSpecs,
objc, (CONST char **) objv, (char *) canvasPtr,
flags|TK_CONFIG_OBJS) != TCL_OK) {
+ printf("configure returned ERROR: %p\n", canvasPtr);
return TCL_ERROR;
}
+ printf("configure returned .. okay?: %p\n", canvasPtr);
/*
* A few options need special processing, such as setting the background
* from a 3-D border and creating a GC for copying bits to the screen.
*/
+ printf("About to call SetBackgroundFromBorder(%p, %p)\n", canvasPtr->tkwin, canvasPtr->bgBorder);
Tk_SetBackgroundFromBorder(canvasPtr->tkwin, canvasPtr->bgBorder);
if (canvasPtr->highlightWidth < 0) {
canvasPtr->highlightWidth = 0;
}
aspect added on 2015-06-30 15:14:22: The bad option after -bg doesn't have to be -width:
% catch {scrollbar .c -bg #001 -potato}
% scrollbar .d
Segmentation Fault
| |||