Clang Static Analyser no longer checks for NULL dereferences

Originator:macmade
Number:rdar://33242810 Date Originated:July 11 2017, 9:05 PM
Status:Closed Resolved:Yes
Product:Developer Tools Product Version:
Classification:Serious Bug Reproducible:Always
 
Summary:

Xcode used to be able to check for NULL pointer dereferences when analysing a project, with the Clang Static Analyser.

It looks like it is no longer the case with Xcode 9.

--------------------------------------------------

Steps to Reproduce:

Use some very basic/simple code that dereferences NULL pointers, like:

    int * _Nullable foo( void );
    int * _Nullable foo( void )
    {
        return NULL;
    }

    int main( void )
    {
        int * p1 = foo();
        int * p2 = NULL;
        
        printf( "%i\n", *( foo() ) );
        printf( "%i\n", *( p1 ) );
        printf( "%i\n", *( ( volatile int * )NULL ) );
        
        int i1 = *( p1 );
        int i2 = *( p2 );
        
        printf( "%i\n", i1 );
        printf( "%i\n", i2 );
        
        return 0;
    }

--------------------------------------------------

Expected Results:

When running the analyser, it should warn about possible NULL pointer dereferences.

--------------------------------------------------

Observed Results:

No warning is issued.

--------------------------------------------------

Version:

macOS 10.13 Beta (17A306f)
Xcode 9.0 beta 3 (9M174d)

--------------------------------------------------

Notes:

Attached is a project demonstrating the issue.

Comments

Jean-David Gadina

Thanks a lot for the detailed answer. I did not realise this behaviour was changed so many versions ago.

I can understand the reason behind this. Anyway, as long as I can turn this analysis back on with a custom build setting, I'm fine wit it.

Thanks : )

Apple Developer Relations

Engineering has provided the following information regarding this issue:

The analyzer has heuristics to suppress null pointer dereference diagnostics where the null value comes from a return in a called function. We found that in practice many of these returns were error paths that were not feasible but that the analyzer didn’t realize were not feasible. This means that after the dereference *(foo()) the analyzer is intentionally deciding not to report an issue and not to continue along that path.

This behavior dates back to at least Xcode 4.6 — it is not new. You can turn this heuristic off with a the following custom build setting:

CLANG_ANALYZER_OTHER_FLAGS = -analyzer-config suppress-null-return-paths=false

That will tell the analyzer not to suppress those paths.

Note that even with the heuristic disabled, you will still only get one report in main(). This is because we intentionally do not report any further issues along a path after reporting a null pointer dereference. The reason is that a null pointer dereference is bad enough that any further reports on that path are likely to not be helpful.


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!