mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Added object access check to delegate invocation
This commit is contained in:
parent
5a0aa8a95b
commit
65ee34e37b
8 changed files with 89 additions and 10 deletions
|
@ -31,7 +31,11 @@ namespace System
|
||||||
|
|
||||||
public void* GetTarget()
|
public void* GetTarget()
|
||||||
{
|
{
|
||||||
|
#if BF_64_BIT && BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||||
|
return (.)((int)mTarget & 0x7FFFFFFF'FFFFFFFF);
|
||||||
|
#else
|
||||||
return mTarget;
|
return mTarget;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetFuncPtr(void* ptr, void* target = null)
|
public void SetFuncPtr(void* ptr, void* target = null)
|
||||||
|
@ -43,7 +47,11 @@ namespace System
|
||||||
protected override void GCMarkMembers()
|
protected override void GCMarkMembers()
|
||||||
{
|
{
|
||||||
// Note- this is safe even if mTarget is not an object, because the GC does object address validation
|
// Note- this is safe even if mTarget is not an object, because the GC does object address validation
|
||||||
|
#if BF_64_BIT && BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||||
|
GC.Mark(Internal.UnsafeCastToObject((.)((int)mTarget & 0x7FFFFFFF'FFFFFFFF)));
|
||||||
|
#else
|
||||||
GC.Mark(Internal.UnsafeCastToObject(mTarget));
|
GC.Mark(Internal.UnsafeCastToObject(mTarget));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetHashCode()
|
public int GetHashCode()
|
||||||
|
|
4
IDE/dist/BeefDbgVis.toml
vendored
4
IDE/dist/BeefDbgVis.toml
vendored
|
@ -23,11 +23,11 @@ ValuePointer = "/*(mMethodId < 0) ? &this :*/ __cast(\"_BF_DeferredData_\", mMet
|
||||||
Name = "System.Event<*>"
|
Name = "System.Event<*>"
|
||||||
DisplayString = "{{ data={__cast(\"System.Object\", mData & sDataMask)} }}"
|
DisplayString = "{{ data={__cast(\"System.Object\", mData & sDataMask)} }}"
|
||||||
[[Type.Expand.Item]]
|
[[Type.Expand.Item]]
|
||||||
Name = "[target]"
|
Name = "[Target]"
|
||||||
Value = "__cast(\"System.Object\", mData)"
|
Value = "__cast(\"System.Object\", mData)"
|
||||||
Condition = "(mData & sIsEnumerating) == 0"
|
Condition = "(mData & sIsEnumerating) == 0"
|
||||||
[[Type.Expand.Item]]
|
[[Type.Expand.Item]]
|
||||||
Name = "[target]"
|
Name = "[Target]"
|
||||||
Value = "((System.Event<$T1>.Enumerator*)(mData & sDataMask)).mTarget"
|
Value = "((System.Event<$T1>.Enumerator*)(mData & sDataMask)).mTarget"
|
||||||
Condition = "(mData & sIsEnumerating) != 0"
|
Condition = "(mData & sIsEnumerating) != 0"
|
||||||
[[Type.Expand.Item]]
|
[[Type.Expand.Item]]
|
||||||
|
|
|
@ -90,6 +90,11 @@ namespace IDE.ui
|
||||||
SetScaleData();
|
SetScaleData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
IDEApp.sApp.mDebugger.mBreakpointsChangedDelegate.Remove(scope => BreakpointsChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
void SetScaleData()
|
void SetScaleData()
|
||||||
{
|
{
|
||||||
mListView.mIconX = GS!(4);
|
mListView.mIconX = GS!(4);
|
||||||
|
|
|
@ -14031,7 +14031,18 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
||||||
if ((implicitParamCount > 0) || (needsSplat)) // Point back to self, it contains capture data
|
if ((implicitParamCount > 0) || (needsSplat)) // Point back to self, it contains capture data
|
||||||
valPtr = mModule->mBfIRBuilder->CreateBitCast(mResult.mValue, mModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr));
|
valPtr = mModule->mBfIRBuilder->CreateBitCast(mResult.mValue, mModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr));
|
||||||
else if (bindResult.mTarget)
|
else if (bindResult.mTarget)
|
||||||
valPtr = mModule->mBfIRBuilder->CreateBitCast(target.mValue, mModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr));
|
{
|
||||||
|
if ((target.mType->IsObjectOrInterface()) &&
|
||||||
|
(mModule->mCompiler->mOptions.mObjectHasDebugFlags) && (!mModule->mIsComptimeModule) &&
|
||||||
|
(mModule->mCompiler->mSystem->mPtrSize == 8))
|
||||||
|
{
|
||||||
|
auto numVal = mModule->mBfIRBuilder->CreatePtrToInt(target.mValue, BfTypeCode_UInt64);
|
||||||
|
auto orVal = mModule->mBfIRBuilder->CreateOr(numVal, mModule->mBfIRBuilder->CreateConst(BfTypeCode_UInt64, 0x8000000000000000ULL));
|
||||||
|
valPtr = mModule->mBfIRBuilder->CreateIntToPtr(orVal, mModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
valPtr = mModule->mBfIRBuilder->CreateBitCast(target.mValue, mModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
valPtr = mModule->GetDefaultValue(mModule->GetPrimitiveType(BfTypeCode_NullPtr));
|
valPtr = mModule->GetDefaultValue(mModule->GetPrimitiveType(BfTypeCode_NullPtr));
|
||||||
auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(baseDelegate, 0, 2);
|
auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(baseDelegate, 0, 2);
|
||||||
|
|
|
@ -10472,6 +10472,24 @@ void BfModule::SkipObjectAccessCheck(BfTypedValue typedVal)
|
||||||
mCurMethodState->mSkipObjectAccessChecks.Add(typedVal.mValue.mId);
|
mCurMethodState->mSkipObjectAccessChecks.Add(typedVal.mValue.mId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BfModule::WantsObjectAccessCheck(BfType* type)
|
||||||
|
{
|
||||||
|
if ((mBfIRBuilder->mIgnoreWrites) || (!type->IsObjectOrInterface()) || (mCurMethodState == NULL) || (mCurMethodState->mIgnoreObjectAccessCheck))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsComptimeModule))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool emitObjectAccessCheck = mCompiler->mOptions.mEmitObjectAccessCheck;
|
||||||
|
auto typeOptions = GetTypeOptions();
|
||||||
|
if (typeOptions != NULL)
|
||||||
|
emitObjectAccessCheck = typeOptions->Apply(emitObjectAccessCheck, BfOptionFlags_EmitObjectAccessCheck);
|
||||||
|
if (!emitObjectAccessCheck)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal)
|
void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal)
|
||||||
{
|
{
|
||||||
if ((mBfIRBuilder->mIgnoreWrites) || (!typedVal.mType->IsObjectOrInterface()) || (mCurMethodState == NULL) || (mCurMethodState->mIgnoreObjectAccessCheck))
|
if ((mBfIRBuilder->mIgnoreWrites) || (!typedVal.mType->IsObjectOrInterface()) || (mCurMethodState == NULL) || (mCurMethodState->mIgnoreObjectAccessCheck))
|
||||||
|
@ -16754,13 +16772,38 @@ void BfModule::CreateDelegateInvokeMethod()
|
||||||
BfIRValue staticResult;
|
BfIRValue staticResult;
|
||||||
|
|
||||||
auto callingConv = GetIRCallingConvention(mCurMethodInstance);
|
auto callingConv = GetIRCallingConvention(mCurMethodInstance);
|
||||||
|
auto trueEndBB = trueBB;
|
||||||
|
|
||||||
/// Non-static invocation
|
/// Non-static invocation
|
||||||
{
|
{
|
||||||
auto memberFuncPtr = mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapMethod(mCurMethodInstance));
|
auto memberFuncPtr = mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapMethod(mCurMethodInstance));
|
||||||
auto memberFuncPtrPtr = mBfIRBuilder->GetPointerTo(memberFuncPtr);
|
auto memberFuncPtrPtr = mBfIRBuilder->GetPointerTo(memberFuncPtr);
|
||||||
|
|
||||||
mBfIRBuilder->SetInsertPoint(trueBB);
|
mBfIRBuilder->SetInsertPoint(trueBB);
|
||||||
|
|
||||||
|
BfIRValue numVal;
|
||||||
|
if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule) && (mCompiler->mSystem->mPtrSize == 8))
|
||||||
|
{
|
||||||
|
numVal = mBfIRBuilder->CreatePtrToInt(fieldVal, BfTypeCode_UInt64);
|
||||||
|
auto andVal = mBfIRBuilder->CreateAnd(numVal, mBfIRBuilder->CreateConst(BfTypeCode_UInt64, ~0x8000000000000000ULL));
|
||||||
|
fieldVal = andVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((WantsObjectAccessCheck(mContext->mBfObjectType) && (mCompiler->mSystem->mPtrSize == 8)))
|
||||||
|
{
|
||||||
|
auto oacDoBB = mBfIRBuilder->CreateBlock("oac.do", true);
|
||||||
|
auto oacDoneBB = mBfIRBuilder->CreateBlock("oac.done");
|
||||||
|
|
||||||
|
auto checkGTE = mBfIRBuilder->CreateCmpGTE(numVal, mBfIRBuilder->CreateConst(BfTypeCode_UInt64, 0x8000000000000000ULL), false);
|
||||||
|
mBfIRBuilder->CreateCondBr(checkGTE, oacDoBB, oacDoneBB);
|
||||||
|
mBfIRBuilder->SetInsertPoint(oacDoBB);
|
||||||
|
mBfIRBuilder->CreateObjectAccessCheck(fieldVal, !IsOptimized());
|
||||||
|
mBfIRBuilder->CreateBr(oacDoneBB);
|
||||||
|
mBfIRBuilder->AddBlock(oacDoneBB);
|
||||||
|
mBfIRBuilder->SetInsertPoint(oacDoneBB);
|
||||||
|
trueEndBB = oacDoneBB;
|
||||||
|
}
|
||||||
|
|
||||||
memberFuncArgs[thisIdx] = mBfIRBuilder->CreateBitCast(fieldVal, mBfIRBuilder->MapType(mCurTypeInstance));
|
memberFuncArgs[thisIdx] = mBfIRBuilder->CreateBitCast(fieldVal, mBfIRBuilder->MapType(mCurTypeInstance));
|
||||||
auto fieldPtr = mBfIRBuilder->CreateInBoundsGEP(multicastDelegate, 0, 1); // Load 'delegate.mFuncPtr'
|
auto fieldPtr = mBfIRBuilder->CreateInBoundsGEP(multicastDelegate, 0, 1); // Load 'delegate.mFuncPtr'
|
||||||
auto funcPtrPtr = mBfIRBuilder->CreateBitCast(fieldPtr, memberFuncPtrPtr);
|
auto funcPtrPtr = mBfIRBuilder->CreateBitCast(fieldPtr, memberFuncPtrPtr);
|
||||||
|
@ -16829,7 +16872,7 @@ void BfModule::CreateDelegateInvokeMethod()
|
||||||
else
|
else
|
||||||
loweredIRReturnType = mBfIRBuilder->MapType(mCurMethodInstance->mReturnType);
|
loweredIRReturnType = mBfIRBuilder->MapType(mCurMethodInstance->mReturnType);
|
||||||
auto phi = mBfIRBuilder->CreatePhi(loweredIRReturnType, 2);
|
auto phi = mBfIRBuilder->CreatePhi(loweredIRReturnType, 2);
|
||||||
mBfIRBuilder->AddPhiIncoming(phi, nonStaticResult, trueBB);
|
mBfIRBuilder->AddPhiIncoming(phi, nonStaticResult, trueEndBB);
|
||||||
mBfIRBuilder->AddPhiIncoming(phi, staticResult, falseBB);
|
mBfIRBuilder->AddPhiIncoming(phi, staticResult, falseBB);
|
||||||
mBfIRBuilder->CreateRet(phi);
|
mBfIRBuilder->CreateRet(phi);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1746,6 +1746,7 @@ public:
|
||||||
bool HasCompiledOutput();
|
bool HasCompiledOutput();
|
||||||
bool HasExecutedOutput();
|
bool HasExecutedOutput();
|
||||||
void SkipObjectAccessCheck(BfTypedValue typedVal);
|
void SkipObjectAccessCheck(BfTypedValue typedVal);
|
||||||
|
bool WantsObjectAccessCheck(BfType* type);
|
||||||
void EmitObjectAccessCheck(BfTypedValue typedVal);
|
void EmitObjectAccessCheck(BfTypedValue typedVal);
|
||||||
bool WantsDebugHelpers();
|
bool WantsDebugHelpers();
|
||||||
void EmitEnsureInstructionAt();
|
void EmitEnsureInstructionAt();
|
||||||
|
|
|
@ -7739,9 +7739,20 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue
|
||||||
else if (methodName == "__funcTarget")
|
else if (methodName == "__funcTarget")
|
||||||
{
|
{
|
||||||
if (argValues.size() == 2)
|
if (argValues.size() == 2)
|
||||||
{
|
{
|
||||||
|
auto funcTargetTyped = argValues[1];
|
||||||
|
if ((sizeof(addr_target) == 8) && ((funcTargetTyped.mPtr & 0x8000000000000000LL) != 0))
|
||||||
|
{
|
||||||
|
auto objectType = mDbgModule->FindType("System.Object", NULL, DbgLanguage_BeefUnfixed);
|
||||||
|
if (objectType != NULL)
|
||||||
|
objectType = mDbgModule->GetPointerType(objectType);
|
||||||
|
funcTargetTyped.mPtr &= 0x7FFFFFFFFFFFFFFFLL;
|
||||||
|
if (objectType != NULL)
|
||||||
|
funcTargetTyped.mType = objectType;
|
||||||
|
}
|
||||||
|
|
||||||
auto funcPtr = argValues[0].mPtr;
|
auto funcPtr = argValues[0].mPtr;
|
||||||
auto funcTarget = argValues[1].mPtr;
|
auto funcTarget = funcTargetTyped.mPtr;
|
||||||
|
|
||||||
String symbolName;
|
String symbolName;
|
||||||
addr_target offset;
|
addr_target offset;
|
||||||
|
@ -7762,7 +7773,7 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return argValues[1];
|
return funcTargetTyped;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (methodName == "__stringView")
|
else if (methodName == "__stringView")
|
||||||
|
|
|
@ -408,10 +408,10 @@ namespace Tests
|
||||||
Test.Assert(a == 10+10 + 30);
|
Test.Assert(a == 10+10 + 30);
|
||||||
Test.Assert(mA == 100+300+300 + 300);
|
Test.Assert(mA == 100+300+300 + 300);
|
||||||
|
|
||||||
bind.Dispose();
|
|
||||||
|
|
||||||
Test.Assert(Use(scope => dlg, 10) == 400);
|
Test.Assert(Use(scope => dlg, 10) == 400);
|
||||||
|
|
||||||
|
bind.Dispose();
|
||||||
|
|
||||||
function int(int num) func = => StaticMethod;
|
function int(int num) func = => StaticMethod;
|
||||||
Test.Assert(Use(=> StaticMethod, 123) == 1123);
|
Test.Assert(Use(=> StaticMethod, 123) == 1123);
|
||||||
Test.Assert(Use(func, 123) == 1123);
|
Test.Assert(Use(func, 123) == 1123);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue