diff options
author | jfrijters <jfrijters> | 2015-03-24 12:31:46 +0300 |
---|---|---|
committer | jfrijters <jfrijters> | 2015-03-24 12:31:46 +0300 |
commit | a47ead952a7c4aaa38e3da547b5c8ba1d95bf6e0 (patch) | |
tree | c3b289114718bde4f885f0de20ed8b777d70becf | |
parent | 174e388d2207917db68b37963217c68c28aa5f76 (diff) |
Avoid infinite recursion if (broken) class loader triggers a load of a class currently being finished.
-rw-r--r-- | runtime/ClassFile.cs | 60 | ||||
-rw-r--r-- | runtime/DynamicTypeWrapper.cs | 23 | ||||
-rw-r--r-- | runtime/MemberWrapper.cs | 16 |
3 files changed, 61 insertions, 38 deletions
diff --git a/runtime/ClassFile.cs b/runtime/ClassFile.cs index 11f4c723..1bccbbbe 100644 --- a/runtime/ClassFile.cs +++ b/runtime/ClassFile.cs @@ -959,7 +959,7 @@ namespace IKVM.Internal } } - internal void Link(TypeWrapper thisType) + internal void Link(TypeWrapper thisType, LoadMode mode) { // this is not just an optimization, it's required for anonymous classes to be able to refer to themselves ((ConstantPoolItemClass)constantpool[this_class]).LinkSelf(thisType); @@ -967,7 +967,7 @@ namespace IKVM.Internal { if(constantpool[i] != null) { - constantpool[i].Link(thisType); + constantpool[i].Link(thisType, mode); } } } @@ -1424,7 +1424,7 @@ namespace IKVM.Internal { } - internal virtual void Link(TypeWrapper thisType) + internal virtual void Link(TypeWrapper thisType, LoadMode mode) { } @@ -1562,11 +1562,11 @@ namespace IKVM.Internal this.typeWrapper = thisType; } - internal override void Link(TypeWrapper thisType) + internal override void Link(TypeWrapper thisType, LoadMode mode) { if(typeWrapper == VerifierTypeWrapper.Null) { - TypeWrapper tw = thisType.GetClassLoader().LoadClass(name, LoadMode.Link | LoadMode.WarnClassNotFound); + TypeWrapper tw = thisType.GetClassLoader().LoadClass(name, mode | LoadMode.WarnClassNotFound); #if !STATIC_COMPILER && !FIRST_PASS if(!tw.IsUnloadable) { @@ -1677,9 +1677,9 @@ namespace IKVM.Internal clazz.MarkLinkRequired(); } - internal override void Link(TypeWrapper thisType) + internal override void Link(TypeWrapper thisType, LoadMode mode) { - clazz.Link(thisType); + clazz.Link(thisType, mode); } internal string Name @@ -1740,9 +1740,9 @@ namespace IKVM.Internal return fieldTypeWrapper; } - internal override void Link(TypeWrapper thisType) + internal override void Link(TypeWrapper thisType, LoadMode mode) { - base.Link(thisType); + base.Link(thisType, mode); lock(this) { if(fieldTypeWrapper != null) @@ -1761,11 +1761,11 @@ namespace IKVM.Internal fw = wrapper.GetFieldWrapper(Name, Signature); if(fw != null) { - fw.Link(); + fw.Link(mode); } } ClassLoaderWrapper classLoader = thisType.GetClassLoader(); - TypeWrapper fld = classLoader.FieldTypeWrapperFromSigNoThrow(this.Signature); + TypeWrapper fld = classLoader.FieldTypeWrapperFromSig(this.Signature, mode); lock(this) { if(fieldTypeWrapper == null) @@ -1817,9 +1817,9 @@ namespace IKVM.Internal } } - internal override void Link(TypeWrapper thisType) + internal override void Link(TypeWrapper thisType, LoadMode mode) { - base.Link(thisType); + base.Link(thisType, mode); lock(this) { if(argTypeWrappers != null) @@ -1828,8 +1828,8 @@ namespace IKVM.Internal } } ClassLoaderWrapper classLoader = thisType.GetClassLoader(); - TypeWrapper[] args = classLoader.ArgTypeWrapperListFromSigNoThrow(this.Signature); - TypeWrapper ret = classLoader.RetTypeWrapperFromSigNoThrow(this.Signature); + TypeWrapper[] args = classLoader.ArgTypeWrapperListFromSig(this.Signature, mode); + TypeWrapper ret = classLoader.RetTypeWrapperFromSig(this.Signature, mode); lock(this) { if(argTypeWrappers == null) @@ -1872,16 +1872,16 @@ namespace IKVM.Internal { } - internal override void Link(TypeWrapper thisType) + internal override void Link(TypeWrapper thisType, LoadMode mode) { - base.Link(thisType); + base.Link(thisType, mode); TypeWrapper wrapper = GetClassType(); if(wrapper != null && !wrapper.IsUnloadable) { method = wrapper.GetMethodWrapper(Name, Signature, !ReferenceEquals(Name, StringConstants.INIT)); if(method != null) { - method.Link(); + method.Link(mode); } if(Name != StringConstants.INIT && !thisType.IsInterface @@ -1892,7 +1892,7 @@ namespace IKVM.Internal invokespecialMethod = thisType.BaseTypeWrapper.GetMethodWrapper(Name, Signature, true); if(invokespecialMethod != null) { - invokespecialMethod.Link(); + invokespecialMethod.Link(mode); } } } @@ -1905,9 +1905,9 @@ namespace IKVM.Internal { } - internal override void Link(TypeWrapper thisType) + internal override void Link(TypeWrapper thisType, LoadMode mode) { - base.Link(thisType); + base.Link(thisType, mode); TypeWrapper wrapper = GetClassType(); if(wrapper != null) { @@ -1922,7 +1922,7 @@ namespace IKVM.Internal } if(method != null) { - method.Link(); + method.Link(mode); } } } @@ -2117,9 +2117,9 @@ namespace IKVM.Internal return cpi.GetClassType(); } - internal override void Link(TypeWrapper thisType) + internal override void Link(TypeWrapper thisType, LoadMode mode) { - cpi.Link(thisType); + cpi.Link(thisType, mode); } internal override ConstantType GetConstantType() @@ -2150,7 +2150,7 @@ namespace IKVM.Internal this.descriptor = String.Intern(descriptor.Replace('/', '.')); } - internal override void Link(TypeWrapper thisType) + internal override void Link(TypeWrapper thisType, LoadMode mode) { lock (this) { @@ -2160,8 +2160,8 @@ namespace IKVM.Internal } } ClassLoaderWrapper classLoader = thisType.GetClassLoader(); - TypeWrapper[] args = classLoader.ArgTypeWrapperListFromSigNoThrow(descriptor); - TypeWrapper ret = classLoader.RetTypeWrapperFromSigNoThrow(descriptor); + TypeWrapper[] args = classLoader.ArgTypeWrapperListFromSig(descriptor, mode); + TypeWrapper ret = classLoader.RetTypeWrapperFromSig(descriptor, mode); lock (this) { if (argTypeWrappers == null) @@ -2220,7 +2220,7 @@ namespace IKVM.Internal descriptor = String.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, name_and_type.descriptor_index).Replace('/', '.')); } - internal override void Link(TypeWrapper thisType) + internal override void Link(TypeWrapper thisType, LoadMode mode) { lock (this) { @@ -2230,8 +2230,8 @@ namespace IKVM.Internal } } ClassLoaderWrapper classLoader = thisType.GetClassLoader(); - TypeWrapper[] args = classLoader.ArgTypeWrapperListFromSigNoThrow(descriptor); - TypeWrapper ret = classLoader.RetTypeWrapperFromSigNoThrow(descriptor); + TypeWrapper[] args = classLoader.ArgTypeWrapperListFromSig(descriptor, mode); + TypeWrapper ret = classLoader.RetTypeWrapperFromSig(descriptor, mode); lock (this) { if (argTypeWrappers == null) diff --git a/runtime/DynamicTypeWrapper.cs b/runtime/DynamicTypeWrapper.cs index be8a410f..1fe5bf8f 100644 --- a/runtime/DynamicTypeWrapper.cs +++ b/runtime/DynamicTypeWrapper.cs @@ -478,6 +478,7 @@ namespace IKVM.Internal private bool finishInProgress; private MethodBuilder clinitMethod; private MethodBuilder finalizeMethod; + private int recursionCount; #if STATIC_COMPILER private DynamicTypeWrapper enclosingClassWrapper; private AnnotationBuilder annotationBuilder; @@ -1711,14 +1712,26 @@ namespace IKVM.Internal // make sure all classes are loaded, before we start finishing the type. During finishing, we // may not run any Java code, because that might result in a request to finish the type that we // are in the process of finishing, and this would be a problem. - classFile.Link(wrapper); - for (int i = 0; i < fields.Length; i++) + // Prevent infinity recursion for broken class loaders by keeping a recursion count and falling + // back to late binding if we recurse more than twice. + LoadMode mode = System.Threading.Interlocked.Increment(ref recursionCount) > 2 + ? LoadMode.ReturnUnloadable + : LoadMode.Link; + try { - fields[i].Link(); + classFile.Link(wrapper, mode); + for (int i = 0; i < fields.Length; i++) + { + fields[i].Link(mode); + } + for (int i = 0; i < methods.Length; i++) + { + methods[i].Link(mode); + } } - for (int i = 0; i < methods.Length; i++) + finally { - methods[i].Link(); + System.Threading.Interlocked.Decrement(ref recursionCount); } // this is the correct lock, FinishCore doesn't call any user code and mutates global state, // so it needs to be protected by a lock. diff --git a/runtime/MemberWrapper.cs b/runtime/MemberWrapper.cs index 420a2dcc..53c1d66a 100644 --- a/runtime/MemberWrapper.cs +++ b/runtime/MemberWrapper.cs @@ -589,6 +589,11 @@ namespace IKVM.Internal internal void Link() { + Link(LoadMode.Link); + } + + internal void Link(LoadMode mode) + { lock(this) { if(parameterTypeWrappers != null) @@ -597,8 +602,8 @@ namespace IKVM.Internal } } ClassLoaderWrapper loader = this.DeclaringType.GetClassLoader(); - TypeWrapper ret = loader.RetTypeWrapperFromSigNoThrow(Signature); - TypeWrapper[] parameters = loader.ArgTypeWrapperListFromSigNoThrow(Signature); + TypeWrapper ret = loader.RetTypeWrapperFromSig(Signature, mode); + TypeWrapper[] parameters = loader.ArgTypeWrapperListFromSig(Signature, mode); lock(this) { try @@ -1462,6 +1467,11 @@ namespace IKVM.Internal internal void Link() { + Link(LoadMode.Link); + } + + internal void Link(LoadMode mode) + { lock(this) { if(fieldType != null) @@ -1469,7 +1479,7 @@ namespace IKVM.Internal return; } } - TypeWrapper fld = this.DeclaringType.GetClassLoader().FieldTypeWrapperFromSigNoThrow(Signature); + TypeWrapper fld = this.DeclaringType.GetClassLoader().FieldTypeWrapperFromSig(Signature, mode); lock(this) { try |