Tcl Source Code

View Ticket
Login
Ticket UUID: 406709
Title: Bytecode error -TclExecuteByteCode error
Type: Bug Version: obsolete: 8.3.2
Submitter: tallniel Created on: 2001-03-07 15:36:28
Subsystem: 47. Bytecode Compiler Assigned To: msofer
Priority: 9 Immediate Severity:
Status: Closed Last Modified: 2001-04-10 22:06:58
Resolution: Fixed Closed By: msofer
    Closed on: 2001-04-10 15:06:58
Description:
The following script causes a bytecode error on Win98SE. The error causes Wish to hang, and CPU 
and memory usage goes up to near maximum. The wish and console windows remain visible but do 
not redraw if you cover and uncover them with another app (you are left with white 
window-shaped objects). The only solution is to reboot the computer.

Operating System: Windows 98 Second Edition
Tcl Version: 8.3.2
Extensions: none

Error: TclExecuteByeCode execution failure: end stack top != start stack top

Script:

proc createByteCodeBug {} {
    set path [frame .frame];

    entry $path.command;
    text $path.text;

    pack $path.command -side bottom -fill x -expand 1;
    pack $path.text -side top -fill both -expand 1;

    $path.command configure -state disabled;
    $path.text configure -state normal;
    focus $path.text;
    foreach {dir equiv} [list Up k Down j Left h Right l] {
        bind $path.text <Key-$dir> {}
        bind $path.text <Key-$equiv> [concat [bind Text <Key-$dir>]; break];
    }
}

createByteCodeBug
User Comments: msofer added on 2001-04-10 22:06:58:
Logged In: YES 
user_id=148712

Hanging of W98 now submitted as Tk bug #415166

msofer added on 2001-04-07 10:32:41:
Logged In: YES 
user_id=148712

Closed by committal of patch #414470.
The hanging of W98 on a panic has been submitted as bug
#414474

msofer added on 2001-04-07 10:07:42:

File Added - 5103: patch

msofer added on 2001-04-07 10:07:41:
Logged In: YES 
user_id=148712

New patch, similar behaviour to the second patch; corrects
also error messages and adds a test.

hobbs added on 2001-03-31 15:49:32:
Logged In: YES 
user_id=72656

Patch #2 does satisfy the return to 7.6 compatability as 
Donal notes.  However, you need to make sure to update the 
error messages that correspond to changing the if 
condition, as well as add test cases to exercise the fix.

dgp added on 2001-03-31 03:43:33:

File Added - 4786: tclExecute.c.patch2

Logged In: YES 
user_id=80530

Uploading second patch file.  I'm not sure why others
are having trouble; this works fine for me.

dgp added on 2001-03-31 03:42:33:

File Added - 4785: tclExecute.c.patch1

dgp added on 2001-03-31 03:42:32:
Logged In: YES 
user_id=80530

Attempting to upload the patch file.

msofer added on 2001-03-09 23:34:19:
Logged In: YES 
user_id=148712

Donal was kimd enough to hang the patches at
http://www.cs.man.ac.uk/~fellowsd/tcl/patches/
as I can't upload them here ...

tclExecute.c.patch1 transforms the panic into an error; I
think it is quite safe.

tclExecute.c.patch2 gives the correct behaviour for these
cases (no error), but it does weaken a sanity check in the
engine. I'm not sure about all possible consequences of
this, although it is guaranteed safe for any bytecode that
does not cause a dump in current sources.

msofer added on 2001-03-09 19:33:57:
Logged In: YES 
user_id=148712

Here goes patch_1: it fixes b, we now get an error return.
It is a test patch, still incomplete: the error message
should still be fixed, a test should be incorporated, ...

See also patch_2, following in a few moments

msofer added on 2001-03-09 19:33:35:
Logged In: YES 
user_id=148712

Here goes patch_1: it fixes b, we now get an error return.
It is a test patch, still incomplete: the error message
should still be fixed, a test should be incorporated, ...

See also patch_2, following in a few moments

msofer added on 2001-03-09 19:31:45:
Logged In: YES 
user_id=148712

Here goes patch_1: it fixes b, we now get an error return.
It is a test patch, still incomplete: the error message
should still be fixed, a test should be incorporated, ...

See also patch_2, following in a few moments

dkf added on 2001-03-09 18:55:59:
Logged In: YES 
user_id=79902

What follows should probably be a reasonable basis for a
test.  The behaviour under 7.6 is correct, 8.0-8.4a2 crash,
and your simple fix will make it return an error.

$ tclsh7.6
% proc a {} {
    set a 1
    foreach b b {list [concat a; break]; incr a}
    incr a
}
% a
2

msofer added on 2001-03-09 18:33:47:
Logged In: YES 
user_id=148712

I now see this as three different bugs:
(a) loop execptions can leave extra items in the stack
(b) the engine panics when it sees extra items in the stack
- an error would be enough in this case, a panic is in order
when there are *missing* items. Th epoint is that the
presently executing bytecode is not OK, but there is no
evidence that it corrupted any data that doesn't belong to
it in the first place ...
(c) W98 hangs on a tcl panic instead of exiting cleanly

(a) is a tough cookie, it requires some changes in the logic
of the engine, maybe even in the compiler. Not to be fixed
in a hurry ...

(b) is very easy to fix; patch follows later today

(c) I do not know anything about this one ...

I think that by fixing (b) we remove the urgency of the
problem, so that (a) can be given the careful thought it
deserves

dkf added on 2001-03-09 18:17:53:
Logged In: YES 
user_id=79902

Problem existed in 8.0.4 and still exists in CVS HEAD of
8-Mar-2001.

msofer added on 2001-03-09 02:35:29:
Logged In: YES 
user_id=148712

A minimal script that exercises the bug is:
while 1 {puts [break]}

msofer added on 2001-03-08 23:03:25:
Logged In: YES 
user_id=148712

The problem is with loop exception ranges in general: they
do not register (as catch does) the stack level at begin,
and do not restore the stack on return.

To illustrate, this also bombs:
proc a {} {
    for {set i 0} {$i < 10} {incr i} {
        list [continue]
    }
 }

The problem appears *also* in tcl8.4a2 (and I guess many
other versions).

The bad exit from "panic" seems to be unique to W98; at
least it does not happen on W95.

dkf added on 2001-03-08 22:30:04:
Logged In: YES 
user_id=79902

Bytecodes for my little script that exercises the problem
follow:

ByteCode 0x370c8, refCt 1, epoch 0, interp 0x24e30 (epoch 0)
  Source "foreach a a {puts [concat a;break]}"
  Cmds 4, src 35, inst 35, litObjs 4, aux 1, stkDepth 3,
code/src 6.06
  Code 212 = header 100+inst 35+litObj 16+exc 28+aux
8+cmdMap 16
  Proc 0x302d0, refCt 1, args 0, compiled locals 3
      slot 0, scalar, temp
      slot 1, scalar, temp
      slot 2, scalar, "a"
  Exception ranges 1, depth 1:
      0: level 1, loop, pc 17-28, continue 10, break 32
  Commands 4:
      1: pc 0-33, src 0-34         2: pc 17-28, src 13-33
      3: pc 19-24, src 19-26       4: pc 26-26, src 28-32
  Command 1: "foreach a a {puts [concat a;break]}"
    (0) push1 0         # "a"
    (2) storeScalar1 0  # temp var 0
    (4) pop 
    (5) foreach_start4 0 
    (10) foreach_step4 0 
    (15) jumpFalse1 17          # pc 32
  Command 2: "puts [concat a;break]"
    (17) push1 1        # "puts"
  Command 3: "concat a"
    (19) push1 2        # "concat"
    (21) push1 0        # "a"
    (23) invokeStk1 2 
    (25) pop 
  Command 4: "break"
    (26) break 
    (27) invokeStk1 2 
    (29) pop 
    (30) jump1 -20      # pc 10
    (32) push1 3        # ""
    (34) done 

I believe the problem is that the break doesn't clobber the
values pushed onto the stack that were supposed to be
removed before reaching the catching context (the foreach).

dkf added on 2001-03-08 20:40:29:
Logged In: YES 
user_id=79902

The following scriptlet also exercises the bug:
   proc a {} {foreach a b {puts [concat a; break]}}; a
panic() message was (after line breaking):
   TclExecuteByteCode: done instruction at pc 34:
                   stack top 1 != entry stack top 0
   TclExecuteByteCode execution failure: end stack top !=
start stack top
Stack trace follows:
#0  0xff11a118 in _libc_kill () from /usr/lib/libc.so.1
#1  0xff0b95b0 in abort () from /usr/lib/libc.so.1
#2  0xff31d7f0 in Tcl_PanicVA (
    format=0xff3560a0 "TclExecuteByteCode execution failure:
end stack top != start stack top", argList=0xffbedb18) at
./../generic/tclPanic.c:93
#3  0xff31d838 in Tcl_Panic (
    arg1=0xff3560a0 "TclExecuteByteCode execution failure:
end stack top != start stack top") at
./../generic/tclPanic.c:121
#4  0xff2e4140 in TclExecuteByteCode (interp=0x24898,
codePtr=0x2d4b0)
    at ./../generic/tclExecute.c:642
#5  0xff2b0590 in Tcl_EvalObjEx (interp=0x24898,
objPtr=0x2d2f8, flags=0)
    at ./../generic/tclBasic.c:2837
#6  0xff32c644 in TclObjInterpProc (clientData=0x2f7f8,
interp=0x24898, 
    objc=1, objv=0x262e0) at ./../generic/tclProc.c:1014
#7  0xff2e4c98 in TclExecuteByteCode (interp=0x24898,
codePtr=0x334b8)
    at ./../generic/tclExecute.c:874
#8  0xff2b0590 in Tcl_EvalObjEx (interp=0x24898,
objPtr=0x2cf50, flags=0)
    at ./../generic/tclBasic.c:2837
#9  0xff2f91fc in Tcl_RecordAndEvalObj (interp=0x24898,
cmdPtr=0x2cf50, 
    flags=0) at ./../generic/tclHistory.c:142
#10 0xff314678 in Tcl_Main (argc=1, argv=0xffbee9d4, 
    appInitProc=0x10ae0 <Tcl_AppInit>) at
./../generic/tclMain.c:315
#11 0x10acc in main (argc=1, argv=0xffbee9d4) at
./../unix/tclAppInit.c:99

Attachments: