Tcl Source Code

View Ticket
Login
Ticket UUID: 3084489
Title: Serious issue: Tcl_DuplicateObj isn't making a copy?
Type: Bug Version: obsolete: 8.5.7
Submitter: Created on: 2010-10-10 00:43:20
Subsystem: 10. Objects Assigned To: msofer
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2010-10-24 18:20:03
Resolution: Invalid Closed By: sf-robot
    Closed on: 2010-10-24 11:20:03
Description:
http://mkextensions.sourceforge.net/mkGeneric13.htm package provides C commands called lminus and linter.  Under Tcl 8.4 the commands work as expected.  Under Tcl 8.5.7 (running in AOLserver 4.5 on Windows, have not tested on any other platform), providing a pure tcl list (no string rep) as an argument to lminus will result in having the original list's list structure resorted.  (In the scenario in which I discovered this, I actually see the string rep retain the original sequence even as list commands return data in different sequence from its string rep but I don't have a simple test case for that side-effect).

As far as I can tell by looking at the source for this command, the first thing it does is Tcl_DuplicateObj (arvg[1]) (it uses a _DOB macro) and then performs its sort operation on the resulting object.

Here is Tcl code you can use to replicate this problem:
set listA [list c b a]
set listB [list c b a z]
lminus $listB $listA
lindex $listA 0
- will return a instead of c

Again lists must be pure. If you do set listA "c b a", the problem does not occur.

Feel free to email to [email protected] with any questions
User Comments: sf-robot added on 2010-10-24 18:20:03:
This Tracker item was closed automatically by the system. It was
previously set to a Pending status, and the original submitter
did not respond within 14 days (the time period specified by
the administrator of this Tracker).

msofer added on 2010-10-12 05:10:13:
The problem is that the C-array returned by TLOGE is meant to be only for reading, and this app is WRITING to it (sorting the elements in place). Again, TLOGE's 8.5 man page is clear: "The memory pointed to is
managed by Tcl and should not be freed or written to by the caller."

The 8.4 man page refers only not freeing the mem, so this usage was not explicitly invalid in 8.4.

The solution is to make your own copy: Tcl_NewListObj(...), then sort that in place.

added on 2010-10-11 22:40:54:
See source I uploaded starting on line 1133.  The code doesn't make any calls to any private APIs and works fine in 8.4.  It first calls Tcl_DuplicateObj (_DOB) and only then Tcl_ListObjGetElements (_LOGE) and then qsort.

added on 2010-10-11 22:34:16:

File Added - 389611: mkGeneric13.c

ferrieux added on 2010-10-10 22:50:10:
Oh you're right Miguel ! I was saying this from the core's POV, not the extension...
Certainly didn't want to dent the OP's motivation to file a bug report to mk :)

msofer added on 2010-10-10 20:31:31:
Internal workings of internal reps is ... indeed internal, not part of the api :P 

You should not write to the intReps of any obj, except through the api. Or be prepared to update your code if/when internal workings change. 

As to the "nasty things": this is done to avoid having to copy things over when you just want to get a list obj that is protected against shimmering, and do it cheaply (without copying).

ferrieux added on 2010-10-10 20:10:21:
Indeed that's an mk bug, but we have to admit that the Tcl core does nasty tricks with lists. Indeed, the List internal repr has its own level of refcounting, and the dupProc of the List type uses this to do as little work as reasonable: it only shares the internal rep, upping the refcount ! A secondary consequence is that (!Tcl_IsShared) does not allow to modify in place; the deeper test on listRepPtr->refCount is needed...

As a result, all functions that do copy-on-write on lists *must* use more explicit duplication at the deeper level of intreps, eg by calling NewListIntRep. None of this is discussed in ListObj." by the way :(

msofer added on 2010-10-10 18:18:41:
This is almost certainly a bug in mk stuff, not Tcl. Please report to that project, or provide evidence that it is a Tcl problem.

I could not easily find the source for lminus, so can't tell for sure. But here's my guess: there is a call of TclListObjGetElements, and then a sort is done in place. This is NOT a valid usage. To quote the manual http://www.tcl.tk/man/tcl8.5/TclLib/ListObj.htm: "The memory pointed to is managed by Tcl and should not be freed or written to by the caller."

Attachments: