summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2010-01-18 09:50:57 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2010-01-18 09:50:57 (GMT)
commita01c81316c6cdad00e46f0224b7bfe4b52078ad8 (patch)
treeafad03bce4d41a8696008ebfc149fef7ca4e8d99
parentb849702961a75aea821820214c8aac96f91a6c7d (diff)
downloadtcl-a01c81316c6cdad00e46f0224b7bfe4b52078ad8.zip
tcl-a01c81316c6cdad00e46f0224b7bfe4b52078ad8.tar.gz
tcl-a01c81316c6cdad00e46f0224b7bfe4b52078ad8.tar.bz2
[Bug 2932421]: Make [format] less likely to smash intreps.
-rw-r--r--ChangeLog9
-rw-r--r--generic/tclStringObj.c54
2 files changed, 41 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog
index 0c2aaaa..dfd53a3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,13 @@
+2010-01-18 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclStringObj.c (Tcl_AppendFormatToObj): [Bug 2932421]: Stop
+ the [format] command from causing argument objects to change their
+ internal representation when not needed. Thanks to Alexandre Ferrieux
+ for this fix.
+
2010-01-06 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tclCompExpr.c:warning: array subscript has type 'char'
+ * generic/tclCompExpr.c: Warning: array subscript has type 'char'
* generic/tclPkg.c:
* libtommath/bn_mp_read_radix.c:
* unix/tclUnixCompat.c: Fix gcc warning: signed and unsigned type
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c
index 2289659..ffa51f8 100644
--- a/generic/tclStringObj.c
+++ b/generic/tclStringObj.c
@@ -33,7 +33,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclStringObj.c,v 1.70.2.18 2009/08/27 19:33:24 dgp Exp $ */
+ * RCS: @(#) $Id: tclStringObj.c,v 1.70.2.19 2010/01/18 09:50:57 dkf Exp $ */
#include "tclInt.h"
#include "tommath.h"
@@ -2018,6 +2018,7 @@ Tcl_AppendFormatToObj(
*/
segment = objv[objIndex];
+ numChars = -1;
if (ch == 'i') {
ch = 'd';
}
@@ -2025,15 +2026,17 @@ Tcl_AppendFormatToObj(
case '\0':
msg = "format string ended in middle of field specifier";
goto errorMsg;
- case 's': {
- numChars = Tcl_GetCharLength(segment);
- if (gotPrecision && (precision < numChars)) {
- segment = Tcl_GetRange(segment, 0, precision - 1);
- Tcl_IncrRefCount(segment);
- allocSegment = 1;
+ case 's':
+ if (gotPrecision) {
+ numChars = Tcl_GetCharLength(segment);
+ if (precision < numChars) {
+ segment = Tcl_GetRange(segment, 0, precision - 1);
+ numChars = precision;
+ Tcl_IncrRefCount(segment);
+ allocSegment = 1;
+ }
}
break;
- }
case 'c': {
char buf[TCL_UTF_MAX];
int code, length;
@@ -2406,19 +2409,26 @@ Tcl_AppendFormatToObj(
}
}
- numChars = Tcl_GetCharLength(segment);
- if (!gotMinus) {
- if (numChars < width) {
- limit -= (width - numChars);
+ if (width > 0) {
+ if (numChars < 0) {
+ numChars = Tcl_GetCharLength(segment);
}
- while (numChars < width) {
- Tcl_AppendToObj(appendObj, (gotZero ? "0" : " "), 1);
- numChars++;
+ if (!gotMinus) {
+ if (numChars < width) {
+ limit -= (width - numChars);
+ }
+ while (numChars < width) {
+ Tcl_AppendToObj(appendObj, (gotZero ? "0" : " "), 1);
+ numChars++;
+ }
}
}
Tcl_GetStringFromObj(segment, &segmentNumBytes);
if (segmentNumBytes > limit) {
+ if (allocSegment) {
+ Tcl_DecrRefCount(segment);
+ }
msg = overflow;
goto errorMsg;
}
@@ -2427,12 +2437,14 @@ Tcl_AppendFormatToObj(
if (allocSegment) {
Tcl_DecrRefCount(segment);
}
- if (numChars < width) {
- limit -= (width - numChars);
- }
- while (numChars < width) {
- Tcl_AppendToObj(appendObj, (gotZero ? "0" : " "), 1);
- numChars++;
+ if (width > 0) {
+ if (numChars < width) {
+ limit -= (width - numChars);
+ }
+ while (numChars < width) {
+ Tcl_AppendToObj(appendObj, (gotZero ? "0" : " "), 1);
+ numChars++;
+ }
}
objIndex += gotSequential;