Skip to content

Commit

Permalink
Fixed a stack violation access with ldfld
Browse files Browse the repository at this point in the history
  • Loading branch information
liiir1985 committed Apr 3, 2020
1 parent c080159 commit a06efd8
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 32 deletions.
83 changes: 65 additions & 18 deletions ILRuntime/Runtime/Intepreter/ILIntepreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public object Run(ILMethod method, object instance, object[] p)
}
unhandledException = false;
StackObject* objRef, objRef2, dst, val, a, b, arrRef;
object obj;
object obj = null;
IType type;
Type clrType;
int intVal;
Expand All @@ -155,7 +155,7 @@ public object Run(ILMethod method, object instance, object[] p)
mStack.Add(null);
break;
case ObjectTypes.ValueTypeObjectReference:
CloneStackValueType(a, a, mStack);
//CloneStackValueType(a, a, mStack);
break;
case ObjectTypes.Object:
case ObjectTypes.FieldReference:
Expand Down Expand Up @@ -1960,12 +1960,43 @@ public object Run(ILMethod method, object instance, object[] p)
dst = ILIntepreter.ResolveReference(objRef);
var ft = domain.GetType(dst->Value);
if (ft is ILType)
dst = Minus(dst, (int)ip->TokenLong + 1);
val = Minus(dst, (int)ip->TokenLong + 1);
else
dst = Minus(dst, ((CLRType)ft).FieldIndexMapping[(int)ip->TokenLong] + 1);
StackObject valRef = *ret;
CopyToStack(ret, dst, mStack);
FreeStackValueType(&valRef);
val = Minus(dst, ((CLRType)ft).FieldIndexMapping[(int)ip->TokenLong] + 1);
if (val->ObjectType == ObjectTypes.ValueTypeObjectReference && ret->ObjectType == ObjectTypes.ValueTypeObjectReference)
{
int start = int.MaxValue;
int end = int.MaxValue;
objRef2 = dst;
stack.CountValueTypeManaged(ret, ref start, ref end, &objRef2);
stack.RelocateValueType(val, ref dst, ref start);
stack.ValueTypeStackPointer = dst;
if (start <= end)
stack.RemoveManagedStackRange(start, end);
}
else
{
StackObject valRef;
if (val->ObjectType == ObjectTypes.ValueTypeObjectReference)
{
Free(ret);
CopyToStack(ret, val, mStack);
}
else
{
valRef = *val;
if (val->ObjectType >= ObjectTypes.Object)
obj = mStack[val->Value];
//CopyToStack(ret, dst, mStack);
Free(ret);
if (valRef.ObjectType >= ObjectTypes.Object)
{
valRef.Value = mStack.Count;
mStack.Add(obj);
}
*ret = valRef;
}
}
}
else
{
Expand Down Expand Up @@ -4206,8 +4237,6 @@ void DumpStack(StackObject* esp)
void CloneStackValueType(StackObject* src, StackObject* dst, IList<object> mStack)
{
StackObject* descriptor = ILIntepreter.ResolveReference(src);
if (src == dst)
FreeStackValueType(src);
stack.AllocValueType(dst, AppDomain.GetType(descriptor->Value));
StackObject* dstDescriptor = ILIntepreter.ResolveReference(dst);
int cnt = descriptor->ValueLow;
Expand Down Expand Up @@ -5083,12 +5112,22 @@ bool CheckExceptionType(IType catchType, object exception, bool explicitMatch)

public void CopyToStack(StackObject* dst, StackObject* src, IList<object> mStack)
{
*dst = *src;
if (dst->ObjectType >= ObjectTypes.Object)
if (src->ObjectType == ObjectTypes.ValueTypeObjectReference)
{
dst->Value = mStack.Count;
var obj = mStack[src->Value];
mStack.Add(obj);
var descriptor = ResolveReference(src);
var t = domain.GetType(descriptor->Value);
AllocValueType(dst, t);
CopyStackValueType(src, dst, mStack);
}
else
{
*dst = *src;
if (dst->ObjectType >= ObjectTypes.Object)
{
dst->Value = mStack.Count;
var obj = mStack[src->Value];
mStack.Add(obj);
}
}
}

Expand Down Expand Up @@ -5298,11 +5337,18 @@ public static void UnboxObject(StackObject* esp, object obj, IList<object> mStac
#endif
public void Free(StackObject* esp)
{
if (esp->ObjectType >= ObjectTypes.Object)
switch (esp->ObjectType)
{
var mStack = stack.ManagedStack;
if (esp->Value == mStack.Count - 1)
mStack.RemoveAt(esp->Value);
case ObjectTypes.Object:
case ObjectTypes.FieldReference:
case ObjectTypes.ArrayReference:
var mStack = stack.ManagedStack;
if (esp->Value == mStack.Count - 1)
mStack.RemoveAt(esp->Value);
break;
case ObjectTypes.ValueTypeObjectReference:
FreeStackValueType(esp);
break;
}
#if DEBUG && !DISABLE_ILRUNTIME_DEBUG
esp->ObjectType = ObjectTypes.Null;
Expand All @@ -5317,6 +5363,7 @@ public void FreeStackValueType(StackObject* esp)
var addr = ILIntepreter.ResolveReference(esp);
if (addr <= ValueTypeBasePointer)//Only Stack allocation after base pointer should be freed, local variable are freed automatically
stack.FreeValueTypeObject(esp);
esp->ObjectType = ObjectTypes.Null;
}
}

Expand Down
39 changes: 25 additions & 14 deletions ILRuntime/Runtime/Stack/RuntimeStack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ public StackObject* ValueTypeStackPointer
{
return valueTypePtr;
}
set
{
if (value > ValueTypeStackBase)
throw new StackOverflowException();
valueTypePtr = value;
}
}

public StackObject* ValueTypeStackBase
Expand Down Expand Up @@ -139,7 +145,7 @@ public void PushFrame(ref StackFrame frame)
return ret;
}

void RelocateValueType(StackObject* src, ref StackObject* dst, ref int mStackBase)
public void RelocateValueType(StackObject* src, ref StackObject* dst, ref int mStackBase)
{
StackObject* descriptor = ILIntepreter.ResolveReference(src);
if (descriptor > dst)
Expand Down Expand Up @@ -345,19 +351,8 @@ public void ClearValueTypeObject(IType type, StackObject* ptr)
}
}

public void FreeValueTypeObject(StackObject* esp)
public void RemoveManagedStackRange(int start, int end)
{
if (esp->ObjectType != ObjectTypes.ValueTypeObjectReference)
return;
int start = int.MaxValue;
int end = int.MinValue;
StackObject* endAddr;
CountValueTypeManaged(esp, ref start, ref end, &endAddr);

if (endAddr == valueTypePtr)
valueTypePtr = ILIntepreter.ResolveReference(esp);
else
throw new NotSupportedException();
if (start != int.MaxValue)
{
if (end == managedStack.Count - 1)
Expand All @@ -373,7 +368,23 @@ public void FreeValueTypeObject(StackObject* esp)
}
}

void CountValueTypeManaged(StackObject* esp, ref int start, ref int end, StackObject** endAddr)
public void FreeValueTypeObject(StackObject* esp)
{
if (esp->ObjectType != ObjectTypes.ValueTypeObjectReference)
return;
int start = int.MaxValue;
int end = int.MinValue;
StackObject* endAddr;
CountValueTypeManaged(esp, ref start, ref end, &endAddr);

if (endAddr == valueTypePtr)
valueTypePtr = ILIntepreter.ResolveReference(esp);
else
throw new NotSupportedException();
RemoveManagedStackRange(start, end);
}

public void CountValueTypeManaged(StackObject* esp, ref int start, ref int end, StackObject** endAddr)
{
StackObject* descriptor = ILIntepreter.ResolveReference(esp);
int cnt = descriptor->ValueLow;
Expand Down

0 comments on commit a06efd8

Please sign in to comment.