diff --git a/src/coreclr/System.Private.CoreLib/src/System/BadImageFormatException.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/BadImageFormatException.CoreCLR.cs
index 6e44e7e1cfdd65..a8b51c7df17f34 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/BadImageFormatException.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/BadImageFormatException.CoreCLR.cs
@@ -13,5 +13,17 @@ private BadImageFormatException(string? fileName, int hResult)
_fileName = fileName;
SetMessageField();
}
+
+ // Do not delete: this is invoked from native code.
+ // Used when the requesting assembly chain is known, to provide assembly load dependency context.
+ private BadImageFormatException(string? fileName, string? requestingAssemblyChain, int hResult)
+ : base(null)
+ {
+ HResult = hResult;
+ _fileName = fileName;
+ SetMessageField();
+ if (requestingAssemblyChain is not null)
+ _message += Environment.NewLine + IO.FileLoadException.FormatRequestingAssemblyChain(requestingAssemblyChain);
+ }
}
}
diff --git a/src/coreclr/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs
index 439689ca9adc26..778d47a313e326 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs
@@ -17,6 +17,45 @@ private FileLoadException(string? fileName, int hResult)
_message = FormatFileLoadExceptionMessage(FileName, HResult);
}
+ // Do not delete: this is invoked from native code.
+ // Used when the requesting assembly chain is known, to provide assembly load dependency context.
+ // The requestingAssemblyChain parameter is a newline-separated list of assembly display names,
+ // from immediate parent to root ancestor.
+ private FileLoadException(string? fileName, string? requestingAssemblyChain, int hResult)
+ : base(null)
+ {
+ HResult = hResult;
+ FileName = fileName;
+ _message = FormatFileLoadExceptionMessage(FileName, HResult);
+ if (requestingAssemblyChain is not null)
+ _message += Environment.NewLine + FormatRequestingAssemblyChain(requestingAssemblyChain);
+ }
+
+ internal static string FormatRequestingAssemblyChain(string requestingAssemblyChain)
+ {
+ int newlineIndex = requestingAssemblyChain.IndexOf('\n');
+ if (newlineIndex < 0)
+ return SR.Format(SR.IO_FileLoad_RequestingAssembly, requestingAssemblyChain);
+
+ var result = new System.Text.StringBuilder();
+ int start = 0;
+ while (start < requestingAssemblyChain.Length)
+ {
+ int end = requestingAssemblyChain.IndexOf('\n', start);
+ string name = end >= 0
+ ? requestingAssemblyChain.Substring(start, end - start)
+ : requestingAssemblyChain.Substring(start);
+
+ if (result.Length > 0)
+ result.Append(Environment.NewLine);
+ result.Append(SR.Format(SR.IO_FileLoad_RequestingAssembly, name));
+
+ start = end >= 0 ? end + 1 : requestingAssemblyChain.Length;
+ }
+
+ return result.ToString();
+ }
+
internal static string FormatFileLoadExceptionMessage(string? fileName, int hResult)
{
string? format = null;
diff --git a/src/coreclr/System.Private.CoreLib/src/System/IO/FileNotFoundException.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/IO/FileNotFoundException.CoreCLR.cs
index fbd2a6d02e6953..5c81003e973cdf 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/IO/FileNotFoundException.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/IO/FileNotFoundException.CoreCLR.cs
@@ -13,5 +13,17 @@ private FileNotFoundException(string? fileName, int hResult)
FileName = fileName;
SetMessageField();
}
+
+ // Do not delete: this is invoked from native code.
+ // Used when the requesting assembly chain is known, to provide assembly load dependency context.
+ private FileNotFoundException(string? fileName, string? requestingAssemblyChain, int hResult)
+ : base(null)
+ {
+ HResult = hResult;
+ FileName = fileName;
+ SetMessageField();
+ if (requestingAssemblyChain is not null)
+ _message += Environment.NewLine + FileLoadException.FormatRequestingAssemblyChain(requestingAssemblyChain);
+ }
}
}
diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp
index 18ba1c41a962e0..dba1ed87b65e77 100644
--- a/src/coreclr/vm/appdomain.hpp
+++ b/src/coreclr/vm/appdomain.hpp
@@ -1115,6 +1115,12 @@ class AppDomain final
return m_AssemblyCache.LookupAssembly(pSpec, fThrow);
}
+ Assembly* FindCachedParentAssembly(Assembly* pAssembly)
+ {
+ WRAPPER_NO_CONTRACT;
+ return m_AssemblyCache.LookupParentAssemblyForAssembly(pAssembly);
+ }
+
private:
PEAssembly* FindCachedFile(AssemblySpec* pSpec, BOOL fThrow = TRUE);
BOOL IsCached(AssemblySpec *pSpec);
diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp
index 4650b95691e0f2..9c505f43ad69ed 100644
--- a/src/coreclr/vm/assemblyspec.cpp
+++ b/src/coreclr/vm/assemblyspec.cpp
@@ -734,6 +734,34 @@ PEAssembly *AssemblySpecBindingCache::LookupFile(AssemblySpec *pSpec, BOOL fThro
}
}
+Assembly *AssemblySpecBindingCache::LookupParentAssemblyForAssembly(Assembly *pAssembly)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ FORBID_FAULT;
+ MODE_ANY;
+ PRECONDITION(pAssembly != NULL);
+ }
+ CONTRACTL_END;
+
+ PtrHashMap::PtrIterator i = m_map.begin();
+ while (!i.end())
+ {
+ AssemblyBinding *b = (AssemblyBinding*) i.GetValue();
+ if (!b->IsError() && b->GetAssembly() == pAssembly)
+ {
+ Assembly *pParent = b->GetParentAssembly();
+ if (pParent != NULL)
+ return pParent;
+ }
+ ++i;
+ }
+
+ return NULL;
+}
+
class AssemblyBindingHolder
{
diff --git a/src/coreclr/vm/assemblyspec.hpp b/src/coreclr/vm/assemblyspec.hpp
index 977366b05242d9..fa68fad54a2e2b 100644
--- a/src/coreclr/vm/assemblyspec.hpp
+++ b/src/coreclr/vm/assemblyspec.hpp
@@ -346,6 +346,7 @@ class AssemblySpecBindingCache
inline Assembly* GetAssembly(){ LIMITED_METHOD_CONTRACT; return m_pAssembly; };
inline void SetAssembly(Assembly* pAssembly){ LIMITED_METHOD_CONTRACT; m_pAssembly = pAssembly; };
inline PEAssembly* GetFile(){ LIMITED_METHOD_CONTRACT; return m_pPEAssembly;};
+ inline Assembly* GetParentAssembly(){ WRAPPER_NO_CONTRACT; return m_spec.GetParentAssembly(); };
inline BOOL IsError(){ LIMITED_METHOD_CONTRACT; return (m_exceptionType!=EXTYPE_NONE);};
// bound to the file, but failed later
@@ -492,6 +493,7 @@ class AssemblySpecBindingCache
Assembly *LookupAssembly(AssemblySpec *pSpec, BOOL fThrow=TRUE);
PEAssembly *LookupFile(AssemblySpec *pSpec, BOOL fThrow = TRUE);
+ Assembly *LookupParentAssemblyForAssembly(Assembly *pAssembly);
BOOL StoreAssembly(AssemblySpec *pSpec, Assembly *pAssembly);
BOOL StorePEAssembly(AssemblySpec *pSpec, PEAssembly *pPEAssembly);
diff --git a/src/coreclr/vm/clrex.cpp b/src/coreclr/vm/clrex.cpp
index 2953e0a75b5f08..b3bd65b4808fcd 100644
--- a/src/coreclr/vm/clrex.cpp
+++ b/src/coreclr/vm/clrex.cpp
@@ -1606,32 +1606,62 @@ OBJECTREF EEFileLoadException::CreateThrowable()
struct {
OBJECTREF pNewException;
STRINGREF pNewFileString;
+ STRINGREF pNewFusionLogString;
} gc;
gc.pNewException = NULL;
gc.pNewFileString = NULL;
+ gc.pNewFusionLogString = NULL;
GCPROTECT_BEGIN(gc);
gc.pNewFileString = StringObject::NewString(m_name);
gc.pNewException = AllocateObject(CoreLibBinder::GetException(m_kind));
- MethodDesc* pMD = MemberLoader::FindMethod(gc.pNewException->GetMethodTable(),
- COR_CTOR_METHOD_NAME, &gsig_IM_Str_Int_RetVoid);
+ bool usedThreeArgCtor = false;
- if (!pMD)
+ if (!m_requestingAssemblyName.IsEmpty())
{
- MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
- COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
+ gc.pNewFusionLogString = StringObject::NewString(m_requestingAssemblyName);
+
+ MethodDesc* pMD = MemberLoader::FindMethod(gc.pNewException->GetMethodTable(),
+ COR_CTOR_METHOD_NAME, &gsig_IM_Str_Str_Int_RetVoid);
+
+ if (pMD)
+ {
+ MethodDescCallSite exceptionCtor(pMD);
+
+ ARG_SLOT args[] = {
+ ObjToArgSlot(gc.pNewException),
+ ObjToArgSlot(gc.pNewFileString),
+ ObjToArgSlot(gc.pNewFusionLogString),
+ (ARG_SLOT) m_hr
+ };
+
+ exceptionCtor.Call(args);
+ usedThreeArgCtor = true;
+ }
}
- MethodDescCallSite exceptionCtor(pMD);
+ if (!usedThreeArgCtor)
+ {
+ MethodDesc* pMD = MemberLoader::FindMethod(gc.pNewException->GetMethodTable(),
+ COR_CTOR_METHOD_NAME, &gsig_IM_Str_Int_RetVoid);
- ARG_SLOT args[] = {
- ObjToArgSlot(gc.pNewException),
- ObjToArgSlot(gc.pNewFileString),
- (ARG_SLOT) m_hr
- };
+ if (!pMD)
+ {
+ MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
+ COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
+ }
- exceptionCtor.Call(args);
+ MethodDescCallSite exceptionCtor(pMD);
+
+ ARG_SLOT args[] = {
+ ObjToArgSlot(gc.pNewException),
+ ObjToArgSlot(gc.pNewFileString),
+ (ARG_SLOT) m_hr
+ };
+
+ exceptionCtor.Call(args);
+ }
GCPROTECT_END();
@@ -1664,8 +1694,6 @@ BOOL EEFileLoadException::CheckType(Exception* ex)
// @todo: ideally we would use inner exceptions with these routines
-/* static */
-
/* static */
void DECLSPEC_NORETURN EEFileLoadException::Throw(AssemblySpec *pSpec, HRESULT hr, Exception *pInnerException/* = NULL*/)
{
@@ -1684,7 +1712,72 @@ void DECLSPEC_NORETURN EEFileLoadException::Throw(AssemblySpec *pSpec, HRESULT
StackSString name;
pSpec->GetDisplayName(0, name);
- EX_THROW_WITH_INNER(EEFileLoadException, (name, hr), pInnerException);
+
+ // Extract the requesting assembly chain for diagnostic purposes
+ {
+ FAULT_NOT_FATAL();
+
+ Exception *inner2 = ExThrowWithInnerHelper(pInnerException);
+ EEFileLoadException *pException = new EEFileLoadException(name, hr);
+ pException->SetInnerException(inner2);
+
+ Assembly *pParentAssembly = pSpec->GetParentAssembly();
+ if (pParentAssembly != NULL)
+ {
+ StackSString parentName;
+ pParentAssembly->GetDisplayName(parentName);
+
+ // Build the requesting assembly chain: start with the immediate parent,
+ // then walk up the binding cache to find transitive requesting assemblies.
+ StackSString requestingChain;
+ requestingChain.Set(parentName);
+
+ EX_TRY
+ {
+ AppDomain *pDomain = pSpec->GetAppDomain();
+ if (pDomain != NULL)
+ {
+ Assembly *pWalkAssembly = pParentAssembly;
+ int depth = 0;
+ const int MaxChainDepth = 10;
+
+ while (pWalkAssembly != NULL && depth < MaxChainDepth)
+ {
+ // Look up the current assembly in the binding cache to find
+ // which assembly requested its load (its parent).
+ Assembly *pGrandParent = pDomain->FindCachedParentAssembly(pWalkAssembly);
+ if (pGrandParent == NULL || pGrandParent == pWalkAssembly)
+ break;
+
+ // Skip system assemblies (System.Private.CoreLib etc.)
+ if (!pGrandParent->IsSystem())
+ {
+ StackSString grandParentName;
+ pGrandParent->GetDisplayName(grandParentName);
+ requestingChain.Append(W("\n"));
+ requestingChain.Append(grandParentName);
+ }
+
+ pWalkAssembly = pGrandParent;
+ depth++;
+ }
+ }
+ }
+ EX_CATCH
+ {
+ // If the chain walk fails for any reason, just use what we have so far
+ }
+ EX_END_CATCH
+
+ pException->SetRequestingAssembly(requestingChain);
+ }
+
+ STRESS_LOG3(LF_EH, LL_INFO100, "EX_THROW_WITH_INNER Type = 0x%x HR = 0x%x, "
+ INDEBUG(__FILE__) " line %d\n", EEFileLoadException::GetType(),
+ pException->GetHR(), __LINE__);
+ EX_THROW_DEBUG_TRAP(__FUNCTION__, __FILE__, __LINE__, "EEFileLoadException", pException->GetHR(), "(name, hr)");
+ PAL_CPP_THROW(EEFileLoadException *, pException);
+ }
}
/* static */
diff --git a/src/coreclr/vm/clrex.h b/src/coreclr/vm/clrex.h
index 01fbce5df1a1c7..3472d44273c3e5 100644
--- a/src/coreclr/vm/clrex.h
+++ b/src/coreclr/vm/clrex.h
@@ -665,12 +665,19 @@ class EEFileLoadException : public EEException
private:
SString m_name;
HRESULT m_hr;
+ SString m_requestingAssemblyName;
public:
EEFileLoadException(const SString &name, HRESULT hr, Exception *pInnerException = NULL);
~EEFileLoadException();
+ void SetRequestingAssembly(const SString &name)
+ {
+ WRAPPER_NO_CONTRACT;
+ m_requestingAssemblyName = name;
+ }
+
// virtual overrides
HRESULT GetHR()
{
@@ -692,7 +699,9 @@ class EEFileLoadException : public EEException
virtual Exception *CloneHelper()
{
WRAPPER_NO_CONTRACT;
- return new EEFileLoadException(m_name, m_hr);
+ EEFileLoadException *pClone = new EEFileLoadException(m_name, m_hr);
+ pClone->SetRequestingAssembly(m_requestingAssemblyName);
+ return pClone;
}
private:
diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h
index 0ff156f0883adc..2d70a01e273ff2 100644
--- a/src/coreclr/vm/metasig.h
+++ b/src/coreclr/vm/metasig.h
@@ -371,6 +371,7 @@ DEFINE_METASIG(SM(PtrChar_Int_PtrPtrChar_RetArrStr, P(u) i P(P(u)), a(s)))
DEFINE_METASIG_T(IM(Str_Exception_RetVoid, s C(EXCEPTION), v))
DEFINE_METASIG(IM(Str_Str_RetVoid, s s, v))
DEFINE_METASIG(IM(Str_Int_RetVoid, s i, v))
+DEFINE_METASIG(IM(Str_Str_Int_RetVoid, s s i, v))
DEFINE_METASIG(IM(Str_Str_Str_Int_RetVoid, s s s i, v))
DEFINE_METASIG_T(IM(Str_BindingFlags_Binder_Obj_ArrObj_ArrParameterModifier_CultureInfo_ArrStr_RetObj, \
s g(BINDING_FLAGS) C(BINDER) j a(j) a(g(PARAMETER_MODIFIER)) C(CULTURE_INFO) a(s), j))
diff --git a/src/libraries/Microsoft.Bcl.Cryptography/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Bcl.Cryptography/src/CompatibilitySuppressions.xml
new file mode 100644
index 00000000000000..c5a74a9d8396cf
--- /dev/null
+++ b/src/libraries/Microsoft.Bcl.Cryptography/src/CompatibilitySuppressions.xml
@@ -0,0 +1,199 @@
+
+
+
+
+ CP0014
+ M:System.Security.Cryptography.X509Certificates.X509CertificateKeyAccessors.CopyWithPrivateKey(System.Security.Cryptography.X509Certificates.X509Certificate2,System.Security.Cryptography.MLKem):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ true
+
+
+ CP0014
+ M:System.Security.Cryptography.X509Certificates.X509CertificateKeyAccessors.GetMLKemPrivateKey(System.Security.Cryptography.X509Certificates.X509Certificate2):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ true
+
+
+ CP0014
+ M:System.Security.Cryptography.X509Certificates.X509CertificateKeyAccessors.GetMLKemPublicKey(System.Security.Cryptography.X509Certificates.X509Certificate2):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ true
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan{System.Byte},System.Security.Cryptography.PbeParameters):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan{System.Char},System.Security.Cryptography.PbeParameters):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ExportEncryptedPkcs8PrivateKey(System.String,System.Security.Cryptography.PbeParameters):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ExportEncryptedPkcs8PrivateKeyPem(System.ReadOnlySpan{System.Byte},System.Security.Cryptography.PbeParameters):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ExportEncryptedPkcs8PrivateKeyPem(System.ReadOnlySpan{System.Char},System.Security.Cryptography.PbeParameters):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ExportEncryptedPkcs8PrivateKeyPem(System.String,System.Security.Cryptography.PbeParameters):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ExportPkcs8PrivateKey:[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ExportPkcs8PrivateKeyPem:[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ExportSubjectPublicKeyInfo:[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ExportSubjectPublicKeyInfoPem:[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan{System.Byte},System.ReadOnlySpan{System.Byte}):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan{System.Char},System.ReadOnlySpan{System.Byte}):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ImportEncryptedPkcs8PrivateKey(System.String,System.Byte[]):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ImportFromEncryptedPem(System.ReadOnlySpan{System.Char},System.ReadOnlySpan{System.Byte}):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ImportFromEncryptedPem(System.ReadOnlySpan{System.Char},System.ReadOnlySpan{System.Char}):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ImportFromEncryptedPem(System.String,System.Byte[]):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ImportFromEncryptedPem(System.String,System.String):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ImportFromPem(System.ReadOnlySpan{System.Char}):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ImportFromPem(System.String):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ImportPkcs8PrivateKey(System.Byte[]):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ImportPkcs8PrivateKey(System.ReadOnlySpan{System.Byte}):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ImportSubjectPublicKeyInfo(System.Byte[]):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.ImportSubjectPublicKeyInfo(System.ReadOnlySpan{System.Byte}):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan{System.Byte},System.Security.Cryptography.PbeParameters,System.Span{System.Byte},System.Int32@):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan{System.Char},System.Security.Cryptography.PbeParameters,System.Span{System.Byte},System.Int32@):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.TryExportEncryptedPkcs8PrivateKey(System.String,System.Security.Cryptography.PbeParameters,System.Span{System.Byte},System.Int32@):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.TryExportPkcs8PrivateKey(System.Span{System.Byte},System.Int32@):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.TryExportPkcs8PrivateKeyCore(System.Span{System.Byte},System.Int32@):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
+ CP0014
+ M:System.Security.Cryptography.MLKem.TryExportSubjectPublicKeyInfo(System.Span{System.Byte},System.Int32@):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute]
+ lib/net10.0/Microsoft.Bcl.Cryptography.dll
+ lib/net11.0/Microsoft.Bcl.Cryptography.dll
+
+
\ No newline at end of file
diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
index 5249116e7a8976..1134cd2bf68bb0 100644
--- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
+++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
@@ -2840,6 +2840,9 @@
File name: '{0}'
+
+ Requesting assembly: '{0}'
+
Unable to find the specified file.
diff --git a/src/libraries/System.Runtime.Loader/tests/AssemblyLoadContextTest.cs b/src/libraries/System.Runtime.Loader/tests/AssemblyLoadContextTest.cs
index 3292f12de6d7b8..65d12ee3732bf0 100644
--- a/src/libraries/System.Runtime.Loader/tests/AssemblyLoadContextTest.cs
+++ b/src/libraries/System.Runtime.Loader/tests/AssemblyLoadContextTest.cs
@@ -275,5 +275,22 @@ public static void LoadNonRuntimeAssembly()
Exception error = Assert.Throws(() => alc.LoadFromAssemblyName(new AssemblyName("MyAssembly")));
Assert.IsType(error.InnerException);
}
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsCoreCLR))]
+ public static void MissingTransitiveDependency_ExceptionMessageContainsRequestingAssembly()
+ {
+ // MissingDependency.Root depends on MissingDependency.Mid which depends on MissingDependency.Leaf.
+ // MissingDependency.Leaf.dll is not deployed (via PrivateAssets=all in Mid's project reference).
+ // When Root calls Mid's method that uses Leaf types, the runtime throws FileNotFoundException
+ // for the missing Leaf assembly. The exception message should include the full requesting
+ // assembly chain (Mid and Root) so users can diagnose dependency loading issues.
+ FileNotFoundException ex = Assert.Throws(
+ () => MissingDependency.Root.RootClass.UseMiddle());
+
+ Assert.NotNull(ex.FileName);
+ Assert.Contains("MissingDependency.Leaf", ex.FileName);
+ Assert.Contains("MissingDependency.Mid", ex.Message);
+ Assert.Contains("MissingDependency.Root", ex.Message);
+ }
}
}
diff --git a/src/libraries/System.Runtime.Loader/tests/MissingDependency.Leaf/LeafClass.cs b/src/libraries/System.Runtime.Loader/tests/MissingDependency.Leaf/LeafClass.cs
new file mode 100644
index 00000000000000..f6da4365e871ae
--- /dev/null
+++ b/src/libraries/System.Runtime.Loader/tests/MissingDependency.Leaf/LeafClass.cs
@@ -0,0 +1,10 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace MissingDependency.Leaf
+{
+ public class LeafClass
+ {
+ public string GetValue() => "Leaf";
+ }
+}
diff --git a/src/libraries/System.Runtime.Loader/tests/MissingDependency.Leaf/MissingDependency.Leaf.csproj b/src/libraries/System.Runtime.Loader/tests/MissingDependency.Leaf/MissingDependency.Leaf.csproj
new file mode 100644
index 00000000000000..95057b96d5d206
--- /dev/null
+++ b/src/libraries/System.Runtime.Loader/tests/MissingDependency.Leaf/MissingDependency.Leaf.csproj
@@ -0,0 +1,8 @@
+
+
+ $(NetCoreAppCurrent)
+
+
+
+
+
diff --git a/src/libraries/System.Runtime.Loader/tests/MissingDependency.Mid/MidClass.cs b/src/libraries/System.Runtime.Loader/tests/MissingDependency.Mid/MidClass.cs
new file mode 100644
index 00000000000000..59766f3d60fc4c
--- /dev/null
+++ b/src/libraries/System.Runtime.Loader/tests/MissingDependency.Mid/MidClass.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.CompilerServices;
+using MissingDependency.Leaf;
+
+namespace MissingDependency.Mid
+{
+ public class MidClass
+ {
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static string UseLeaf()
+ {
+ return new LeafClass().GetValue();
+ }
+ }
+}
diff --git a/src/libraries/System.Runtime.Loader/tests/MissingDependency.Mid/MissingDependency.Mid.csproj b/src/libraries/System.Runtime.Loader/tests/MissingDependency.Mid/MissingDependency.Mid.csproj
new file mode 100644
index 00000000000000..dfb002634d4be4
--- /dev/null
+++ b/src/libraries/System.Runtime.Loader/tests/MissingDependency.Mid/MissingDependency.Mid.csproj
@@ -0,0 +1,13 @@
+
+
+ $(NetCoreAppCurrent)
+
+
+
+
+
+
+ all
+
+
+
diff --git a/src/libraries/System.Runtime.Loader/tests/MissingDependency.Root/MissingDependency.Root.csproj b/src/libraries/System.Runtime.Loader/tests/MissingDependency.Root/MissingDependency.Root.csproj
new file mode 100644
index 00000000000000..01dcb3ef46c3ba
--- /dev/null
+++ b/src/libraries/System.Runtime.Loader/tests/MissingDependency.Root/MissingDependency.Root.csproj
@@ -0,0 +1,11 @@
+
+
+ $(NetCoreAppCurrent)
+
+
+
+
+
+
+
+
diff --git a/src/libraries/System.Runtime.Loader/tests/MissingDependency.Root/RootClass.cs b/src/libraries/System.Runtime.Loader/tests/MissingDependency.Root/RootClass.cs
new file mode 100644
index 00000000000000..7a665a8874249f
--- /dev/null
+++ b/src/libraries/System.Runtime.Loader/tests/MissingDependency.Root/RootClass.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.CompilerServices;
+using MissingDependency.Mid;
+
+namespace MissingDependency.Root
+{
+ public class RootClass
+ {
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static string UseMiddle()
+ {
+ return MidClass.UseLeaf();
+ }
+ }
+}
diff --git a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj
index 6fa7eb235138d8..e1f3878a0e9983 100644
--- a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj
+++ b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj
@@ -56,6 +56,7 @@
+
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Attributes/JsonNamingPolicyAttribute.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Attributes/JsonNamingPolicyAttribute.cs
new file mode 100644
index 00000000000000..da0b2e246876c4
--- /dev/null
+++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Attributes/JsonNamingPolicyAttribute.cs
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Text.Json.Serialization
+{
+ ///
+ /// When placed on a type, property, or field, indicates what
+ /// should be used to convert property names.
+ ///
+ ///
+ /// When placed on a property or field, the naming policy specified by this attribute
+ /// takes precedence over the type-level attribute and the .
+ /// When placed on a type, the naming policy specified by this attribute takes precedence
+ /// over the .
+ /// The takes precedence over this attribute.
+ ///
+ [AttributeUsage(
+ AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface |
+ AttributeTargets.Property | AttributeTargets.Field,
+ AllowMultiple = false)]
+ public class JsonNamingPolicyAttribute : JsonAttribute
+ {
+ ///
+ /// Initializes a new instance of
+ /// with the specified known naming policy.
+ ///
+ /// The known naming policy to use for name conversion.
+ ///
+ /// The specified is not a valid known naming policy value.
+ ///
+ public JsonNamingPolicyAttribute(JsonKnownNamingPolicy namingPolicy)
+ {
+ NamingPolicy = ResolveNamingPolicy(namingPolicy);
+ }
+
+ ///
+ /// Initializes a new instance of
+ /// with a custom naming policy.
+ ///
+ /// The naming policy to use for name conversion.
+ ///
+ /// is .
+ ///
+ protected JsonNamingPolicyAttribute(JsonNamingPolicy namingPolicy)
+ {
+ if (namingPolicy is null)
+ {
+ ThrowHelper.ThrowArgumentNullException(nameof(namingPolicy));
+ }
+
+ NamingPolicy = namingPolicy;
+ }
+
+ ///
+ /// Gets the naming policy to use for name conversion.
+ ///
+ public JsonNamingPolicy NamingPolicy { get; }
+
+ internal static JsonNamingPolicy ResolveNamingPolicy(JsonKnownNamingPolicy namingPolicy)
+ {
+ return namingPolicy switch
+ {
+ JsonKnownNamingPolicy.CamelCase => JsonNamingPolicy.CamelCase,
+ JsonKnownNamingPolicy.SnakeCaseLower => JsonNamingPolicy.SnakeCaseLower,
+ JsonKnownNamingPolicy.SnakeCaseUpper => JsonNamingPolicy.SnakeCaseUpper,
+ JsonKnownNamingPolicy.KebabCaseLower => JsonNamingPolicy.KebabCaseLower,
+ JsonKnownNamingPolicy.KebabCaseUpper => JsonNamingPolicy.KebabCaseUpper,
+ _ => throw new ArgumentOutOfRangeException(nameof(namingPolicy)),
+ };
+ }
+ }
+}