make JVM_GetSystemPackage a bit smarter

The original stub implementation just echoed back its argument, but
that confused URLClassLoader when dealing with sealed JARs --
returning a non-null value for a non-system class from
JVM_GetSystemPackage made URLClassloader think it had already loaded a
class from a package which was supposed to be sealed, resulting in
SecurityExceptions which ultimately triggered NoClassDefFoundErrors.
The solution is to only return non-null values for actual system
classes.
This commit is contained in:
Joel Dice 2012-09-24 17:43:34 -06:00
parent e20c5cd9c6
commit 3693201911
4 changed files with 83 additions and 3 deletions

View File

@ -88,6 +88,12 @@ class MyClasspath : public Classpath {
return AVIAN_CLASSPATH; return AVIAN_CLASSPATH;
} }
virtual void
updatePackageMap(Thread*, object)
{
// ignore
}
virtual void virtual void
dispose() dispose()
{ {

View File

@ -638,6 +638,47 @@ class MyClasspath : public Classpath {
return classpath; return classpath;
} }
virtual void
updatePackageMap(Thread* t, object class_)
{
PROTECT(t, class_);
if (root(t, Machine::PackageMap) == 0) {
setRoot(t, Machine::PackageMap, makeHashMap(t, 0, 0));
}
object className = vm::className(t, class_);
if ('[' != byteArrayBody(t, className, 0)) {
THREAD_RUNTIME_ARRAY
(t, char, packageName, byteArrayLength(t, className));
char* s = reinterpret_cast<char*>(&byteArrayBody(t, className, 0));
char* p = strrchr(s, '/');
if (p) {
int length = (p - s) + 1;
memcpy(RUNTIME_ARRAY_BODY(packageName),
&byteArrayBody(t, className, 0),
length);
RUNTIME_ARRAY_BODY(packageName)[length] = 0;
object key = vm::makeByteArray(t, "%s", packageName);
hashMapRemove
(t, root(t, Machine::PackageMap), key, byteArrayHash,
byteArrayEqual);
object source = classSource(t, class_);
if (source == 0) {
source = vm::makeByteArray(t, "avian-dummy-package-source");
}
hashMapInsert
(t, root(t, Machine::PackageMap), key, source, byteArrayHash);
}
}
}
virtual void virtual void
dispose() dispose()
{ {
@ -3531,10 +3572,37 @@ EXPORT(JVM_ClassDepth)(Thread*, jstring) { abort(); }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
EXPORT(JVM_ClassLoaderDepth)(Thread*) { abort(); } EXPORT(JVM_ClassLoaderDepth)(Thread*) { abort(); }
extern "C" JNIEXPORT jstring JNICALL uint64_t
EXPORT(JVM_GetSystemPackage)(Thread*, jstring s) jvmGetSystemPackage(Thread* t, uintptr_t* arguments)
{ {
return s; jstring s = reinterpret_cast<jstring>(arguments[0]);
ACQUIRE(t, t->m->classLock);
THREAD_RUNTIME_ARRAY(t, char, chars, stringLength(t, *s) + 1);
stringChars(t, *s, RUNTIME_ARRAY_BODY(chars));
object key = makeByteArray(t, RUNTIME_ARRAY_BODY(chars));
object array = hashMapFind
(t, root(t, Machine::PackageMap), key, byteArrayHash, byteArrayEqual);
if (array) {
return reinterpret_cast<uintptr_t>
(makeLocalReference
(t, t->m->classpath->makeString
(t, array, 0, byteArrayLength(t, array))));
} else {
return 0;
}
}
extern "C" JNIEXPORT jstring JNICALL
EXPORT(JVM_GetSystemPackage)(Thread* t, jstring s)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(s) };
return reinterpret_cast<jstring>(run(t, jvmGetSystemPackage, arguments));
} }
uint64_t uint64_t

View File

@ -4099,6 +4099,8 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_,
if (class_) { if (class_) {
hashMapInsert(t, classLoaderMap(t, loader), spec, class_, byteArrayHash); hashMapInsert(t, classLoaderMap(t, loader), spec, class_, byteArrayHash);
t->m->classpath->updatePackageMap(t, class_);
} else if (throw_) { } else if (throw_) {
throwNew(t, throwType, "%s", &byteArrayBody(t, spec, 0)); throwNew(t, throwType, "%s", &byteArrayBody(t, spec, 0));
} }

View File

@ -1206,6 +1206,7 @@ class Machine {
BootLoader, BootLoader,
AppLoader, AppLoader,
BootstrapClassMap, BootstrapClassMap,
PackageMap,
FindLoadedClassMethod, FindLoadedClassMethod,
LoadClassMethod, LoadClassMethod,
MonitorMap, MonitorMap,
@ -1550,6 +1551,9 @@ class Classpath {
virtual const char* virtual const char*
bootClasspath() = 0; bootClasspath() = 0;
virtual void
updatePackageMap(Thread* t, object class_) = 0;
virtual void virtual void
dispose() = 0; dispose() = 0;
}; };