Tcl Source Code

View Ticket
Login
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: (text/x-fossil-plain)
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: (text/x-fossil-wiki)
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: (text/x-fossil-wiki)
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: (text/x-fossil-wiki)
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:
<pre>
    fconfigure $f -encoding binary
    puts -nonewline $f "a乍\x00"
</pre>
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: (text/x-fossil-wiki)
See also [07563f771].

My guess is that this is introduced with [https://core.tcl-lang.org/tips/doc/trunk/tip/568.md|TIP #568]: Revise ByteArray Routines To Support Proper Value Extraction