JDK-4896879 : StringIndexOutOfBoundsException in java.beans.Introspector.getTargetEventInfo()
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.beans
  • Affected Version: 1.4.2
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2003-07-26
  • Updated: 2003-11-03
  • Resolved: 2003-11-03
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0 b28Fixed
Related Reports
Relates :  
Description
Name: rl43681			Date: 07/26/2003


FULL PRODUCT VERSION :
java version "1.4.2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-b28)
Java HotSpot(TM) Client VM (build 1.4.2-b28, mixed mode)

FULL OS VERSION :
Windows 2000 service pack 3

A DESCRIPTION OF THE PROBLEM :
Conditions when the bug appears:
When you implement two classes that inherits from java.beans.Beans and implements an java.util.EventListener like the followings

CLASS 1 : introspector_test.A

package introspector_test;
import java.beans.Beans;
import java.util.EventListener;
import java.util.Vector;
public class A extends Beans implements EventListener{
		Vector bs=new Vector();
		public A() {
		}
		public void addB(B b) {
			bs.addElement(b);
		}
		public void removeB(B b) {
			bs.removeElement(b);
		}
}


CLASS 2 : introspector_test.B
package introspector_test;
import java.beans.Beans;
import java.util.EventListener;
public class B extends Beans implements EventListener {
		java.util.Vector as=new java.util.Vector();
			public B() {
		}
		public void addA(A a) {
			as.addElement(a);
		}
		public void removeA(A a) {
			as.removeElement(a);
		}
}




And third class to let the bug appear:

package introspector_test;
import java.beans.BeanInfo;
import java.beans.Introspector;
public class Main {

	public static void main(String[] args) {
		try {
			BeanInfo info=Introspector.getBeanInfo(A.class);
		}catch(Throwable th1) {
			th1.printStackTrace();
		}
		
	}
}

Running the Introspector like in main() function let it throw an
java.lang.StringIndexOutOfBoundsException
with a stack trace like that:

java.lang.StringIndexOutOfBoundsException: String index out of range: -7
	at java.lang.String.substring(String.java:1444)
	at java.beans.Introspector.getTargetEventInfo(Introspector.java:884)
	at java.beans.Introspector.getBeanInfo(Introspector.java:371)
	at java.beans.Introspector.getBeanInfo(Introspector.java:144)
	at introspector_test.Main.main(Main.java:23)


The exception is at line : 884 of class java.beans.Introspector, in that point your code does like that:

> String eventName = decapitalize(listenerName.substring(0, listenerName.length()-8));


Even if the Beans standard does reccomend to use method names add<event-name>Listener and remove<event-name>Listener
it does not say that i must avoid to name methods with add<...> and remove<.....> starting words,so it is coherent to write
classes like A and B. I think you forget to test if name of add/remove methods ends with the word "Listener" (that is the same stuff you are
cutting with listenerName.length()-8 parameter).



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
CLASS 1 : introspector_test.A

package introspector_test;
import java.beans.Beans;
import java.util.EventListener;
import java.util.Vector;
public class A extends Beans implements EventListener{
		Vector bs=new Vector();
		public A() {
		}
		public void addB(B b) {
			bs.addElement(b);
		}
		public void removeB(B b) {
			bs.removeElement(b);
		}
}


CLASS 2 : introspector_test.B
package introspector_test;
import java.beans.Beans;
import java.util.EventListener;
public class B extends Beans implements EventListener {
		java.util.Vector as=new java.util.Vector();
			public B() {
		}
		public void addA(A a) {
			as.addElement(a);
		}
		public void removeA(A a) {
			as.removeElement(a);
		}
}




And third class to let the bug appear:

package introspector_test;
import java.beans.BeanInfo;
import java.beans.Introspector;
public class Main {

	public static void main(String[] args) {
		try {
			BeanInfo info=Introspector.getBeanInfo(A.class);
		}catch(Throwable th1) {
			th1.printStackTrace();
		}
		
	}
}

Running the Introspector like in main() function let it throw an
java.lang.StringIndexOutOfBoundsException
with a stack trace like that:

java.lang.StringIndexOutOfBoundsException: String index out of range: -7
	at java.lang.String.substring(String.java:1444)
	at java.beans.Introspector.getTargetEventInfo(Introspector.java:884)
	at java.beans.Introspector.getBeanInfo(Introspector.java:371)
	at java.beans.Introspector.getBeanInfo(Introspector.java:144)
	at introspector_test.Main.main(Main.java:23)

The exception is at line : 884 of class java.beans.Introspector, in that point your code does like that:

> String eventName = decapitalize(listenerName.substring(0, listenerName.length()-8));


Even if the Beans standard does reccomend to use method names add<event-name>Listener and remove<event-name>Listener
it does not say that i must avoid to name methods with add<...> and remove<.....> starting words,so it is coherent to write
classes like A and B. I think you forget to test if name of add/remove methods ends with the word "Listener" (that is the same stuff you are
cutting with listenerName.length()-8 parameter).



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
A normal JavaBeans introspection
ACTUAL -
at line 884 of java.beans.Introspector an exception of type java.lang.StringIndexOutOfBoundsException is thrown

ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.StringIndexOutOfBoundsException: String index out of range: -7
	at java.lang.String.substring(String.java:1444)
	at java.beans.Introspector.getTargetEventInfo(Introspector.java:884)
	at java.beans.Introspector.getBeanInfo(Introspector.java:371)
	at java.beans.Introspector.getBeanInfo(Introspector.java:144)
	at introspector_test.Main.main(Main.java:23)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
CLASS 1 : introspector_test.A

package introspector_test;
import java.beans.Beans;
import java.util.EventListener;
import java.util.Vector;
public class A extends Beans implements EventListener{
		Vector bs=new Vector();
		public A() {
		}
		public void addB(B b) {
			bs.addElement(b);
		}
		public void removeB(B b) {
			bs.removeElement(b);
		}
}


CLASS 2 : introspector_test.B
package introspector_test;
import java.beans.Beans;
import java.util.EventListener;
public class B extends Beans implements EventListener {
		java.util.Vector as=new java.util.Vector();
			public B() {
		}
		public void addA(A a) {
			as.addElement(a);
		}
		public void removeA(A a) {
			as.removeElement(a);
		}
}




And third class to let the bug appear:
CLASS 3:

package introspector_test;
import java.beans.BeanInfo;
import java.beans.Introspector;
public class Main {

	public static void main(String[] args) {
		try {
			BeanInfo info=Introspector.getBeanInfo(A.class);
		}catch(Throwable th1) {
			th1.printStackTrace();
		}
		
	}
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Avoid declaring class A and B as implementing java.util.EventListener
(Incident Review ID: 189507) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger tiger-beta FIXED IN: tiger-beta INTEGRATED IN: tiger-b28 tiger-beta
14-06-2004

EVALUATION Customer has provided possible fix for bug. Fix is in attached file. ###@###.### 2003-07-31 The problem exists because the Introspector makes the assumption that classes with the methods: void add<F>(EventListener); void remove<F>(EventListener); ...are part of an EventSetDescriptor. The approach presented by the customer submitted fix is correct. These methods should be processed unless they conform to the JavaBeans naming convensions for EventSets. In other words, they do not belong in an EventSet unless the name of the method is one of: add<F>Listener, remove<F>Listener, get<F>Listeners Simple low risk fix. ###@###.### 2003-08-04
04-08-2003