Tcl Source Code

Ticket Change Details
Login
Overview

Artifact ID: f9284911b307fca852de228e524c077582fd0321
Ticket: 578155d5a19b348dc1a9fe96cc2c067a59326a89
Very rare bug (segfault) if set variable (with error case) using self-releasable object as new value
User & Date: sebres 2017-07-14 10:20:42
Changes

  1. icomment:
    Still one argument against this code at all - if caller want to release ownership of the object (should not hold own reference anymore after set variable, the caller should currently take care by the decreasing of it.<br/>
    Especially in the error case of <code>Tcl_ObjSetVar2</code> (because this time it should then always do it). How it can be sure, that <code>Tcl_ObjSetVar2</code> did it not already?
    So for example:
    <code><pre>
    /* we get someValue from somewhere and take ownership of reference now */
    someValue = TransmitObjFromSomewhere(...);
    ...
    if (!Tcl_ObjSetVar2(interp, varName, NULL, someValue, ...)) {
      /* [**BAD**] error case - decrease and return */
      Tcl_DecrRefCount(someValue);
      /* [**/BAD**] */
      return ...;
    }
    /* do somewhat else also, e. g. using this object, for example: */
    ... Tcl_GetString(someValue) ...
    
    /* we are ready here, release our ownership (further in var) */
    Tcl_DecrRefCount(someValue);
    return ...;
    
    </pre></code>
    
    But currently we cannot do this sane...<br/>
    I mean the code enclosed between <code>[**BAD**]...[**/BAD**]</code>.<br/>
    Because we can be not sure what happens with reference in <code>Tcl_ObjSetVar2</code>.
    
    Possibly we should introduce a new flag (TCL_OWN_OBJREF) like here:
    <code><pre>
    <b style="color:gray">// tcl.h:</b>
    
    <b style="color:green">+ /* Indicate the object reference supplied to Tcl_ObjSetVar2 etc should be not owned by caller anymore */</b>
    <b style="color:green">+ #define TCL_OWN_OBJREF           0x800000</b>
    
    <b style="color:gray">// everywhere where expected to transmit the reference ownership to var:</b>
    
    <b style="color:red">- Tcl_ObjSetVar2(interp, varName, NULL, someValue, TCL_LEAVE_ERR_MSG);</b>
    <b style="color:red">- Tcl_DecrRefCount(someValue);</b>
    <b style="color:green">+ Tcl_ObjSetVar2(interp, varName, NULL, someValue, TCL_OWN_OBJREF | TCL_LEAVE_ERR_MSG);</b>
    </pre></code>
    
    It could then set the variable value with decreasing of the refCount by variable assignment routines (but always, not only in error case if refCount was 0).
    
    IMHO only this would be the right way, to make it sane.
    
  2. login: "sebres"
  3. mimetype: "text/x-fossil-wiki"