stack overflow interacts poorly with classloaders
Timothy Stack
kaffe@rufus.w3.org
Tue, 13 Jun 2000 14:32:47 -0600 (MDT)
hi,
I modified verifyMethod in code-analayse.c to load the exception
classes and it seems to work fine. I also updated godmars Overflow
test case to use a class loader and tweaked some other ones. Can
someone look this over and make sure I'm not missing something...
thanks,
tim stack
Index: kaffe/kaffe/kaffevm/baseClasses.c
diff -u kaffe/kaffe/kaffevm/baseClasses.c:1.2 kaffe/kaffe/kaffevm/baseClasses.c:1.3
--- kaffe/kaffe/kaffevm/baseClasses.c:1.2 Thu May 4 17:00:39 2000
+++ kaffe/kaffe/kaffevm/baseClasses.c Tue Jun 13 14:21:34 2000
@@ -68,6 +68,7 @@
Hjava_lang_Class* javaLangFloatClass;
Hjava_lang_Class* javaLangDoubleClass;
+Hjava_lang_Class* javaLangThrowable;
Hjava_lang_Class* javaLangArrayIndexOutOfBoundsException;
Hjava_lang_Class* javaLangNullPointerException;
Hjava_lang_Class* javaLangArithmeticException;
@@ -248,6 +249,7 @@
loadStaticClass(&PtrClass, PTRCLASS);
/* Exception handling types */
+ loadStaticClass(&javaLangThrowable, "java/lang/Throwable");
loadStaticClass(&javaLangArrayIndexOutOfBoundsException, "java/lang/ArrayIndexOutOfBoundsException");
loadStaticClass(&javaLangNullPointerException, "java/lang/NullPointerException");
loadStaticClass(&javaLangArithmeticException, "java/lang/ArithmeticException");
Index: kaffe/kaffe/kaffevm/baseClasses.h
diff -u kaffe/kaffe/kaffevm/baseClasses.h:1.1 kaffe/kaffe/kaffevm/baseClasses.h:1.2
--- kaffe/kaffe/kaffevm/baseClasses.h:1.1 Thu May 4 16:13:06 2000
+++ kaffe/kaffe/kaffevm/baseClasses.h Tue Jun 13 14:21:38 2000
@@ -46,6 +46,7 @@
extern struct Hjava_lang_Class* javaLangFloatClass;
extern struct Hjava_lang_Class* javaLangDoubleClass;
+extern struct Hjava_lang_Class* javaLangThrowable;
extern struct Hjava_lang_Class* javaLangNullPointerException;
extern struct Hjava_lang_Class* javaLangArithmeticException;
extern struct Hjava_lang_Class* javaLangArrayIndexOutOfBoundsException;
Index: kaffe/kaffe/kaffevm/code-analyse.c
diff -u kaffe/kaffe/kaffevm/code-analyse.c:1.1 kaffe/kaffe/kaffevm/code-analyse.c:1.2
--- kaffe/kaffe/kaffevm/code-analyse.c:1.1 Thu May 4 16:13:06 2000
+++ kaffe/kaffe/kaffevm/code-analyse.c Tue Jun 13 14:21:42 2000
@@ -28,6 +28,8 @@
#include "locks.h"
#include "thread.h"
#include "jthread.h"
+#include "baseClasses.h"
+#include "soft.h"
#include "md.h"
#include "gc.h"
@@ -249,6 +251,51 @@
sp = meth->localsz + meth->stacksz - 1;
if (meth->exception_table != 0) {
for (lcl = 0; lcl < meth->exception_table->length; lcl++) {
+ jexceptionEntry* eptr;
+
+ eptr = &meth->exception_table->entry[lcl];
+ /*
+ * Verification requires us to resolve the catch type
+ * and check that its actually a Throwable. But, we
+ * also do it to ensure that the classes are ready when
+ * we need them and have little room to work (e.g. a
+ * stack overflow).
+ */
+ if( eptr->catch_idx == 0 ) {
+ /* A finally clause... */
+ } else {
+ eptr->catch_type = getClass(eptr->catch_idx,
+ meth->class,
+ einfo);
+ /*
+ * If we could not resolve the catch class,
+ * then we must a) record that fact to guard
+ * against possible recursive attempts to load
+ * it and b) throw the error resulting from
+ * that failure and forget about the current
+ * exception.
+ */
+ if (eptr->catch_type == NULL) {
+DBG(ELOOKUP|DBG_RESERROR,
+ dprintf("Couldn't resolve catch class\n");
+)
+ eptr->catch_type =
+ UNRESOLVABLE_CATCHTYPE;
+ throwError(einfo);
+ return (false);
+ }
+ /*
+ * Make sure the exception is a subclass of
+ * throwable.
+ */
+ if( !instanceof(javaLangThrowable,
+ eptr->catch_type) )
+ {
+ postException(einfo,
+ JAVA_LANG(ClassFormatError));
+ throwError(einfo);
+ }
+ }
pc = meth->exception_table->entry[lcl].handler_pc;
ATTACH_NEW_BASICBLOCK(pc);
SET_STARTOFEXCEPTION(pc);
Index: kaffe/test/regression/ExceptionTestClassLoader.java
diff -u kaffe/test/regression/ExceptionTestClassLoader.java:1.1 kaffe/test/regression/ExceptionTestClassLoader.java:1.2
--- kaffe/test/regression/ExceptionTestClassLoader.java:1.1 Thu May 4 16:13:48 2000
+++ kaffe/test/regression/ExceptionTestClassLoader.java Tue Jun 13 14:22:09 2000
@@ -68,7 +68,7 @@
-
+// Sort output
/* Expected Output:
Success 1.
Success 2.
Index: kaffe/test/regression/ExceptionTestClassLoader2.java
diff -u kaffe/test/regression/ExceptionTestClassLoader2.java:1.1 kaffe/test/regression/ExceptionTestClassLoader2.java:1.2
--- kaffe/test/regression/ExceptionTestClassLoader2.java:1.1 Thu May 4 16:13:48 2000
+++ kaffe/test/regression/ExceptionTestClassLoader2.java Tue Jun 13 14:22:17 2000
@@ -89,9 +89,8 @@
/* Expected Output:
-Success 1.
Success 2.
Success 3.
Success 4.
Index: kaffe/test/regression/Overflow.java
diff -u kaffe/test/regression/Overflow.java:1.1 kaffe/test/regression/Overflow.java:1.2
--- kaffe/test/regression/Overflow.java:1.1 Thu May 4 16:13:49 2000
+++ kaffe/test/regression/Overflow.java Tue Jun 13 14:23:14 2000
@@ -4,7 +4,9 @@
*
* @author Godmar Back <gback@cs.utah.edu>
*/
-public class Overflow extends Thread
+import java.io.*;
+
+class OverflowTester extends Thread
{
public void run() {
try {
@@ -18,17 +20,61 @@
recurse();
}
- public static void main(String av[]) throws Exception
+ public OverflowTester() throws Exception
{
- Overflow o = new Overflow();
- o.run(); // check for main thread
-
- o.start(); // check for other thread
- o.join();
+ run(); // check for main thread
+
+ start(); // check for other thread
+ join();
}
}
+class Overflow extends ClassLoader {
+
+ /*
+ * read a .class file
+ */
+ static byte [] readin(String name) throws Exception
+ {
+ File cf = new File(name);
+ FileInputStream cfi = new FileInputStream(cf);
+
+ int len = (int)cf.length();
+ byte [] cb = new byte[len];
+ if (cfi.read(cb) != len)
+ throw new Exception("short read for " + name);
+ return cb;
+ }
+
+ public Class loadClass(String name, boolean resolve)
+ throws ClassNotFoundException
+ {
+ Class c = null;
+
+ try {
+ byte []b = readin(name + ".class");
+ return defineClass(name, b, 0, b.length);
+ } catch (Exception e) {
+ return findSystemClass(name);
+ }
+ }
+
+ public static void main(String av[]) throws Exception
+ {
+ OverflowTester oft;
+ Overflow l = new Overflow();
+ Class c;
+
+ c = l.loadClass("OverflowTester");
+ c.newInstance();
+ oft = new OverflowTester();
+ }
+
+}
+
/* Expected Output:
+Success.
+Success.
Success.
Success.
*/