Undiagnosed null pointer dereference

I was looking at a bug that a customer reported to me, and have reduced the code to the following fragment:

void func(int *z) {

int *b = 0; // This is the customer bug

for (int j = 0; j < 16; j++) {

int c = *b;

c -= *z++;

*b++ = c;

}

}

It is clearly undefined behaviour, and this produces the following IR:

; Function Attrs: norecurse nounwind

define void @func(i32* nocapture readonly) local_unnamed_addr #0 {

unreachable

}

which emits a label for the function in assembly, but no instructions. But if I comment out any of the lines in the loop, I get:

; Function Attrs: norecurse nounwind readnone

define void @func(i32* nocapture) local_unnamed_addr #0 {

ret void

}

then it emits an function which returns immediately.

I was surprised though, that even with ‘-Wall -Wextra’ the de-reference of the null pointer is not diagnosed.

I guess this is a bug, but I haven’t yet gone through the process of reporting bugs.

MartinO

I was looking at a bug that a customer reported to me, and have reduced the code to the following fragment:
void func(int *z) {
  int *b = 0; // This is the customer bug

  for (int j = 0; j < 16; j++) {
    int c = *b;
    c -= *z++;
    *b++ = c;
  }
}
It is clearly undefined behaviour, and this produces the following IR:
; Function Attrs: norecurse nounwind
define void @func(i32* nocapture readonly) local_unnamed_addr #0 {
  unreachable
}
which emits a label for the function in assembly, but no instructions. But if I comment out any of the lines in the loop, I get:
; Function Attrs: norecurse nounwind readnone
define void @func(i32* nocapture) local_unnamed_addr #0 {
  ret void
}
then it emits an function which returns immediately.

I was surprised though, that even with ‘-Wall -Wextra’ the de-reference of the null pointer is not diagnosed.

The compiler frontend doesn't normally do the kind of cross-statement data-flow analysis that would be necessary to report this. I'm sure the static analyzer would report it, though. It would also be exposed dynamically if you built with UBSan.

I don't really see a bug here.

John.

Thanks John,

I decided to try this with GCC v4.8.3, v6.3.0 and VC2015, and none of these compiler detect it either. However, as you expected, the static analyser does identify this perfectly:

ANALYZE (Syntax): bug.cpp func(int *)

ANALYZE (Path, Inline_Regular): bug.cpp func(int *)

bug.cpp:5:13: warning: Dereference of null pointer (loaded from variable ‘b’)

int c = *b;

^~

1 warning generated.

All the best,

MartinO