Tcl Source Code

Ticket Change Details
Login
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

  1. assignee changed to: "nobody"
  2. closer changed to: "nobody"
  3. cmimetype changed to: "text/x-fossil-wiki"
  4. 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...
    
  5. foundin changed to: ">= 8.5"
  6. is_private changed to: "0"
  7. login: "sebres"
  8. priority changed to: "5 Medium"
  9. resolution changed to: "None"
  10. severity changed to: "Critical"
  11. status changed to: "Open"
  12. submitter changed to: "sebres"
  13. subsystem changed to: "07. Variables"
  14. title changed to:
    Very rare bug (segfault) if set variable (with error case) using self-releasable object as new value
    
  15. type changed to: "Bug"