[Tcl-bugs] [Tcl] (stu) tkt (Open): StringObj.3 Tcl_ObjPrintf inaccuracies

Previous Topic Next Topic
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

[Tcl-bugs] [Tcl] (stu) tkt (Open): StringObj.3 Tcl_ObjPrintf inaccuracies

Automated mail by fx, on behalf of [hidden email]

Ticket Change [0d3171c42f1ff28b3ba3b98967e4e04bbfbec707]
  [StringObj.3 Tcl_ObjPrintf inaccuracies]
  By      stu
  For     Tcl
  On      2017-07-08T18:37:03.764
  Details https://core.tcl.tk/tcl/tinfo?name=0d3171c42f1ff28b3ba3b98967e4e04bbfbec707
  Ticket  https://core.tcl.tk/tcl/tktview/2089279fffffffffffffffffffffffffffffffff

Changed Fields
  closer:   nobody
  comment:  StringObj.3 gives this example:  long x = 5;  Tcl_Obj *objPtr =
            Tcl_ObjPrintf("Value is %d", x);

            This is incorrect, because the Tcl_ObjPrintf code will expect an int,
            and use va_arg with int.

            As can be seen in the AppendPrintfToObjVA:  case 'd':  ...
            seekingConversion = 0;  switch (size) {  case -1:  case 0:
            Tcl_ListObjAppendElement(NULL, list, Tcl_NewLongObj((long
            int)va_arg(argList, int)));

            The issue is that if the user uses %d for a long, the va_list will
            have the wrong offset. The example will work in the 1 argument case,
            and even the multiple argument case if sizeof(int) = sizeof(long). It
            however will fail in the case of sizeof(long) > sizeof(int), because
            the va_list will have the wrong offset. Thus you'd be getting parts of
            the integer. This can have disasterous consequences if the offset is
            wrong, because the next va_arg call becomes wrong, which if it's a
            pointer may lead to segfaults.

            Tcl works with some platforms where a long is 64-bit and an int is
            32-bit. #ifdef TCL_WIDE_INT_IS_LONG as I understand it refers to this.

            The next issue is that the format specifiers are not exactly the same
            as the [format] command, and probably shouldn't be.

            The format command uses (as documented) %ld for truncation to a 64-bit
            integer. %lld for no truncation (BigNum) and %d for a 32-bit integer.
            This is incomptible with AppendPrintfToObjVA() (used by
            Tcl_ObjPrintf), because it currently accepts a long for %ld which may
            or may not be 64-bit depending on the platform. The wide and BigNum
            cases are also not handled by AppendPrintfToObjVA(). Thus the
            suggestion in the documentation that Tcl_ObjPrintf has the same syntax
            as the format command are wrong.
  icomment: Just stumbled across this.  See also

            On 32-bit systems:

            Tcl_ObjPrintf("%lld %ld\ ", (long long) 3, (long) 4))  Yields "3 0"

            Tcl_ObjPrintf("%lld %s\ ", (long long) 3, "a"))  Segfaults

            Right now it's hard to have confidence in Tcl_ObjPrintf.  Even if it
            was fixed today the broken version will persist in the wild for a long
            time possibly requiring autoconfery for those who wish to use it with

            Too bad.
  login:    stu
  severity: Minor

See Tcl/Tk development @ http://core.tcl.tk/

Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Tcl-Bugs mailing list
[hidden email]