Bug 44876 - ArrayIndexOutOfBoundsException thrown from TABLESWITCH.initFromFile
Summary: ArrayIndexOutOfBoundsException thrown from TABLESWITCH.initFromFile
Alias: None
Product: BCEL - Now in Jira
Classification: Unclassified
Component: Main (show other bugs)
Version: 5.2
Hardware: PC Windows XP
: P2 normal
Target Milestone: ---
Assignee: issues@commons.apache.org
Keywords: PatchAvailable
Depends on:
Reported: 2008-04-25 13:00 UTC by Timothy Alper
Modified: 2010-01-10 13:27 UTC (History)
0 users

Proposed patch (754 bytes, patch)
2008-04-25 13:00 UTC, Timothy Alper
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Timothy Alper 2008-04-25 13:00:34 UTC
Created attachment 21856 [details]
Proposed patch

BCEL throws the ArrayIndexOutOfBoundsException when trying to construct a new org.apache.bcel.generic.MethodGen on a method containing the bytes compiled from the following code:

switch (i) {
  case Integer.MAX_VALUE:
    b = true;

The method that does not handle this corner case correctly is org.apache.bcel.generic.TABLESWITCH.initFromFile(ByteSequence, boolean).
Comment 1 Torsten Curdt 2008-04-28 06:46:04 UTC
Could you please provide the exception or describe the corner case.
It's not exactly obvious why your patch fixes this problem.
Comment 2 Timothy Alper 2008-04-28 08:54:16 UTC
Sorry about that, I was in a bit of a rush.

The corner case is if the low and high values (signed ints) are the same and their value is 0x7fffffff (Integer.MAX_VALUE). This occurs only if there is one case (aside from the default) in the switch and it happens to be MAX_VALUE.

Here's the code in BCEL that causes the problem:

for (int i = low; i <= high; i++) {
  match[i - low] = i; //ArrayIndexOutOfBoundsException thrown here

The loop boundaries are the problem. 'i' is initialized to MAX_VALUE, then match[0] is set correctly to MAX_VALUE, i is incremented causing overflow, since i is still <= MAX_VALUE the loop continues. Then on the next time through the loop (i - low) == (0x80000000 - 0x7fffffff) == 1, but match[1] is invalid because it was initialized to have only 1 element by "match_length = high - low + 1" and "match = new int[match_length]".

As you can see, my patch resolves this corner case and has the added benefit of eliminating an extra for loop.

By the way, the actual exception that finally bubbles up isn't too helpful because the ArrayIndexOutOfBoundsException gets converted into a ClassGenException without having the whole ArrayIndexOutOfBoundsException wrapped. Anyway, for the sake of being complete, it looks like this:
java.lang.ArrayIndexOutOfBoundsException: 1
        at org.apache.bcel.generic.Instruction.readInstruction(Instruction.java:177)
        at org.apache.bcel.generic.MethodGen.<init>(MethodGen.java:164)
        at ...
Comment 3 Torsten Curdt 2010-01-10 13:27:51 UTC
Fixed. Thx.