Tcl Source Code

View Ticket
Login
2022-11-28
23:13 Closed ticket [da63e4c1ef]: Crash in Tcl_WriteChars() plus 5 other changes artifact: 3ab6d62437 user: jan.nijtmans
2022-11-23
21:26 Pending ticket [da63e4c1ef]. artifact: 3cbd8aecbc user: jan.nijtmans
21:03
Fix [da63e4c1e]: Crash in Tcl_WriteChars(). Make everything compile (again) with a C++ compiler. check-in: 3539aef815 user: jan.nijtmans tags: trunk, main
18:04 Ticket [da63e4c1ef] Crash in Tcl_WriteChars() status still Open with 3 other changes artifact: 1a6a733564 user: anonymous
15:34 Ticket [da63e4c1ef]: 3 changes artifact: 7ff07324bd user: jan.nijtmans
15:21
Proposed fix for [da63e4c1e]. First version, not 100% as expected yet. Closed-Leaf check-in: 58883dde6d user: jan.nijtmans tags: bug-da63e4c1e
09:38 Ticket [da63e4c1ef] Crash in Tcl_WriteChars() status still Open with 3 other changes artifact: 2af3ced5a9 user: anonymous
08:53 Ticket [da63e4c1ef]: 3 changes artifact: 4f13e77294 user: anonymous
07:56 Ticket [da63e4c1ef]: 4 changes artifact: c3514056b9 user: jan.nijtmans
07:49 Ticket [07563f771f] Segfault when changing encoding on stdout status still Open with 3 other changes artifact: 4ea9cafb4d user: jan.nijtmans
2022-11-16
10:49 Ticket [da63e4c1ef] Crash in Tcl_WriteChars() status still Open with 4 other changes artifact: daf3a44a9a user: jan.nijtmans
10:16 New ticket [da63e4c1ef]. artifact: 19f5803f9e user: anonymous

Ticket UUID: da63e4c1efcfc3e68fdc4527df6a8109e1eac348
Title: Crash in Tcl_WriteChars()
Type: Bug Version: 9.0a4
Submitter: anonymous Created on: 2022-11-16 10:16:13
Subsystem: 12. ByteArray Object Assigned To: jan.nijtmans
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2022-11-28 23:13:41
Resolution: Fixed Closed By: jan.nijtmans
    Closed on: 2022-11-28 23:13:41
Description:
Tcl 9.0 crashes in Tcl_WriteChars() when calling TclDecrRefCount(copy)
(in generic/tclIO.c).  Before the crash, the Tcl_Obj *copy has the following content:

copy refcount 0
copy bytes 0x0
copy type 0x1054c77a0
copy type name bytearray

The problem happens in [1] and can be reproduced 
when compiling the tip version of NaviServer with Tcl9.0 
and running then "make test".

Adding "Tcl_IncrRefCount(copy)" after TclNarrowToBytes() helps for NaviServer 
to get past Tcl_WriteChars(), but does not solve the problem 
(as pointed out by Jan).

-gustaf

[1] https://bitbucket.org/naviserver/naviserver/src/c7b93582c076c41508dc7bf342d3fa864d3d6409/nsd/pidfile.c#lines-65
User Comments: jan.nijtmans added on 2022-11-28 23:13:41:

At first sight, the use of TclNarrowToBytes() looked suspicious. Currently there's only one usage left (in "binary format"), and there it's doing exactly the right thing. Maybe not the most efficient way, but that's not enough to leave this ticket open for.

So, closing this ticket.


jan.nijtmans added on 2022-11-23 21:26:26:

Fix committed [3539aef815|here]. Leaving this ticket pending for possible further enhancements.


anonymous added on 2022-11-23 18:04:57:
I've just tested the change in Tcl_WriteChars(), and this works fine for NaviServer.

jan.nijtmans added on 2022-11-23 15:34:14:

First attempt for a fix [58883dde6de7f4a8|here].

Although the fix works, it shows that TIP #601 (about making encoding errors thowing exceptions) was not implemented throughout yet. For example, testcase io-1.6 does the following:

    fconfigure $f -encoding binary
    puts -nonewline $f "a乍\x00"
This is illegal, because the "binary" encoding only accepts bytes while 乍 is not a byte at all. With TIP #601, I expect this test-case to throw an exception. The solution [58883dde6de7f4a8] does this by generating this exception when converting the string to a bytearray.

What would be even better, is when "puts" would write the bytes to the channel up to the error-character (so, just 'a' in this case), and then throw the exception. That part is not done yet in this first attempt.


anonymous added on 2022-11-23 09:38:36:
The problem seems to be, that after

    objPtr = Tcl_NewStringObj(src, len);
    copy = TclNarrowToBytes(objPtr);

objPtr and copy point to the same Tcl_Obj, and
that after the TclDecrRefCount in

    src = (char *) Tcl_GetByteArrayFromObj(copy, &len);
    TclDecrRefCount(objPtr);

also the object pointed to by copy is cleared, such that
the final 

    TclDecrRefCount(copy);

causes the crash. So, it looks to me, that either adding 
one Tcl_IncrRefCount() or removing one of the TclDecrRefCount()
solves the issue. TclNarrowToBytes() seems to return always
the same object, or removing the first TclDecrRefCount(objPtr) seems
ok.

anonymous added on 2022-11-23 08:53:24:
Hmm, the buffer passed to Tcl_WriteChars() does not look problematic to me:

[23/Nov/2022:09:51:05][14150.102ae4580][-main:conf-] Notice: buffer for Tcl_WriteChars (len 6): 31 34 31 35 30 0a

jan.nijtmans added on 2022-11-23 07:56:44:

See also [07563f771].

My guess is that this is introduced with TIP #568: Revise ByteArray Routines To Support Proper Value Extraction