Skip to content

Commit

Permalink
Workaround hash collision between literals 'null' and 'false' in DFA
Browse files Browse the repository at this point in the history
  • Loading branch information
Youssef1313 committed Aug 20, 2023
1 parent 3587540 commit ff945db
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -7763,6 +7763,31 @@ internal void Open()
}.RunAsync();
}

[Fact]
public async Task NullableBooleanComparisonWithNullAndFalse()
{
var code = """
public class Test
{
public static void Method(string parameter)
{
var flag = GetFlag();

if (flag == null || flag == false)
{
if (flag == false)
{
}
}
}

public static bool? GetFlag() => false;
}

""";
await VerifyCS.VerifyCodeFixAsync(code, code);
}

[Trait(Traits.DataflowAnalysis, Traits.Dataflow.PointsToAnalysis)]
[Trait(Traits.DataflowAnalysis, Traits.Dataflow.NullAnalysis)]
[Fact, WorkItem(4984, "https://github.com/dotnet/roslyn-analyzers/issues/4984")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,32 @@ protected override void ComputeHashCodeParts(ref RoslynHashCode hashCode)
protected override bool ComputeEqualsByHashCodeParts(CacheBasedEquatable<ValueContentAbstractValue> obj)
{
var other = (ValueContentAbstractValue)obj;
return HashUtilities.Combine(LiteralValues) == HashUtilities.Combine(other.LiteralValues)
if (LiteralValues.Count != other.LiteralValues.Count)
{
return false;
}

var hashCode1 = new RoslynHashCode();
int nullCount1 = 0;
foreach (var value1 in LiteralValues)
{
hashCode1.Add(value1);
if (value1 is null)
nullCount1++;
}

var hashCode2 = new RoslynHashCode();
int nullCount2 = 0;
foreach (var value2 in other.LiteralValues)
{
hashCode2.Add(value2);
if (value2 is null)
nullCount2++;
}

// null and false can easily cause hash collisions and cause incorrect behaviors.
// We count the nulls to workaround this collision.
return nullCount1 == nullCount2 && hashCode1.ToHashCode() == hashCode2.ToHashCode()
&& NonLiteralState.GetHashCode() == other.NonLiteralState.GetHashCode();
}

Expand Down

0 comments on commit ff945db

Please sign in to comment.