Overview
Artifact ID: | d47de8c7074021b030c1651fec15ff49d76661a6 |
---|---|
Ticket: | 578155d5a19b348dc1a9fe96cc2c067a59326a89
Very rare bug (segfault) if set variable (with error case) using self-releasable object as new value |
User & Date: | sebres 2017-07-12 19:15:40 |
Changes
- assignee changed to: "nobody"
- closer changed to: "nobody"
- cmimetype changed to: "text/x-fossil-wiki"
- comment changed to:
I found a very rare but very annoying bug (segfault), if variable will set for example using Tcl_ObjSetVar2 or similar.<br/> In result it belongs to very old check-in [510663a99e3a096bb7bab7314eb59fc805335318] from 2005.<br/> I had this bug sometimes very-very sporadically, so I executed one of my tcl-service under debugger until it not occurred again. <h2>PoC:</h2> <ul> <li> somewhat will set var varName to newValue with `Tcl_ObjSetVar2`, `Tcl_SetVar2Ex` or similar (e. g. with flag TCL_LEAVE_ERR_MSG);</li> <li> thereby this object (newValue) was <b>only once referenced</b> (somewhere in interpreter state, e. g. something in sub-list or sub-dictionary of interp-result, etc.). Emphasis on "only once", so newValue->refCount is 1.</li> <li> the set produces an interim error (for example something going wrong by the resolving of the varname, or in trace, etc)</li> <li> by the following throwing of the error-state to interp (result, errorInfo, errorCode) this will automatically decrease old object of interp-state, which can also remove all children</li> <li> thus the <b>newValue->refCount will be implicit decreased to 0</b>, and object newValue will be released.</li> <li> the problem is then the code like here - <a href="http://core.tcl.tk/tcl/artifact/3293a2dbff528bd4?ln=1458">artifact/3293a2dbff528bd4?ln=1458</a> or <a href="http://core.tcl.tk/tcl/artifact/3293a2dbff528bd4?ln=1517">artifact/3293a2dbff528bd4?ln=1517</a>, because it tries to access already released object newValue (that does not exists anymore!) and decrease its reference again and then tries to release it again!</li> </ul> Why I think, that is a bug? Because only the caller of `Tcl_ObjSetVar2` really know that the reference of this object should be decremented or not. And because explicit decreasing inside `Tcl_ObjSetVar2` is very unexpected behavior, IMHO (because rather increased or unmodified).<br/> Otherwise the call of `Tcl_ObjSetVar2`, `Tcl_SetVar2Ex` or similar should <b>always</b> look like this: <code><pre> Tcl_IncrRefCount(newValue); Tcl_ObjSetVar2(interp, varName, NULL, newValue, ...) Tcl_DecrRefCount(newValue); </pre></code> But in this case the <a href="http://core.tcl.tk/tcl/artifact/3293a2dbff528bd4?ln=1517">above-mentioned code</a> is totally unnecessary (because newValuePtr->refCount will be never 0).<br/> And then this check-in no longer makes sense at all. So I'm desperate, how it can be fixed plausible resp. totally backwards compatible (this check-in is older as 10 years). Suggestions are welcome...
- foundin changed to: ">= 8.5"
- is_private changed to: "0"
- login: "sebres"
- priority changed to: "5 Medium"
- resolution changed to: "None"
- severity changed to: "Critical"
- status changed to: "Open"
- submitter changed to: "sebres"
- subsystem changed to: "07. Variables"
- title changed to:
Very rare bug (segfault) if set variable (with error case) using self-releasable object as new value
- type changed to: "Bug"