Tcl Source Code

Artifact [6d96445469]
Login

Artifact 6d9644546911bcf8404607dd3889da12dc2a50e7:

Attachment "string634856.patch" to ticket [634856ffff] added by hobbs 2002-11-15 02:42:17.
? generic/hobbs
Index: generic/tclGet.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclGet.c,v
retrieving revision 1.7
diff -u -r1.7 tclGet.c
--- generic/tclGet.c	25 Sep 2001 16:23:56 -0000	1.7
+++ generic/tclGet.c	14 Nov 2002 19:36:16 -0000
@@ -46,7 +46,7 @@
     int *intPtr;		/* Place to store converted result. */
 {
     char *end;
-    CONST char *p;
+    CONST char *p = string;
     long i;
 
     /*
@@ -56,7 +56,14 @@
      */
 
     errno = 0;
-    for (p = string; isspace(UCHAR(*p)); p++) {	/* INTL: ISO space. */
+#ifdef TCL_STRTOUL_SIGN_CHECK
+    /*
+     * This special sign check actually causes bad numbers to be allowed
+     * when strtoul.  I can't find a strtoul that doesn't validly handle
+     * signed characters, and the C standard implies that this is all
+     * unnecessary. [Bug #634856]
+     */
+    for ( ; isspace(UCHAR(*p)); p++) {	/* INTL: ISO space. */
 	/* Empty loop body. */
     }
     if (*p == '-') {
@@ -65,9 +72,10 @@
     } else if (*p == '+') {
 	p++;
 	i = strtoul(p, &end, 0); /* INTL: Tcl source. */
-    } else {
+    } else
+#else
 	i = strtoul(p, &end, 0); /* INTL: Tcl source. */
-    }
+#endif
     if (end == p) {
 	badInteger:
         if (interp != (Tcl_Interp *) NULL) {
@@ -135,7 +143,7 @@
     long *longPtr;		/* Place to store converted long result. */
 {
     char *end;
-    CONST char *p;
+    CONST char *p = string;
     long i;
 
     /*
@@ -144,7 +152,8 @@
      */
 
     errno = 0;
-    for (p = string; isspace(UCHAR(*p)); p++) {	/* INTL: ISO space. */
+#ifdef TCL_STRTOUL_SIGN_CHECK
+    for ( ; isspace(UCHAR(*p)); p++) {	/* INTL: ISO space. */
 	/* Empty loop body. */
     }
     if (*p == '-') {
@@ -153,9 +162,10 @@
     } else if (*p == '+') {
 	p++;
 	i = strtoul(p, &end, 0); /* INTL: Tcl source. */
-    } else {
+    } else
+#else
 	i = strtoul(p, &end, 0); /* INTL: Tcl source. */
-    }
+#endif
     if (end == p) {
 	badInteger:
         if (interp != (Tcl_Interp *) NULL) {
Index: generic/tclObj.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclObj.c,v
retrieving revision 1.40
diff -u -r1.40 tclObj.c
--- generic/tclObj.c	24 Aug 2002 01:29:46 -0000	1.40
+++ generic/tclObj.c	14 Nov 2002 19:36:16 -0000
@@ -1794,7 +1794,7 @@
      * Get the string representation. Make it up-to-date if necessary.
      */
 
-    string = Tcl_GetStringFromObj(objPtr, &length);
+    p = string = Tcl_GetStringFromObj(objPtr, &length);
 
     /*
      * Now parse "objPtr"s string as an int. We use an implementation here
@@ -1805,7 +1805,8 @@
      */
 
     errno = 0;
-    for (p = string;  isspace(UCHAR(*p));  p++) { /* INTL: ISO space. */
+#ifdef TCL_STRTOUL_SIGN_CHECK
+    for ( ;  isspace(UCHAR(*p));  p++) { /* INTL: ISO space. */
 	/* Empty loop body. */
     }
     if (*p == '-') {
@@ -1814,9 +1815,10 @@
     } else if (*p == '+') {
 	p++;
 	newLong = strtoul(p, &end, 0);
-    } else {
+    } else
+#else
 	newLong = strtoul(p, &end, 0);
-    }
+#endif
     if (end == p) {
 	badInteger:
 	if (interp != NULL) {
@@ -1865,7 +1867,7 @@
     if ((oldTypePtr != NULL) &&	(oldTypePtr->freeIntRepProc != NULL)) {
 	oldTypePtr->freeIntRepProc(objPtr);
     }
-    
+
     objPtr->internalRep.longValue = newLong;
     objPtr->typePtr = &tclIntType;
     return TCL_OK;
@@ -2147,7 +2149,7 @@
      * Get the string representation. Make it up-to-date if necessary.
      */
 
-    string = Tcl_GetStringFromObj(objPtr, &length);
+    p = string = Tcl_GetStringFromObj(objPtr, &length);
 
     /*
      * Now parse "objPtr"s string as an int. We use an implementation here
@@ -2158,7 +2160,8 @@
      */
 
     errno = 0;
-    for (p = string;  isspace(UCHAR(*p));  p++) { /* INTL: ISO space. */
+#ifdef TCL_STRTOUL_SIGN_CHECK
+    for ( ;  isspace(UCHAR(*p));  p++) { /* INTL: ISO space. */
 	/* Empty loop body. */
     }
     if (*p == '-') {
@@ -2167,9 +2170,10 @@
     } else if (*p == '+') {
 	p++;
 	newWide = strtoull(p, &end, 0);
-    } else {
+    } else
+#else
 	newWide = strtoull(p, &end, 0);
-    }
+#endif
     if (end == p) {
 	badInteger:
 	if (interp != NULL) {
Index: generic/tclUtil.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclUtil.c,v
retrieving revision 1.35
diff -u -r1.35 tclUtil.c
--- generic/tclUtil.c	12 Nov 2002 02:26:40 -0000	1.35
+++ generic/tclUtil.c	14 Nov 2002 19:36:16 -0000
@@ -2406,14 +2406,15 @@
 
     if (length <= 3) {
 	offset = 0;
-    } else if (bytes[3] == '-') {
+    } else if ((length > 4) && (bytes[3] == '-')) {
 	/*
-	 * This is our limited string expression evaluator
+	 * This is our limited string expression evaluator.  Pass everything
+	 * after "end-" to Tcl_GetInt, then reverse for offset.
 	 */
-	if (Tcl_GetInt(interp, bytes+3, &offset) != TCL_OK) {
+	if (Tcl_GetInt(interp, bytes+4, &offset) != TCL_OK) {
 	    return TCL_ERROR;
 	}
-
+	offset = -offset;
     } else {
 	/*
 	 * Conversion failed.  Report the error.
Index: tests/get.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/get.test,v
retrieving revision 1.7
diff -u -r1.7 get.test
--- tests/get.test	15 Feb 2002 23:42:12 -0000	1.7
+++ tests/get.test	14 Nov 2002 19:36:16 -0000
@@ -94,6 +94,24 @@
     list [catch {format %g .000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001} msg] $msg $errorCode
 } {1 {floating-point value too small to represent} {ARITH UNDERFLOW {floating-point value too small to represent}}}
 
+test get-3.1 {Tcl_GetInt(FromObj), bad numbers} {
+    # SF bug #634856
+    set result ""
+    set numbers [list 1 +1 ++1 +-1 -+1 -1 --1 "- +1" "+12345678987654321" "++12345678987654321"]
+    foreach num $numbers {
+	lappend result [catch {format %ld $num} msg] $msg
+    }
+    set result
+} {0 1 0 1 1 {expected integer but got "++1"} 1 {expected integer but got "+-1"} 1 {expected integer but got "-+1"} 0 -1 1 {expected integer but got "--1"} 1 {expected integer but got "- +1"} 0 12345678987654321 1 {expected integer but got "++12345678987654321"}}
+test get-3.2 {Tcl_GetDouble(FromObj), bad numbers} {
+    set result ""
+    set numbers [list 1.0 +1.0 ++1.0 +-1.0 -+1.0 -1.0 --1.0 "- +1.0"]
+    foreach num $numbers {
+	lappend result [catch {format %g $num} msg] $msg
+    }
+    set result
+} {0 1 0 1 1 {expected floating-point number but got "++1.0"} 1 {expected floating-point number but got "+-1.0"} 1 {expected floating-point number but got "-+1.0"} 0 -1 1 {expected floating-point number but got "--1.0"} 1 {expected floating-point number but got "- +1.0"}}
+
 # cleanup
 ::tcltest::cleanupTests
 return
Index: tests/string.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/string.test,v
retrieving revision 1.34
diff -u -r1.34 string.test
--- tests/string.test	29 May 2002 09:09:00 -0000	1.34
+++ tests/string.test	14 Nov 2002 19:36:16 -0000
@@ -574,6 +574,24 @@
     list [string is xdigit -fail var 0123456789\u0061bcdefABCDEFg] $var
 } {0 22}
 
+test string-6.90 {string is integer, bad integers} {
+    # SF bug #634856
+    set result ""
+    set numbers [list 1 +1 ++1 +-1 -+1 -1 --1 "- +1"]
+    foreach num $numbers {
+	lappend result [string is int -strict $num]
+    }
+    set result
+} {1 1 0 0 0 1 0 0}
+test string-6.91 {string is double, bad doubles} {
+    set result ""
+    set numbers [list 1.0 +1.0 ++1.0 +-1.0 -+1.0 -1.0 --1.0 "- +1.0"]
+    foreach num $numbers {
+	lappend result [string is double -strict $num]
+    }
+    set result
+} {1 1 0 0 0 1 0 0}
+
 catch {rename largest_int {}}
 
 test string-7.1 {string last, too few args} {