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 |
