Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix potential NoDelta leak into IReplicatedData.Merge() #4811

Conversation

Arkatufus
Copy link
Contributor

Related to #4806
Minimize the number of changes to only those that directly relates to the bug.

@@ -105,19 +104,17 @@ public void Delete(string key)
var cacheKey = (key, fromSeqNr, toSeqNr);
if (!cache.TryGetValue(cacheKey, out var deltaGroup))
{
using (var e = deltaEntriesAfterJ.Values.GetEnumerator())
deltaGroup = deltaEntriesAfterJ.Values.Aggregate((d1, d2) =>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced the suspicious looking code block with one that makes a lot more sense.
This is the scala code for reference:

val group = deltaEntriesAfterJ.valuesIterator.reduceLeft { (d1, d2) =>
  val merged = d2 match {
    case NoDeltaPlaceholder => NoDeltaPlaceholder
    case _                  =>
      // this is fine also if d1 is a NoDeltaPlaceholder
      d1.merge(d2.asInstanceOf[d1.T])
  }
  merged match {
    case s: ReplicatedDeltaSize if s.deltaSize >= maxDeltaSize =>
      // discard too large deltas
      NoDeltaPlaceholder
    case _ => merged
  }
}

reduceLeft works exactly the same as LINQ Aggregate

deltaGroup = e.Current;
while (e.MoveNext())
{
deltaGroup = deltaGroup.Merge(e.Current);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bug happened here, a NoDelta null delta marker got passed into this line and ORDictionary could not cast it to DeltaGroup

@@ -68,13 +69,11 @@ public void Delete(string key)
if (all.Length <= sliceSize) slice = all;
else
{
var start = (int)(_deltaNodeRoundRobinCounter % all.Length);
Copy link
Contributor Author

@Arkatufus Arkatufus Mar 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part of the code also looks suspicious, so I re-ported it with a cleaner one.
Reference scala code:

val i = (deltaNodeRoundRobinCounter % all.size).toInt
val first = all.slice(i, i + sliceSize)
if (first.size == sliceSize) first
else first ++ all.take(sliceSize - first.size)

}
slice = ImmutableArray.CreateRange(buffer);
var i = (int)(_deltaNodeRoundRobinCounter % all.Length);
slice = all.Slice(i, sliceSize).ToImmutableArray();
Copy link
Contributor Author

@Arkatufus Arkatufus Mar 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code looks different than the reference scala because in scala, slice parameters are from and to, while in C#, slice parameters are from and count

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - I was just about to ask

@Arkatufus Arkatufus requested a review from Aaronontheweb March 4, 2021 19:29
Copy link
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

}
slice = ImmutableArray.CreateRange(buffer);
var i = (int)(_deltaNodeRoundRobinCounter % all.Length);
slice = all.Slice(i, sliceSize).ToImmutableArray();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - I was just about to ask

@Aaronontheweb Aaronontheweb merged commit 114d165 into akkadotnet:dev Mar 5, 2021
@Arkatufus Arkatufus deleted the #4806_NoDelta_leaked_into_ORDictionary_minimalist branch March 8, 2021 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants