Explorar el Código

Added object access check to delegate invocation

Brian Fiete hace 10 meses
padre
commit
65ee34e37b

+ 8 - 0
BeefLibs/corlib/src/Delegate.bf

@@ -31,7 +31,11 @@ namespace System
 
 		public void* GetTarget()
 		{
+#if BF_64_BIT && BF_ENABLE_OBJECT_DEBUG_FLAGS
+			return (.)((int)mTarget & 0x7FFFFFFF'FFFFFFFF);
+#else
 			return mTarget;
+#endif
 		}
 
 	    public void SetFuncPtr(void* ptr, void* target = null)
@@ -43,7 +47,11 @@ namespace System
 		protected override void GCMarkMembers()
 		{
 			// 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));
+#endif
 		}
 
 		public int GetHashCode()

+ 2 - 2
IDE/dist/BeefDbgVis.toml

@@ -23,11 +23,11 @@ ValuePointer = "/*(mMethodId < 0) ? &this :*/ __cast(\"_BF_DeferredData_\", mMet
 Name = "System.Event<*>"
 DisplayString = "{{ data={__cast(\"System.Object\", mData & sDataMask)} }}"
 [[Type.Expand.Item]]
-Name = "[target]"
+Name = "[Target]"
 Value = "__cast(\"System.Object\", mData)"
 Condition = "(mData & sIsEnumerating) == 0"
 [[Type.Expand.Item]]
-Name = "[target]"
+Name = "[Target]"
 Value = "((System.Event<$T1>.Enumerator*)(mData & sDataMask)).mTarget"
 Condition = "(mData & sIsEnumerating) != 0"
 [[Type.Expand.Item]]

+ 5 - 0
IDE/src/ui/BreakpointPanel.bf

@@ -90,6 +90,11 @@ namespace IDE.ui
     		SetScaleData();
 		}
 
+		public ~this()
+		{
+			IDEApp.sApp.mDebugger.mBreakpointsChangedDelegate.Remove(scope => BreakpointsChanged, true);
+		}
+
 		void SetScaleData()
 		{
 			mListView.mIconX = GS!(4);

+ 12 - 1
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -14031,7 +14031,18 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
 		if ((implicitParamCount > 0) || (needsSplat)) // Point back to self, it contains capture data
 			valPtr = mModule->mBfIRBuilder->CreateBitCast(mResult.mValue, mModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr));
 		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
 			valPtr = mModule->GetDefaultValue(mModule->GetPrimitiveType(BfTypeCode_NullPtr));
 		auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(baseDelegate, 0, 2);

+ 45 - 2
IDEHelper/Compiler/BfModule.cpp

@@ -10472,6 +10472,24 @@ void BfModule::SkipObjectAccessCheck(BfTypedValue typedVal)
 	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)
 {
 	if ((mBfIRBuilder->mIgnoreWrites) || (!typedVal.mType->IsObjectOrInterface()) || (mCurMethodState == NULL) || (mCurMethodState->mIgnoreObjectAccessCheck))
@@ -16754,13 +16772,38 @@ void BfModule::CreateDelegateInvokeMethod()
 	BfIRValue staticResult;
 
 	auto callingConv = GetIRCallingConvention(mCurMethodInstance);
-
+	auto trueEndBB = trueBB;
+	
 	/// Non-static invocation
 	{
 		auto memberFuncPtr = mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapMethod(mCurMethodInstance));
 		auto memberFuncPtrPtr = mBfIRBuilder->GetPointerTo(memberFuncPtr);
 
 		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));
 		auto fieldPtr = mBfIRBuilder->CreateInBoundsGEP(multicastDelegate, 0, 1); // Load 'delegate.mFuncPtr'
 		auto funcPtrPtr = mBfIRBuilder->CreateBitCast(fieldPtr, memberFuncPtrPtr);
@@ -16829,7 +16872,7 @@ void BfModule::CreateDelegateInvokeMethod()
 		else
 			loweredIRReturnType = mBfIRBuilder->MapType(mCurMethodInstance->mReturnType);
 		auto phi = mBfIRBuilder->CreatePhi(loweredIRReturnType, 2);
-		mBfIRBuilder->AddPhiIncoming(phi, nonStaticResult, trueBB);
+		mBfIRBuilder->AddPhiIncoming(phi, nonStaticResult, trueEndBB);
 		mBfIRBuilder->AddPhiIncoming(phi, staticResult, falseBB);
 		mBfIRBuilder->CreateRet(phi);
 	}

+ 1 - 0
IDEHelper/Compiler/BfModule.h

@@ -1746,6 +1746,7 @@ public:
 	bool HasCompiledOutput();
 	bool HasExecutedOutput();
 	void SkipObjectAccessCheck(BfTypedValue typedVal);
+	bool WantsObjectAccessCheck(BfType* type);
 	void EmitObjectAccessCheck(BfTypedValue typedVal);
 	bool WantsDebugHelpers();
 	void EmitEnsureInstructionAt();

+ 14 - 3
IDEHelper/DbgExprEvaluator.cpp

@@ -7739,9 +7739,20 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue
 	else if (methodName == "__funcTarget")
 	{
 		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 funcTarget = argValues[1].mPtr;
+			auto funcTarget = funcTargetTyped.mPtr;
 
 			String symbolName;
 			addr_target offset;
@@ -7762,7 +7773,7 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue
 				}
 			}
 
-			return argValues[1];
+			return funcTargetTyped;
 		}
 	}
 	else if (methodName == "__stringView")

+ 2 - 2
IDEHelper/Tests/src/FuncRefs.bf

@@ -408,10 +408,10 @@ namespace Tests
 				Test.Assert(a == 10+10 + 30);
 				Test.Assert(mA == 100+300+300 + 300);
 
-				bind.Dispose();
-
 				Test.Assert(Use(scope => dlg, 10) == 400);
 
+				bind.Dispose();
+
 				function int(int num) func = => StaticMethod;
 				Test.Assert(Use(=> StaticMethod, 123) == 1123);
 				Test.Assert(Use(func, 123) == 1123);