JDK-4699765 : java.text.DigitList throws ArrayOutOfBoundsException
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.text
  • Affected Version: 1.3.1_02
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: solaris_8
  • CPU: sparc
  • Submitted: 2002-06-10
  • Updated: 2003-05-28
  • Resolved: 2003-05-28
Related Reports
Duplicate :  
Description
The method:   java.text.DigitList.fitsIntoLong()

throws ArrayIndexOutOfBoundsException

There is negative indexing occurs to an array that may have no elements:

java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
        at java.text.DigitList.fitsIntoLong(DigitList.java:173)
        at java.text.DecimalFormat.parse(DecimalFormat.java:817)
        at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1201)
        at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:730)
        at java.text.DateFormat.parse(DateFormat.java:322)
        at org.apache.catalina.servlets.DefaultServlet.checkIfHeaders(DefaultSer
vlet.java:754)
        at org.apache.catalina.servlets.DefaultServlet.serveResource(DefaultServ
let.java:1100)
        at org.apache.catalina.servlets.DefaultServlet.doGet(DefaultServlet.java
:520)
	.
	.

The code on the JDK 1.3.1.02 (where this happens): is as follows:

    /**
     * Return true if the number represented by this object can fit into
     * a long.
     * @param isPositive true if this number should be regarded as positive
     * @param ignoreNegativeZero true if -0 should be regarded as identical to
     * +0; otherwise they are considered distinct
     * @return true if this number fits into a Java long
     */
    boolean fitsIntoLong(boolean isPositive, boolean ignoreNegativeZero)
    {
        // Figure out if the result will fit in a long.  We have to
        // first look for nonzero digits after the decimal point;
        // then check the size.  If the digit count is 18 or less, then
        // the value can definitely be represented as a long.  If it is 19
        // then it may be too large.

        // Trim trailing zeros.  This does not change the represented value.
        while (count > 0 && digits[count - 1] == (byte)'0') --count;


'count' is initialized to zero, there is no prior check whether digits has
been initialized, nor what the value of 'count' is.

	

Comments
EVALUATION Name: nl37777 Date: 06/10/2002 Additional information provided by submitter: I am using Tomcat 4.0.1. The bug is not easily reproducible. I don't know the exact circumstances under which Tomcat performs header parsing (especially, because we are generating JSPs and we do not control the headers). We tried running Tomcat on J2RE 1.4, and the bug is as spurious as on 1.3.1_02. Relevant sections from Tomcat's DefaultServlet.java - note the static date format objects: /** * The set of SimpleDateFormat formats to use in getDateHeader(). */ protected static final SimpleDateFormat formats[] = { new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US), new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US), new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) }; protected final static TimeZone gmtZone = TimeZone.getTimeZone("GMT"); /** * GMT timezone - all HTTP dates are on GMT */ static { formats[0].setTimeZone(gmtZone); formats[1].setTimeZone(gmtZone); formats[2].setTimeZone(gmtZone); } [...] protected boolean checkIfHeaders(HttpServletRequest request, HttpServletResponse response, ResourceInfo resourceInfo) throws IOException { [...] String headerValue; [...] // Checking If-Modified-Since headerValue = request.getHeader("If-Modified-Since"); if (headerValue != null) { // If an If-None-Match header has been specified, if modified since // is ignored. if (request.getHeader("If-None-Match") == null) { Date date = null; // Parsing the HTTP Date for (int i = 0; (date == null) && (i < formats.length); i++) { try { date = formats[i].parse(headerValue); } catch (ParseException e) { ; } catch (NumberFormatException e) { ; } } [...] ====================================================================== DigitList initializes digits to "new byte[MAX_COUNT]" during construction. It also ensures that count is always between 0 <= count <= MAX_COUNT. In the single-threaded case, the array access therefore cannot throw an exception. However, DigitList (like the DecimalFormat class, its only client) is not threadsafe. It was never designed this way, and this is documented in the DecimalFormat class description starting from 1.4. As the code above shows, Tomcat is using shared Dateformat instances (which internally use DecimalFormat) without synchronization, so it is likely to run into threading issues. There's another bug report requesting to make DecimalFormat threadsafe, so I'm closing as a duplicate of that one. ###@###.### 2003-05-28 ======================================================================
28-05-2003