Tcl Source Code

View Ticket
Login
Ticket UUID: 756791
Title: [patch]Tcl incorrectly uses ckfree() when freeProc == free()
Type: Bug Version: None
Submitter: landonf Created on: 2003-06-18 19:17:52
Subsystem: 41. Memory Allocation Assigned To: aku
Priority: 9 Immediate Severity: Minor
Status: Closed Last Modified: 2023-10-11 12:58:56
Resolution: Fixed Closed By: chrstphrchvz
    Closed on: 2023-10-11 12:58:56
Description:
Tcl incorrectly uses ckfree() on pointers supplied with a 
freeProc of free()

Fix attached, explanation below.

Prototype for Tcl_SetResult:
Tcl_SetResult(interp, string, freeProc)

Tcl_SetResult allows one to specify any custom free function 
that matches the Tcl_FreeProc prototype, or one of 
TCL_VOLATILE, TCL_STATIC, or TCL_DYNAMIC.

If one specifies TCL_DYNAMIC, it is assumed that the string 
pointer is owned by the Tcl allocator, and ckfree() is used to 
free the allocated memory.

However, if free() is specified, ckfree() is ALSO used to free 
the allocated memory. This is incorrect, as ckfree() can not 
be used on memory allocated by malloc.

        if ((iPtr->freeProc == TCL_DYNAMIC)
                || (iPtr->freeProc == (Tcl_FreeProc *) 
free)) {
ckfree(iPtr->result);
}

When looking through the code, I found that this error was 
propagated in numerous other locations. Attached is a fix. In 
all cases, the above if conditional has been changed to 
remove the test for iPtr->freeProc == (Tcl_FreeProc *) 
free. In example:
if (iPtr->freeProc == TCL_DYNAMIC) {
...
}

Detailed problem information follows:

Tcl_DStringGetResult(interp, dsPtr):
If iPtr->freeProc is either TCL_DYNAMIC or free, dsPtr-
>string is set to iPtr->result. Later, when Tcl_DStringFree() 
is called, ckfree() will be called on dsPtr->string.

Tcl_Release(clientData):
If Tcl_EventuallyFree has been called on the pointer passed 
to Tcl_Release, refPtr->mustFree will be set, and refPtr-
>freeProc will be set to the free function given to 
Tcl_EventuallyFree. If refPtr->freeProc is either 
TCL_DYNAMIC or free, ckfree(clientData) will be called.

Tcl_EventuallyFree(clientData, freeProc):
If there is no reference in the refArray for the clientData 
pointer, clientData is immediately freed using the supplied 
freeProc, unless freeProc == free() or TCL_DYNAMIC, and 
then, ckfree(clientData) is called.

Tcl_DiscardResult(statePtr)
If Tcl_SetResult was called with a freeProc of free, 
Tcl_SaveResult(interp, statePtr) will set statePtr->freeProc 
to iPtr->freeProc, and statePtr->result to iPtr->result. When 
Tcl_DiscardResult is called on this statePtr, if statePtr-
>freeProc is TCL_DYNAMIC or free(), ckfree() is called on 
statPtr->result.

Tcl_SetResult(interp, string, freeProc)
If the old interp->freeProc is TCL_DYNAMIC or free(), ckfree 
is called.

Tcl_SetObjResult(interp, objPtr)
If interp->result && interp->freeProc are not NULL, and 
interp->freeProc is either TCL_DYNAMIC or free(), ckfree() 
is called.

Tcl_GetObjResult(interp):
If interp->result && interp->freeProc are not NULL, and 
interp->freeProc is either TCL_DYNAMIC or free(), ckfree() 
is called.

Tcl_FreeResult(interp):
If interp->freeProc is not NULL, and interp->freeProc is 
either TCL_DYNAMIC or free(), ckfree() is called.
User Comments: chrstphrchvz added on 2023-10-11 12:58:56:

There is still an instance of this issue in Tk: https://core.tcl-lang.org/tk/info/9675dd5916ba


hobbs added on 2003-07-17 04:25:32:
Logged In: YES 
user_id=72656

patch had one bug.  commited fixed for 8.5a and 8.4.4.

landonf added on 2003-06-19 02:17:52:

File Added - 53476: tcl-diff-ckfree.diff

Attachments: