Tcl Source Code

View Ticket
Login
Ticket UUID: 804681
Title: traces on errorInfo/errorCode corrupt the evaluation stack
Type: Bug Version: obsolete: 8.4b1
Submitter: hume Created on: 2003-09-11 20:00:06
Subsystem: 47. Bytecode Compiler Assigned To: msofer
Priority: 8 Severity:
Status: Closed Last Modified: 2003-09-20 01:06:31
Resolution: Fixed Closed By: msofer
    Closed on: 2003-09-19 18:06:31
Description:
If a variable trace is placed on errorInfo, certain errors cause a core dump in FreeListInternalRep() 
on both NT and Linux platforms.  The crash does not happen with version 8.3

To show the error enter the following at the Tcl prompt:

proc show args {puts $args}
trace variable errorInfo wu show
expr 9/0

Here is the NT stack:

FreeListInternalRep(Tcl_Obj * 0x002eb348) line 1386 + 6 bytes
TclExecuteByteCode(Tcl_Interp * 0x0029d380, ByteCode * 0x002a5390) line 4198 + 55 bytes
TclCompEvalObj(Tcl_Interp * 0x0029d380, Tcl_Obj * 0x00294ba0) line 1008 + 13 bytes
Tcl_EvalObjEx(Tcl_Interp * 0x0029d380, Tcl_Obj * 0x00294ba0, int 131072) line 3952 + 13 bytes
Tcl_RecordAndEvalObj(Tcl_Interp * 0x0029d380, Tcl_Obj * 0x00294ba0, int 131072) line 142 + 23 
bytes
Tcl_Main(int 1, char * * 0x00274b30, int (Tcl_Interp *)* 0x00401005 _Tcl_AppInit) line 390 + 24 
bytes
main() line 110 + 19 bytes
mainCRTStartup() line 338 + 17 bytes
KERNEL32! 7c4e87f5()
User Comments: msofer added on 2003-09-20 01:06:31:
Logged In: YES 
user_id=148712

Fixed in HEAD and 8.4-branch; patch attached as reference
for evetnual backporters

msofer added on 2003-09-15 15:21:54:
Logged In: YES 
user_id=148712

The function calls that require protection are:
Tcl_ResetResult, Tcl_AddObjErrorInfo, Tcl_AddErrorInfo,
Tcl_SetObjErrorCode, Tcl_SetErrorCode, Tcl_SetErrorCodeVA,
Tcl_PosixError, Tcl_LogCommandInfo

msofer added on 2003-09-15 15:18:45:
Logged In: YES 
user_id=148712

Pre-modif TEBC had the bug too, but it was more difficult to
trigger. Witness

mig@cx:/CVS/tcl8.3.4/unix$ ./tclsh
% info patch
8.3.4
% proc show args {puts $args}
% trace variable errorInfo wu show
% expr {1+9/0}
errorInfo {} w
errorInfo {} w
divide by zero
% exit
Segmentation fault

Before those modifs, an instruction that caused an error
removed its arguments from the stack before "goto
checkForCatch", so that the corruption only happened when
there were objects in the stack deeper than them - in the
example, the "1" is in the stack when the division error
occurs, so that removing the "9" and "0" is not quite enough.
Now the stack is not cleared before "goto checkForCatch", so
that the stack is always corrupted if error logging causes
TEBC to be called.

msofer added on 2003-09-14 21:04:22:
Logged In: YES 
user_id=148712

Explicit bug description, for the record:
 
(a) every call from TEBC to an outside function that may
evaluate a bcc'ed script has to be protected by a
(DE)CACHE_STACK_INFO() macro pair to insure the stack's
integrity - namely, so that the nested TEBC knows where the
not-in-use part of the stack starts. Failure to do so
corrupts the evaluation stack.

(b) due to the trace mechanism, every variable modification
may end up evaluating bcc'ed code. Therefore, every call
that touches a variable should be protected as above.

(c) the error mechanism modifies ::errorInfo. But error
reports are not protected in TEBC. Thus, a trace on
::errorInfo that calls a proc corrupts the evaluation stack.

One possible fix is to identify every instance at risk and
protect it. I have not yet been able to understand why TEBC
was immune to this problem before, ie, what (subtle?)
pre-existing protection I destroyed. TEBC will be fixed
shortly with either a restoration of the previous mechanism,
or else a bunch of new macro pairs.

msofer added on 2003-09-13 04:14:11:
Logged In: YES 
user_id=148712

Good catch Don! There's more of the same, the following
still crashes after your patch:

   proc show args {puts $args}
   trace variable errorInfo wu show
   incr a ;# assuming no variable a is defined

I'll hunt down all similar things in TEBC, now that you
discovered what was happening. I'd also try to understand
how those modifs introduced the bug

dgp added on 2003-09-13 04:00:40:

File Added - 61387: 804681.patch

Logged In: YES 
user_id=80530


Here's a patch against the
tip of the core-8-4-branch that
fixes the segfault in the
reported script.

Leaving the report open for
further review from msofer.

dgp added on 2003-09-13 00:02:29:
Logged In: YES 
user_id=80530


The segfault happens as the
bytecode execution engine
tries to clear away items on
the stack.  It decrements and
tries to free a list value that
has already been freed.

This list value is the $args
value that was a local variable
in the [show] proc.  It has been
freed already because it was
freed when [show] returned, as
one would expect.

It's a mystery why there's a reference
to $args on the bytecode execution
stack, and another mystery why that
reference, if it must indeed exist,
never accounted for itself with a refCount.

dgp added on 2003-09-12 09:24:31:
Logged In: YES 
user_id=80530


This bug was introduced by
msofer's commits on
2002-06-18.

dgp added on 2003-09-12 05:43:03:
Logged In: YES 
user_id=80530


Between 8.4a4 and 8.4b1 even.

dgp added on 2003-09-12 05:27:51:
Logged In: YES 
user_id=80530


Thanks for the report.

Further investigation reveals
this bug entered sometime between
releases Tcl 8.4a4 and Tcl 8.4.0.

Attachments: