False positive Is null on at least one path when null check in method

Hi,
We’re getting false positives on S2259: is null on at least one execution path, when our null check is in method. We have a wrapper on checking null to simplify it, but sonar doesn’t understand it and throwing an errors all the time. Can you help us, please?
Example below:

public class Class1
{
    public void Check() {
        Monkey? _monkey = null;

        QAssert.IsNotNull(_monkey);

        Console.WriteLine(_monkey.Name);
    }

}

public class Monkey
{
    public string? Name { get; set; }
}

public static class QAssert
{
    public static void IsNotNull(Monkey? o)
    {
        if (o is null)
        {
            throw new ArgumentException("Wrong Monkey");
        }
    }
}

Hi,

Welcome to the community!

What’s your version of SonarQube?

 
Ann

Actually we have latest version of SonarCloud, I’m sorry for confusion.

Hi,

Thanks for the clarification. And I should have asked this to start with: is this C#? (That’s my guess, but…)

 
Ann

Yes, it’s C# :wink:

1 Like

Hi Łukasz,
I can reproduce the behavior: we are aware of this limitation but have a workaround.

The symbolic execution engine, that powers the rule S2259, is currently single-method-based and is not looking into the effects that the method QAssert.IsNotNull has on the Class1.Check.

That means that after the second line of Class1.Check (QAssert.IsNotNull(_monkey);), the engine doesn’t infer that _monkey can’t possibly be null, because otherwise QAssert.IsNotNull would have raised an exception and the flow would have never reached the instruction Console.WriteLine(_monkey.Name);.

Scenarios involving constraints from other methods are complex to handle, and while we may tackle them in the future, we provide a workaround to handle cases like yours, by declaring a ValidatedNotNullAttribute and decorating the Monkey?o parameter of QAssert.IsNotNull with that attribute:

public static class QAssert
{
    public static void IsNotNull([ValidatedNotNull]Monkey? o)
    {
        if (o is null)
        {
            throw new ArgumentException("Wrong Monkey");
        }
    }
}

public sealed class ValidatedNotNullAttribute : Attribute { }

That will help our engine understand that, whenever QAssert.IsNotNull is called, its first parameter is going to be checked against null, and have that constraint in the following steps of the execution.

More information about the use of the ValidatedNotNullAttribute is available in the description of the C# version of the S2259 rule: RSPEC

Let me know if that helps,
Antonio

Thanks Antonio for workaround, it worked :wink: I hope that it will be fixed in new versions without this workaround :wink: