[tcljava-dev] Patch: exception during 'string is ...'
Brought to you by:
mdejong
From: Tom P. <tpo...@ny...> - 2003-10-05 19:47:05
|
This patch fixes an exception thrown during 'string is ...', when a zero length value is compared. E.g. % string is integer "" Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0 at java.lang.String.charAt(String.java:511) at tcl.lang.StringCmd.cmdProc(StringCmd.java:458) With the patch, you get: % string is integer "" 1 % string is integer -strict "" 0 This patch is against the 1.3.1 release code. The patch simply adds an 'else' block at line 359 encompassing the following switch block. log entry: * src/jacl/tcl/lang/StringCmd.java: fix StringIndexOutOfBoundsException during 'string is' processing when value is zero length. -- Tom Poindexter tpo...@ny... http://www.nyx.net/~tpoindex/ --- jacl1.3.1/src/jacl/tcl/lang/StringCmd.java 2003-07-25 02:45:06.000000000 -0600 +++ jacl1.3.1.tp/src/jacl/tcl/lang/StringCmd.java 2003-09-29 15:31:03.000000000 -0600 @@ -355,193 +355,194 @@ if (length1 == 0) { if (strict) { result = false; - } - } + } + } else { - switch (index) { - case STR_IS_BOOL: - case STR_IS_TRUE: - case STR_IS_FALSE: { - if (obj.getInternalRep() instanceof TclBoolean) { - if (((index == STR_IS_TRUE) && - !TclBoolean.get(interp, obj)) || - ((index == STR_IS_FALSE) && - TclBoolean.get(interp, obj))) { - result = false; - } - } else { - try { - boolean i = TclBoolean.get(null, obj); - if (((index == STR_IS_TRUE) && !i) || - ((index == STR_IS_FALSE) && i)) { + switch (index) { + case STR_IS_BOOL: + case STR_IS_TRUE: + case STR_IS_FALSE: { + if (obj.getInternalRep() instanceof TclBoolean) { + if (((index == STR_IS_TRUE) && + !TclBoolean.get(interp, obj)) || + ((index == STR_IS_FALSE) && + TclBoolean.get(interp, obj))) { result = false; } - } catch (TclException e) { - result = false; + } else { + try { + boolean i = TclBoolean.get(null, obj); + if (((index == STR_IS_TRUE) && !i) || + ((index == STR_IS_FALSE) && i)) { + result = false; + } + } catch (TclException e) { + result = false; + } } - } - break; - } - case STR_IS_DOUBLE: { - if ((obj.getInternalRep() instanceof TclDouble) || - (obj.getInternalRep() instanceof TclInteger)) { break; } + case STR_IS_DOUBLE: { + if ((obj.getInternalRep() instanceof TclDouble) || + (obj.getInternalRep() instanceof TclInteger)) { + break; + } - // This is adapted from Tcl_GetDouble - // - // The danger in this function is that - // "12345678901234567890" is an acceptable 'double', - // but will later be interp'd as an int by something - // like [expr]. Therefore, we check to see if it looks - // like an int, and if so we do a range check on it. - // If strtoul gets to the end, we know we either - // received an acceptable int, or over/underflow + // This is adapted from Tcl_GetDouble + // + // The danger in this function is that + // "12345678901234567890" is an acceptable 'double', + // but will later be interp'd as an int by something + // like [expr]. Therefore, we check to see if it looks + // like an int, and if so we do a range check on it. + // If strtoul gets to the end, we know we either + // received an acceptable int, or over/underflow + + if (Expression.looksLikeInt(string1, length1, 0)) { + char c = string1.charAt(0); + int signIx = (c == '-' || c == '+') ? 1 : 0; + StrtoulResult res = Util.strtoul(string1, signIx, 0); + if (res.index == length1) { + if (res.errno == TCL.INTEGER_RANGE) { + result = false; + failat = -1; + } + break; + } + } - if (Expression.looksLikeInt(string1, length1, 0)) { char c = string1.charAt(0); int signIx = (c == '-' || c == '+') ? 1 : 0; - StrtoulResult res = Util.strtoul(string1, signIx, 0); - if (res.index == length1) { - if (res.errno == TCL.INTEGER_RANGE) { - result = false; - failat = -1; - } - break; - } - } + StrtodResult res = Util.strtod(string1, signIx); + if (res.errno == TCL.DOUBLE_RANGE) { + // if (errno == ERANGE), then it was an over/underflow + // problem, but in this method, we only want to know + // yes or no, so bad flow returns 0 (false) and sets + // the failVarObj to the string length. - char c = string1.charAt(0); - int signIx = (c == '-' || c == '+') ? 1 : 0; - StrtodResult res = Util.strtod(string1, signIx); - if (res.errno == TCL.DOUBLE_RANGE) { - // if (errno == ERANGE), then it was an over/underflow - // problem, but in this method, we only want to know - // yes or no, so bad flow returns 0 (false) and sets - // the failVarObj to the string length. - - result = false; - failat = -1; - } else if (res.index == 0) { - // In this case, nothing like a number was found - - result = false; - failat = 0; - } else { - // Go onto SPACE, since we are - // allowed trailing whitespace - - failat = res.index; - for (int i = res.index; i<length1; i++) { - if (!Character.isWhitespace(string1.charAt(i))) { - result = false; - break; + result = false; + failat = -1; + } else if (res.index == 0) { + // In this case, nothing like a number was found + + result = false; + failat = 0; + } else { + // Go onto SPACE, since we are + // allowed trailing whitespace + + failat = res.index; + for (int i = res.index; i<length1; i++) { + if (!Character.isWhitespace(string1.charAt(i))) { + result = false; + break; + } } } - } - break; - } - case STR_IS_INT: { - if (obj.getInternalRep() instanceof TclInteger) { - break; - } - boolean isInteger = true; - try { - TclInteger.get(null, obj); - } catch (TclException e) { - isInteger = false; - } - if (isInteger) { break; } + case STR_IS_INT: { + if (obj.getInternalRep() instanceof TclInteger) { + break; + } + boolean isInteger = true; + try { + TclInteger.get(null, obj); + } catch (TclException e) { + isInteger = false; + } + if (isInteger) { + break; + } - char c = string1.charAt(0); - int signIx = (c == '-' || c == '+') ? 1 : 0; - StrtoulResult res = Util.strtoul(string1, signIx, 0); - if (res.errno == TCL.INTEGER_RANGE) { - // if (errno == ERANGE), then it was an over/underflow - // problem, but in this method, we only want to know - // yes or no, so bad flow returns false and sets - // the failVarObj to the string length. - - result = false; - failat = -1; - } else if (res.index == 0) { - // In this case, nothing like a number was found - - result = false; - failat = 0; - } else { - // Go onto SPACE, since we are - // allowed trailing whitespace - - failat = res.index; - for (int i = res.index; i<length1; i++) { - if (!Character.isWhitespace(string1.charAt(i))) { - result = false; - break; + char c = string1.charAt(0); + int signIx = (c == '-' || c == '+') ? 1 : 0; + StrtoulResult res = Util.strtoul(string1, signIx, 0); + if (res.errno == TCL.INTEGER_RANGE) { + // if (errno == ERANGE), then it was an over/underflow + // problem, but in this method, we only want to know + // yes or no, so bad flow returns false and sets + // the failVarObj to the string length. + + result = false; + failat = -1; + } else if (res.index == 0) { + // In this case, nothing like a number was found + + result = false; + failat = 0; + } else { + // Go onto SPACE, since we are + // allowed trailing whitespace + + failat = res.index; + for (int i = res.index; i<length1; i++) { + if (!Character.isWhitespace(string1.charAt(i))) { + result = false; + break; + } } } + break; } - break; - } - default: { - for (failat = 0; failat < length1; failat++) { - char c = string1.charAt(failat); - switch (index) { - case STR_IS_ASCII: - // This is a valid check in unicode, because - // all bytes < 0xC0 are single byte chars - // (but isascii limits that def'n to 0x80). - - result = c < 0x80; - break; - case STR_IS_ALNUM: - result = Character.isLetterOrDigit(c); - break; - case STR_IS_ALPHA: - result = Character.isLetter(c); - break; - case STR_IS_DIGIT: - result = Character.isDigit(c); - break; - case STR_IS_GRAPH: - result = ((1 << Character.getType(c)) - & PRINT_BITS) != 0 - && c != ' '; - break; - case STR_IS_PRINT: - result = ((1 << Character.getType(c)) - & PRINT_BITS) != 0; - break; - case STR_IS_PUNCT: - result = ((1 << Character.getType(c)) - & PUNCT_BITS) != 0; - break; - case STR_IS_UPPER: - result = Character.isUpperCase(c); - break; - case STR_IS_SPACE: - result = Character.isWhitespace(c); - break; - case STR_IS_CONTROL: - result = Character.isISOControl(c); - break; - case STR_IS_LOWER: - result = Character.isLowerCase(c); - break; - case STR_IS_WORD: - result = ((1 << Character.getType(c)) - & WORD_BITS) != 0; - break; - case STR_IS_XDIGIT: - result = Character.digit(c, 16) >= 0; + default: { + for (failat = 0; failat < length1; failat++) { + char c = string1.charAt(failat); + switch (index) { + case STR_IS_ASCII: + // This is a valid check in unicode, because + // all bytes < 0xC0 are single byte chars + // (but isascii limits that def'n to 0x80). + + result = c < 0x80; + break; + case STR_IS_ALNUM: + result = Character.isLetterOrDigit(c); + break; + case STR_IS_ALPHA: + result = Character.isLetter(c); + break; + case STR_IS_DIGIT: + result = Character.isDigit(c); + break; + case STR_IS_GRAPH: + result = ((1 << Character.getType(c)) + & PRINT_BITS) != 0 + && c != ' '; + break; + case STR_IS_PRINT: + result = ((1 << Character.getType(c)) + & PRINT_BITS) != 0; + break; + case STR_IS_PUNCT: + result = ((1 << Character.getType(c)) + & PUNCT_BITS) != 0; + break; + case STR_IS_UPPER: + result = Character.isUpperCase(c); + break; + case STR_IS_SPACE: + result = Character.isWhitespace(c); + break; + case STR_IS_CONTROL: + result = Character.isISOControl(c); + break; + case STR_IS_LOWER: + result = Character.isLowerCase(c); + break; + case STR_IS_WORD: + result = ((1 << Character.getType(c)) + & WORD_BITS) != 0; + break; + case STR_IS_XDIGIT: + result = Character.digit(c, 16) >= 0; + break; + default: + throw new TclRuntimeError("unimplemented"); + } + if (!result) { break; - default: - throw new TclRuntimeError("unimplemented"); - } - if (!result) { - break; + } } } } |