Skip to content

Commit c7d8c15

Browse files
committed
v.0.2.2.12-beta
Fixed a Bug 92 where copying a protected resource into another ref-struct declared in a larger scope (of the same type or containing a field at any level of nesting in its graph) could result in unsynchronized access. Fix was accomplished by the addition of more analyzer rules and attributes that can trigger them. Unit tests were added to validate the fix and code was added to the ExampleCodePlayground demonstrating Bug92. A full description of Bug 92, the new attributes and analyzer rules is available now in "DotNetVault Description.pdf".
1 parent 929151b commit c7d8c15

File tree

78 files changed

+5002
-714
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+5002
-714
lines changed

CafeBabeGame/CafeBabeGame/CafeBabeGame.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
</PropertyGroup>
1414

1515
<ItemGroup>
16-
<PackageReference Include="DotNetVault" Version="0.2.2.1-beta" />
16+
<PackageReference Include="DotNetVault" Version="0.2.2.12-beta" />
1717
<PackageReference Include="HighPrecisionTimeStamps" Version="0.0.1-alpha" />
1818
</ItemGroup>
1919

CafeBabeGame/CafeBabeGame/Program.cs

+287-175
Large diffs are not rendered by default.

Clorton Game/ClortonGameDemo/ClortonGameDemo.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
</PropertyGroup>
1414

1515
<ItemGroup>
16-
<PackageReference Include="DotNetVault" Version="0.2.2.1-beta" />
16+
<PackageReference Include="DotNetVault" Version="0.2.2.12-beta" />
1717
<PackageReference Include="HighPrecisionTimeStamps" Version="0.0.1-alpha" />
1818
</ItemGroup>
1919

ConsoleStressTest/ConsoleStressTest.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
</PropertyGroup>
1818

1919
<ItemGroup>
20-
<PackageReference Include="DotNetVault" Version="0.2.2.1-beta" />
20+
<PackageReference Include="DotNetVault" Version="0.2.2.12-beta" />
2121
</ItemGroup>
2222

2323
</Project>

DotNetVault Description.docx

43.9 KB
Binary file not shown.

DotNetVault Description.pdf

127 KB
Binary file not shown.

DotNetVault.Test/AnalyzerYetAgainUnitTests.cs

+141-3
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,7 @@ public void TestEarlyReleaseErrorCaseAttrib()
112112
var test = ResourceFiles.EarlyReleaseTestCases.EarlyReleaseErrorCaseHaver;
113113
VerifyCSharpDiagnostic(test, col => col.Count() == 1, dx => dx.Id == DotNetVaultAnalyzer.DotNetVault_EarlyDisposeJustification &&
114114
dx.Severity == DiagnosticSeverity.Info && dx.DefaultSeverity == DiagnosticSeverity.Info &&
115-
dx.GetMessage().Contains("DisposingOnError"));
116-
}
115+
dx.GetMessage().Contains("DisposingOnError")); }
117116

118117
[TestMethod]
119118
public void TestUnjustifiedEarlyRelease()
@@ -164,6 +163,71 @@ public void TestNotVsBadBase()
164163
dx => true);
165164
}
166165

166+
[TestMethod]
167+
public void TestNotOkBadAssignUs()
168+
{
169+
var test = ResourceFiles.NdiTestCases.NoCopyBadAssignUsingStatement;
170+
SortedSet<string> expectedIds = new SortedSet<string>{DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoCopyAssignment, DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoCopyIllegalPass};
171+
VerifyCSharpDiagnostic(test,
172+
dxes => new SortedSet<string>(dxes.Select(dx => dx.Descriptor.Id)).SetEquals(expectedIds), dx => true);
173+
174+
175+
}
176+
177+
[TestMethod]
178+
public void TestInlineNotOkCase()
179+
{
180+
Dictionary<string, int> expectedCounts = new Dictionary<string, int>
181+
{
182+
{DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoCopyAssignment, 8},
183+
{DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoCopyIllegalPass, 4},
184+
{DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoLockedResourceWrappersAllowedInScope, 2}
185+
};
186+
187+
Dictionary<string, int> actualCounts = new Dictionary<string, int>
188+
{
189+
{DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoCopyAssignment, 0},
190+
{DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoCopyIllegalPass, 0},
191+
{DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoLockedResourceWrappersAllowedInScope, 0}
192+
};
193+
194+
var test = ResourceFiles.NdiTestCases.NoCopyAttributeWithBadAssignment;
195+
VerifyCSharpDiagnostic(test, dxes =>
196+
{
197+
foreach (var dx in dxes)
198+
{
199+
++actualCounts[dx.Id];
200+
}
201+
return actualCounts.All(kvp => expectedCounts[kvp.Key] == kvp.Value);
202+
203+
}, dx => true);
204+
}
205+
206+
[TestMethod]
207+
public void TestCopyAssignmentOne()
208+
{
209+
var test = ResourceFiles.CopyAssignmentTestCases.CopyAssignmentTestCase1;
210+
VerifyCSharpDiagnostic(test, col => col.Count() == 3,
211+
dx => dx.Id == DotNetVaultAnalyzer
212+
.DotNetVault_UsingMandatory_IrregularLockedResourceObjects_NotAllowedInScope);
213+
}
214+
215+
[TestMethod]
216+
public void TestCopyAssignmentTwo()
217+
{
218+
var test = ResourceFiles.CopyAssignmentTestCases.CopyAssignmentTestCase2;
219+
VerifyCSharpDiagnostic(test, col => col.Count() == 1,
220+
dx => dx.Id == DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoCopyAssignment);
221+
}
222+
223+
[TestMethod]
224+
public void TestBadExtensionMethod()
225+
{
226+
var test = ResourceFiles.NdiTestCases.ExtensionMethodPbvTest;
227+
VerifyCSharpDiagnostic(test, dxes => dxes.SingleOrDefault() != null,
228+
dx => dx.Id == DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoCopyIllegalPass_ExtMethod);
229+
}
230+
167231
[TestMethod]
168232
public void TestNdiOkCases()
169233
{
@@ -217,6 +281,78 @@ static bool TestIndividuals(Diagnostic dx) =>
217281
(dx.Id == DotNetVaultAnalyzer.DotNetVault_NotDirectlyInvocable && dx.Location.GetLineSpan().StartLinePosition.Line == zeroIdxVersion);
218282
}
219283

284+
[TestMethod]
285+
public void TestNdiNotOkIllegalWrapper()
286+
{
287+
var test = ResourceFiles.NdiTestCases.IllegalWrapperTestCase;
288+
VerifyCSharpDiagnostic(test, col => col.Count() == 2,
289+
dx => dx.Descriptor.Id ==
290+
DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoLockedResourceWrappersAllowedInScope);
291+
}
292+
293+
[TestMethod]
294+
public void TestNdiNotOkIllegalWrapperTestCaseTwo()
295+
{
296+
var test = ResourceFiles.NdiTestCases.illegalwrappertestcase2;
297+
VerifyCSharpDiagnostic(test, col => col.Any(), dx => true);
298+
}
299+
300+
[TestMethod]
301+
public void TestNdiNotOkIllegalWrapperCaseThree()
302+
{
303+
var test = ResourceFiles.NdiTestCases.illegalwrappertestcase3;
304+
VerifyCSharpDiagnostic(test, col => col.Count() == 1,
305+
dx => dx.Id == DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoLockedResourceWrappersAllowedInScope);
306+
}
307+
308+
[TestMethod]
309+
public void TestNdiNotOkIllegalWrapperCaseFour()
310+
{
311+
var test = ResourceFiles.NdiTestCases.IllegalWrapperTestCase4;
312+
VerifyCSharpDiagnostic(test, col => col.Any(),
313+
dx => dx.Id == DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoLockedResourceWrappersAllowedInScope);
314+
}
315+
316+
[TestMethod]
317+
public void TestNdiNotOkDeepIllegalWrapper()
318+
{
319+
var test = ResourceFiles.NdiTestCases.TestDeepIllegalWrapper;
320+
VerifyCSharpDiagnostic(test, col => col.Count() == 2,
321+
dx => dx.Descriptor.Id ==
322+
DotNetVaultAnalyzer.DotNetVault_UsingMandatory_NoLockedResourceWrappersAllowedInScope);
323+
}
324+
325+
[TestMethod]
326+
public void TestDeepWrapperActuallyOk()
327+
{
328+
var test = ResourceFiles.NdiTestCases.TestDeepWrapperActuallyOk;
329+
VerifyCSharpDiagnostic(test);
330+
}
331+
332+
[TestMethod]
333+
public void TestRefStructAttrOkCases()
334+
{
335+
var test = ResourceFiles.RefStructAttributeTestCases.RefStructAttributeTestsOk;
336+
VerifyCSharpDiagnostic(test);
337+
}
338+
339+
[TestMethod]
340+
public void TestRefStructAttrNotOkCase1()
341+
{
342+
var test = ResourceFiles.RefStructAttributeTestCases.RefStructAttrNotOkCase1;
343+
VerifyCSharpDiagnostic(test, col => col.Count() == 1,
344+
dx => dx.Descriptor.Id == DotNetVaultAnalyzer.DotNetVault_OnlyOnRefStruct);
345+
}
346+
347+
[TestMethod]
348+
public void TestRefStructAttrNotOkCase2()
349+
{
350+
var test = ResourceFiles.RefStructAttributeTestCases.RoRegularNotARefStructCase2;
351+
VerifyCSharpDiagnostic(test, col => col.Count() == 1,
352+
dx => dx.Descriptor.Id == DotNetVaultAnalyzer.DotNetVault_OnlyOnRefStruct);
353+
}
354+
355+
220356
[TestMethod]
221357
public void TestNotVsEx()
222358
{
@@ -583,7 +719,8 @@ private static Project CreateProject(string[] sources, string language = Languag
583719
.AddMetadataReference(projectId, UriReference)
584720
.AddMetadataReference(projectId, NameReference)
585721
.AddMetadataReference(projectId, NdiReference)
586-
.AddMetadataReference(projectId, UmReference);
722+
.AddMetadataReference(projectId, UmReference)
723+
.AddMetadataReference(projectId, NcReference);
587724

588725

589726
int count = 0;
@@ -610,5 +747,6 @@ private static Project CreateProject(string[] sources, string language = Languag
610747
private static readonly MetadataReference NameReference = MetadataReference.CreateFromFile(typeof(Name).Assembly.Location);
611748
private static readonly MetadataReference NdiReference = MetadataReference.CreateFromFile(typeof(NoDirectInvokeAttribute).Assembly.Location);
612749
private static readonly MetadataReference UmReference = MetadataReference.CreateFromFile(typeof(UsingMandatoryAttribute).Assembly.Location);
750+
private static readonly MetadataReference NcReference = MetadataReference.CreateFromFile(typeof(NoCopyAttribute).Assembly.Location);
613751
}
614752
}

DotNetVault.Test/DotNetVault.Test.csproj

+37-10
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,18 @@
3636
<Compile Remove="TestCases\BvIllegalRefExprTestCase4.cs" />
3737
<Compile Remove="TestCases\ConditionallyImmutableClassNonRoImmutF.cs" />
3838
<Compile Remove="TestCases\ConditionallyImmutStructWithNonROImmutF.cs" />
39+
<Compile Remove="TestCases\CopyAssignmentTestCase1.cs" />
40+
<Compile Remove="TestCases\CopyAssignmentTestCase2.cs" />
3941
<Compile Remove="TestCases\DataFlowTestCases.cs" />
4042
<Compile Remove="TestCases\DelegateCreationOpsAndDynamic.cs" />
4143
<Compile Remove="TestCases\DiagnosticALittleMoreComplex.cs" />
4244
<Compile Remove="TestCases\EarlyReleaseErrorCaseHaver.cs" />
4345
<Compile Remove="TestCases\EmitsDiagnosticUmRequiresInlineDecl.cs" />
4446
<Compile Remove="TestCases\EventArgsOkTest.cs" />
47+
<Compile Remove="TestCases\ExtensionMethodPbvTest.cs" />
48+
<Compile Remove="TestCases\IllegalWrapperTestCase.cs" />
49+
<Compile Remove="TestCases\illegalwrappertestcase2.cs" />
50+
<Compile Remove="TestCases\illegalwrappertestcase3.cs" />
4551
<Compile Remove="TestCases\ImmutableCollectionIsVaultSafe.cs" />
4652
<Compile Remove="TestCases\ImmutableStructIsVaultSafe.cs" />
4753
<Compile Remove="TestCases\ImmutableStructIsVsUnmanaged.cs" />
@@ -50,6 +56,8 @@
5056
<Compile Remove="TestCases\NdiMixedWithNotInlineNotOkCaseThree.cs" />
5157
<Compile Remove="TestCases\NdiNotOkCaseOne.cs" />
5258
<Compile Remove="TestCases\NdiNotOkTestTwo.cs" />
59+
<Compile Remove="TestCases\NoCopyAttributeWithBadAssignment.cs" />
60+
<Compile Remove="TestCases\NoCopyBadAssignUsingStatement.cs" />
5361
<Compile Remove="TestCases\NoDiagnosticALittleMoreComplex.cs" />
5462
<Compile Remove="TestCases\NoDiagnosticAttributeButAllUpper.cs" />
5563
<Compile Remove="TestCases\NoDiagnosticBecauseOnFaith.cs" />
@@ -59,12 +67,17 @@
5967
<Compile Remove="TestCases\NotVsException.cs" />
6068
<Compile Remove="TestCases\NullableNotHeldAgainstTest.cs" />
6169
<Compile Remove="TestCases\QueryTestCases.cs" />
70+
<Compile Remove="TestCases\RefStructAttributeTestsOk.cs" />
71+
<Compile Remove="TestCases\RefStructAttrNotOkCase1.cs" />
72+
<Compile Remove="TestCases\RoRegularNotARefStructCase2.cs" />
6273
<Compile Remove="TestCases\SbAndUriBNotVaultSafe.cs" />
6374
<Compile Remove="TestCases\ShouldTriggerDiagnosticBecauseNoUsing.cs" />
6475
<Compile Remove="TestCases\ShouldTriggerDiagnosticLowercaseAndVsAttribute.cs" />
6576
<Compile Remove="TestCases\ShouldTriggerDiagnosticLowercaseAndVsAttributeV2.cs" />
6677
<Compile Remove="TestCases\ShouldTriggerDiagnosticLowercaseAndVsAttributeV3.cs" />
6778
<Compile Remove="TestCases\TestBaseClassWbVsIfSealed.cs" />
79+
<Compile Remove="TestCases\TestDeepIllegalWrapper.cs" />
80+
<Compile Remove="TestCases\TestDeepWrapperActuallyOk.cs" />
6881
<Compile Remove="TestCases\TestDynamicNeverConsideredVaultSafe.cs" />
6982
<Compile Remove="TestCases\TestEarlyReleaseBadJustification.cs" />
7083
<Compile Remove="TestCases\TestFindEarlyReleaseAttribute.cs" />
@@ -81,15 +94,15 @@
8194
</ItemGroup>
8295

8396
<ItemGroup>
84-
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="2.9.6">
97+
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.0">
8598
<PrivateAssets>all</PrivateAssets>
8699
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
87100
</PackageReference>
88-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.3.1" />
89-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
90-
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
91-
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
92-
<PackageReference Include="System.Collections.Immutable" Version="1.6.0" />
101+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.7.0" />
102+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
103+
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
104+
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
105+
<PackageReference Include="System.Collections.Immutable" Version="1.7.1" />
93106
</ItemGroup>
94107

95108
<ItemGroup>
@@ -118,6 +131,11 @@
118131
<AutoGen>True</AutoGen>
119132
<DependentUpon>ConditionallyVsImmutableTypes.resx</DependentUpon>
120133
</Compile>
134+
<Compile Update="ResourceFiles\CopyAssignmentTestCases.Designer.cs">
135+
<DesignTime>True</DesignTime>
136+
<AutoGen>True</AutoGen>
137+
<DependentUpon>CopyAssignmentTestCases.resx</DependentUpon>
138+
</Compile>
121139
<Compile Update="ResourceFiles\EarlyReleaseTestCases.Designer.cs">
122140
<DesignTime>True</DesignTime>
123141
<AutoGen>True</AutoGen>
@@ -133,6 +151,11 @@
133151
<AutoGen>True</AutoGen>
134152
<DependentUpon>NullableNotHeldAgainstTests.resx</DependentUpon>
135153
</Compile>
154+
<Compile Update="ResourceFiles\RefStructAttributeTestCases.Designer.cs">
155+
<DesignTime>True</DesignTime>
156+
<AutoGen>True</AutoGen>
157+
<DependentUpon>RefStructAttributeTestCases.resx</DependentUpon>
158+
</Compile>
136159
<Compile Update="ResourceFiles\UsingMandatoryTestCases.Designer.cs">
137160
<DesignTime>True</DesignTime>
138161
<AutoGen>True</AutoGen>
@@ -201,6 +224,10 @@
201224
<Generator>ResXFileCodeGenerator</Generator>
202225
<LastGenOutput>ConditionallyVsImmutableTypes.Designer.cs</LastGenOutput>
203226
</EmbeddedResource>
227+
<EmbeddedResource Update="ResourceFiles\CopyAssignmentTestCases.resx">
228+
<Generator>ResXFileCodeGenerator</Generator>
229+
<LastGenOutput>CopyAssignmentTestCases.Designer.cs</LastGenOutput>
230+
</EmbeddedResource>
204231
<EmbeddedResource Update="ResourceFiles\EarlyReleaseTestCases.resx">
205232
<Generator>ResXFileCodeGenerator</Generator>
206233
<LastGenOutput>EarlyReleaseTestCases.Designer.cs</LastGenOutput>
@@ -213,6 +240,10 @@
213240
<Generator>ResXFileCodeGenerator</Generator>
214241
<LastGenOutput>NullableNotHeldAgainstTests.Designer.cs</LastGenOutput>
215242
</EmbeddedResource>
243+
<EmbeddedResource Update="ResourceFiles\RefStructAttributeTestCases.resx">
244+
<Generator>ResXFileCodeGenerator</Generator>
245+
<LastGenOutput>RefStructAttributeTestCases.Designer.cs</LastGenOutput>
246+
</EmbeddedResource>
216247
<EmbeddedResource Update="ResourceFiles\UsingMandatoryTestCases.resx">
217248
<Generator>ResXFileCodeGenerator</Generator>
218249
<LastGenOutput>UsingMandatoryTestCases.Designer.cs</LastGenOutput>
@@ -255,8 +286,4 @@
255286
<ProjectReference Include="..\DotNetVault\DotNetVault.csproj" />
256287
</ItemGroup>
257288

258-
<ItemGroup>
259-
<Folder Include="TestCases\" />
260-
</ItemGroup>
261-
262289
</Project>

0 commit comments

Comments
 (0)