Clang: one savvy code analyzer! No Comments
Given this code:
- (void)calculateData:(int32_t)n intoLeftBuffer:(int16_t *)lbuf rightBuffer:(int16_t *)rbuf { static uint64_t (*calculateInternalCall)(id, SEL) = NULL; if (!calculateInternalCall) calculateInternalCall = (uint64_t (*)(id, SEL))[self methodForSelector:@selector(calculateInternal)]; uint64_t leftEnableMask = self.isEnabled && lbuf ? ((-(is0Enabled & leftEnabled[0])) & 0xFFFF000000000000) | ((-(is1Enabled & leftEnabled[1])) & 0x0000FFFF00000000) | ((-(is2Enabled & leftEnabled[2])) & 0x00000000FFFF0000) | ((-(is3Enabled & leftEnabled[3])) & 0x000000000000FFFF) : 0, rightEnableMask = self.isEnabled && rbuf ? ((-(is0Enabled & rightEnabled[0])) & 0xFFFF000000000000) | ((-(is1Enabled & rightEnabled[1])) & 0x0000FFFF00000000) | ((-(is2Enabled & rightEnabled[2])) & 0x00000000FFFF0000) | ((-(is3Enabled & rightEnabled[3])) & 0x000000000000FFFF) : 0; for (int32_t i = 0; i < n; ++i) { uint64_t data = calculateInternalCall(self, @selector(calculateInternal)), lv = data & leftEnableMask, rv = data & rightEnableMask; int16_t *l = (int16_t *)&lv, *r = (int16_t *)&rv; lbuf[i] += l[0] + l[1] + l[2] + l[3]; rbuf[i] += r[0] + r[1] + r[2] + r[3]; } }
Where are the two NULL dereferences Clang claims to have found?
Answer: In the assignments to lbuf and rbuf. By checking whether the pointers are NULL earlier in the function, I alerted Clang to the possibility that they might be at all. Since the code doesn’t subsequently check for NULL before actually writing to the pointers, this was a valid warning. Nice catch, Clang!
Clang’s Website. I highly recommend it.
January 25, 2010 at 12:12 pm