From 7ebc86ed8d8800f2743d492cd35abe0cc56210a3 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 2 Sep 2026 11:03:19 +0200 Subject: [PATCH] Unsafe evolution: fix a race in version decoding --- .../Symbols/Metadata/PE/PEModuleSymbol.cs | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEModuleSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEModuleSymbol.cs index e6177e8c9e634..77d2b5a1ac608 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEModuleSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEModuleSymbol.cs @@ -116,7 +116,7 @@ internal enum RefSafetyRulesAttributeVersion private RefSafetyRulesAttributeVersion _lazyRefSafetyRulesAttributeVersion; - private MemorySafetyRulesVersion? _lazyMemorySafetyRulesVersion; + private SingleInitNullable _lazyMemorySafetyRulesVersion; #nullable enable private DiagnosticInfo? _lazyCachedCompilerFeatureRequiredDiagnosticInfo = CSDiagnosticInfo.EmptyErrorInfo; @@ -753,16 +753,14 @@ internal override MemorySafetyRulesVersion MemorySafetyRulesVersion { get { - return _lazyMemorySafetyRulesVersion ??= getAttributeVersion(); - - // Returns - // * recognized: 1 if the attribute is not present, - // * recognized: 2 if the attribute is present and has the value 2, - // * unrecognized: -1 if the attribute is present and has the value 1 or some non-integer value, - // * unrecognized: the attribute's value (which is other than 1 or 2). - MemorySafetyRulesVersion getAttributeVersion() + return _lazyMemorySafetyRulesVersion.Initialize(static @this => { - if (_module.HasMemorySafetyRulesAttribute(Token, out int version, out bool foundAttributeType) && + // Returns + // * recognized: 1 if the attribute is not present, + // * recognized: 2 if the attribute is present and has the value 2, + // * unrecognized: -1 if the attribute is present and has the value 1 or some non-integer value, + // * unrecognized: the attribute's value (which is other than 1 or 2). + if (@this._module.HasMemorySafetyRulesAttribute(Token, out int version, out bool foundAttributeType) && version != (int)MemorySafetyRulesVersion.Version1) { return (MemorySafetyRulesVersion)version; @@ -771,7 +769,7 @@ MemorySafetyRulesVersion getAttributeVersion() return foundAttributeType ? (MemorySafetyRulesVersion)(-1) : MemorySafetyRulesVersion.Version1; - } + }, this); } }