Skip to content

Commit 6d06a0d

Browse files
authored
fix: thread-safety issue in the runtime (#1780)
We are now more careful about the pointers we send around.
1 parent 19c1f20 commit 6d06a0d

File tree

2 files changed

+18
-7
lines changed

2 files changed

+18
-7
lines changed

RELEASE_NOTES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Upcoming
22

33
- fix: No output when compiling to JavaScript on Windows (https://github.com/dafny-lang/dafny/pull/1824)
4+
- fix: Behavior of the C# runtime in a concurrent setting (https://github.com/dafny-lang/dafny/pull/1780)
45

56

67
# 3.4.1

Source/DafnyRuntime/DafnyRuntime.cs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ public override int Count {
11541154
internal class ConcatSequence<T> : Sequence<T> {
11551155
// INVARIANT: Either left != null, right != null, and elmts's underlying array == null or
11561156
// left == null, right == null, and elmts's underlying array != null
1157-
private ISequence<T> left, right;
1157+
private volatile ISequence<T> left, right;
11581158
private ImmutableArray<T> elmts;
11591159
private readonly int count;
11601160

@@ -1189,15 +1189,25 @@ private ImmutableArray<T> ComputeElements() {
11891189
// Traverse the tree formed by all descendants which are ConcatSequences
11901190
var ansBuilder = ImmutableArray.CreateBuilder<T>();
11911191
var toVisit = new Stack<ISequence<T>>();
1192-
toVisit.Push(right);
1193-
toVisit.Push(left);
1192+
var (leftBuffer, rightBuffer) = (left, right);
1193+
if (left == null || right == null) {
1194+
// elmts can't be .IsDefault while either left, or right are null
1195+
return elmts;
1196+
}
1197+
toVisit.Push(rightBuffer);
1198+
toVisit.Push(leftBuffer);
11941199

11951200
while (toVisit.Count != 0) {
11961201
var seq = toVisit.Pop();
1197-
var cs = seq as ConcatSequence<T>;
1198-
if (cs != null && cs.elmts.IsDefault) {
1199-
toVisit.Push(cs.right);
1200-
toVisit.Push(cs.left);
1202+
if (seq is ConcatSequence<T> { elmts: { IsDefault: true } } cs) {
1203+
(leftBuffer, rightBuffer) = (cs.left, cs.right);
1204+
if (cs.left == null || cs.right == null) {
1205+
// !cs.elmts.IsDefault, due to concurrent enumeration
1206+
toVisit.Push(cs);
1207+
} else {
1208+
toVisit.Push(rightBuffer);
1209+
toVisit.Push(leftBuffer);
1210+
}
12011211
} else {
12021212
var array = seq.Elements;
12031213
ansBuilder.AddRange(array);

0 commit comments

Comments
 (0)