diff options
| author | apnadkarni <apnmbx-wits@yahoo.com> | 2023-04-24 10:02:23 (GMT) |
|---|---|---|
| committer | apnadkarni <apnmbx-wits@yahoo.com> | 2023-04-24 10:02:23 (GMT) |
| commit | ef5af053661a12ed001550d36fd4f7b22266c7fa (patch) | |
| tree | ca0a4d53eb969825184e4314e6841c8a152cc3ab /generic/tclScan.c | |
| parent | f5125db22b057658b3dbb285a53fc3a4f50e281d (diff) | |
| download | tcl-ef5af053661a12ed001550d36fd4f7b22266c7fa.zip tcl-ef5af053661a12ed001550d36fd4f7b22266c7fa.tar.gz tcl-ef5af053661a12ed001550d36fd4f7b22266c7fa.tar.bz2 | |
Fix for bug [d4ede611a7] (scan)
Diffstat (limited to 'generic/tclScan.c')
| -rw-r--r-- | generic/tclScan.c | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/generic/tclScan.c b/generic/tclScan.c index 04e27f7..07daadd 100644 --- a/generic/tclScan.c +++ b/generic/tclScan.c @@ -11,6 +11,7 @@ #include "tclInt.h" #include "tclTomMath.h" +#include <assert.h> /* * Flag values used by Tcl_ScanObjCmd. @@ -352,7 +353,20 @@ ValidateFormat( */ if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */ - long longVal = strtoul(format-1, (char **) &format, 10); /* INTL: "C" locale. */ + Tcl_WideInt wide; + wide = strtoll(format-1, (char **) &format, 10); /* INTL: "C" locale. */ + /* Note wide >= 0 because of isdigit check above */ + if (wide >= TCL_SIZE_MAX) { + Tcl_SetObjResult( + interp, + Tcl_ObjPrintf("specified field width %" TCL_LL_MODIFIER + "d exceeds limit %" TCL_SIZE_MODIFIER "d.", + wide, + (Tcl_Size)TCL_SIZE_MAX-1)); + Tcl_SetErrorCode( + interp, "TCL", "FORMAT", "WIDTHLIMIT", NULL); + goto error; + } flags |= SCAN_WIDTH; format += TclUtfToUniChar(format, &ch); } @@ -675,6 +689,7 @@ Tcl_ScanObjCmd( format += TclUtfToUniChar(format, &ch); } else if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */ char *formatEnd; + /* Note currently XPG3 range limited to INT_MAX to match type of objc */ value = strtoul(format-1, &formatEnd, 10);/* INTL: "C" locale. */ if (*formatEnd == '$') { format = formatEnd+1; @@ -688,7 +703,10 @@ Tcl_ScanObjCmd( */ if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */ - width = (int) strtoul(format-1, (char **) &format, 10);/* INTL: "C" locale. */ + Tcl_WideInt wide; + wide = strtoll(format-1, (char **) &format, 10); /* INTL: "C" locale. */ + assert(wide <= TCL_SIZE_MAX); /* Else ValidateFormat should've error'ed */ + width = (Tcl_Size)wide; format += TclUtfToUniChar(format, &ch); } else { width = 0; @@ -1078,9 +1096,9 @@ Tcl_ScanObjCmd( Tcl_Obj *emptyObj = Tcl_NewObj(); Tcl_IncrRefCount(emptyObj); TclNewObj(objPtr); - for (i = 0; i < totalVars; i++) { + for (i = 0; code == TCL_OK && i < totalVars; i++) { if (objs[i] != NULL) { - Tcl_ListObjAppendElement(NULL, objPtr, objs[i]); + code = Tcl_ListObjAppendElement(interp, objPtr, objs[i]); Tcl_DecrRefCount(objs[i]); } else { /* @@ -1088,10 +1106,20 @@ Tcl_ScanObjCmd( * empty strings for these. */ - Tcl_ListObjAppendElement(NULL, objPtr, emptyObj); + code = Tcl_ListObjAppendElement(interp, objPtr, emptyObj); } } - Tcl_IncrRefCount(emptyObj); + Tcl_DecrRefCount(emptyObj); + if (code != TCL_OK) { + /* If error'ed out, free up remaining. i contains last index freed */ + while (++i < totalVars) { + if (objs[i] != NULL) { + Tcl_DecrRefCount(objs[i]); + } + } + Tcl_DecrRefCount(objPtr); + objPtr = NULL; + } } if (objs != NULL) { Tcl_Free(objs); |
