Fixed, thanks! I did not see this because my memcpy()
does not have the nonnull attribute.
Off-topic: the nonnull attribute has this speciality - the compiler assumes that the parameter will never be null and may eliminate branches in the function that check for that. For example:
0void func(char* buf) __nonnull(1)
1{
2 if (buf == nullptr) {
3 // take action
4 return;
5 }
6 buf[0] = 1;
7}
Compiler optimization may reduce this to:
0void func(char* buf) __nonnull(1)
1{
2 buf[0] = 1;
3}
It looks reasonable, given that code like func(nullptr);
will not compile. However, if the value of the argument is determined at runtime and may still end up being nullptr
, then the compiler has no way to detect this during compilation. So the line buf[0] = 1;
may still be executed with buf
being nullptr
even though the source code checks for that just above, leading to some nice “wtf” moments.
Ubsan alleviates this.