Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfrijters <jfrijters>2015-03-24 12:31:46 +0300
committerjfrijters <jfrijters>2015-03-24 12:31:46 +0300
commita47ead952a7c4aaa38e3da547b5c8ba1d95bf6e0 (patch)
treec3b289114718bde4f885f0de20ed8b777d70becf
parent174e388d2207917db68b37963217c68c28aa5f76 (diff)
Avoid infinite recursion if (broken) class loader triggers a load of a class currently being finished.
-rw-r--r--runtime/ClassFile.cs60
-rw-r--r--runtime/DynamicTypeWrapper.cs23
-rw-r--r--runtime/MemberWrapper.cs16
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