Hey, I was running the [cppcheck](https://cppcheck.sourceforge.io/) static analysis tool, found a few potential bugs, and wrote the following to share how tools like this can help us ensure the integrity of our code. The following are some bugs found. If anyone is interested in running cppcheck on their project, scroll to the bottom for a HOW-TO. Is using a static analysis tool like this something we'd be interested in adding to ci/cd?
*The following were found in NuttX 12.2.1* ## Null pointer dereference #### 1: sched/signal/sig_dispatch.c:325 ``` src/deps/nuttx/sched/signal/sig_dispatch.c:325:26: warning: Either the condition 'info!=NULL' is redundant or there is possible null pointer dereference: info. [nullPointerRedundantCheck] stcb, stcb->pid, info->si_signo, info->si_code, ^ src/deps/nuttx/sched/signal/sig_dispatch.c:329:36: note: Assuming that condition 'info!=NULL' is not redundant DEBUGASSERT(stcb != NULL && info != NULL); ^ src/deps/nuttx/sched/signal/sig_dispatch.c:325:26: note: Null pointer dereference stcb, stcb->pid, info->si_signo, info->si_code, ^ ``` #### 2: sched/signal/sig_dispatch.c:326 ``` src/deps/nuttx/sched/signal/sig_dispatch.c:326:9: warning: Either the condition 'info!=NULL' is redundant or there is possible null pointer dereference: info. [nullPointerRedundantCheck] info->si_value.sival_int, ^ src/deps/nuttx/sched/signal/sig_dispatch.c:329:36: note: Assuming that condition 'info!=NULL' is not redundant DEBUGASSERT(stcb != NULL && info != NULL); ^ src/deps/nuttx/sched/signal/sig_dispatch.c:326:9: note: Null pointer dereference info->si_value.sival_int, ^ ``` #### 3: sched/signal/sig_dispatch.c:327 ``` src/deps/nuttx/sched/signal/sig_dispatch.c:327:41: warning: Either the condition 'info!=NULL' is redundant or there is possible null pointer dereference: info. [nullPointerRedundantCheck] sigismember(&stcb->sigprocmask, info->si_signo) == 1 ? "YES" : "NO"); ^ src/deps/nuttx/sched/signal/sig_dispatch.c:329:36: note: Assuming that condition 'info!=NULL' is not redundant DEBUGASSERT(stcb != NULL && info != NULL); ^ src/deps/nuttx/sched/signal/sig_dispatch.c:327:41: note: Null pointer dereference sigismember(&stcb->sigprocmask, info->si_signo) == 1 ? "YES" : "NO"); ^ ``` #### 4: src/deps/nuttx/libs/libc/stdlib/lib_mbstowcs.c:42 ``` src/deps/nuttx/libs/libc/stdlib/lib_mbstowcs.c:42:36: error: Null pointer dereference [nullPointer] return mbsrtowcs(dst, &src, len, NULL); ^ ``` #### 5: nuttx/libs/libc/stdlib/lib_wcstombs.c:38 ``` src/deps/nuttx/libs/libc/stdlib/lib_wcstombs.c:38:36: error: Null pointer dereference [nullPointer] return wcsrtombs(dst, &src, len, NULL); ``` #### 6: drivers/net/netdev_upperhalf.c:168 ``` src/deps/nuttx/drivers/net/netdev_upperhalf.c:168:42: warning: Either the condition 'dev' is redundant or there is possible null pointer dereference: dev. [nullPointerRedundantCheck] FAR struct netdev_upperhalf_s *upper = dev->d_private; ^ src/deps/nuttx/drivers/net/netdev_upperhalf.c:170:15: note: Assuming that condition 'dev' is not redundant DEBUGASSERT(dev && pkt); ^ src/deps/nuttx/drivers/net/netdev_upperhalf.c:168:42: note: Null pointer dereference FAR struct netdev_upperhalf_s *upper = dev->d_private; ^ ``` #### 7: sched/task/task_init.c:90 ``` src/deps/nuttx/sched/task/task_init.c:90:19: warning: Either the condition 'tcb' is redundant or there is possible null pointer dereference: tcb. [nullPointerRedundantCheck] uint8_t ttype = tcb->cmn.flags & TCB_FLAG_TTYPE_MASK; ^ src/deps/nuttx/sched/task/task_init.c:96:15: note: Assuming that condition 'tcb' is not redundant DEBUGASSERT(tcb && ttype != TCB_FLAG_TTYPE_PTHREAD); ^ ``` ## Signed integer overflow The [C standard]( https://www.gnu.org/software/autoconf/manual/autoconf-2.63/html_node/Integer-Overflow-Basics.html) treats _signed_ integer overflow as undefined behavior. #### 8: arch/arm/src/armv7-m/arm_fpuconfig.c:75 ``` src/deps/nuttx/arch/arm/src/armv7-m/arm_fpuconfig.c:75:15: error: Signed integer overflow for expression '1<<31'. [integerOverflow] regval &= ~(NVIC_FPCCR_ASPEN | NVIC_FPCCR_LSPEN); ``` #### 9: arch/arm/src/armv7-m/arm_hardfault.c:169 ``` src/deps/nuttx/arch/arm/src/armv7-m/arm_hardfault.c:169:19: error: Signed integer overflow for expression '1<<31'. [integerOverflow] else if (hfsr & NVIC_HFAULTS_DEBUGEVT) ``` ## Buffer Overflow #### 10: nuttx/tools/mkdeps.c:795 ``` src/deps/nuttx/tools/mkdeps.c:795:12: warning: Either the condition 'cmdlen>=10240' is redundant or the array 'g_command[10240]' is accessed at index 10240, which is out of bounds. [arrayIndexOutOfBoundsCond] g_command[cmdlen] = '\0'; ^ src/deps/nuttx/tools/mkdeps.c:781:18: note: Assuming that condition 'cmdlen>=10240' is not redundant if (cmdlen >= MAX_BUFFER) ^ src/deps/nuttx/tools/mkdeps.c:794:3: note: cmdlen is incremented', new value is 10240 cmdlen++; ^ src/deps/nuttx/tools/mkdeps.c:795:12: note: Array index out of bounds g_command[cmdlen] = '\0'; ^ ``` ## Uninitialized Variable #### 11: src/deps/nuttx/tools/mkdeps.c:138 ``` src/deps/nuttx/tools/mkdeps.c:138:23: warning: Uninitialized variable: *saveptr [uninitvar] else if (saveptr && *saveptr) ^ src/deps/nuttx/tools/mkdeps.c:962:39: note: Calling function 'my_strtok_r', 3rd argument '&lasts' value is <Uninit> while ((file = strtok_r(files, " ", &lasts)) != NULL) ^ src/deps/nuttx/tools/mkdeps.c:138:23: note: Uninitialized variable: *saveptr else if (saveptr && *saveptr) ^ ``` ## Background I needed a way to create a [compile_commands.json]( https://cmake.org/cmake/help/latest/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html) from `make`, so I installed [bear](https://github.com/rizsotto/Bear) from my ubuntu package manager. I cloned `cppcheck` from its [github repo]( https://github.com/danmar/cppcheck) and built it by following the [cmake instructions](https://github.com/danmar/cppcheck#cmake). Next, I ran `make clean` followed by `bear make` on my project, which generated the `compile_commands.json`. Then, I ran: ``` >>> /path/to/build/bin/cppcheck --version Cppcheck 2.13 dev >>> /path/to/build/bin/cppcheck --project=/path/to/compile_commands.json -j8 --std=c++11 --std=c89 --quiet --enable=warning ``` -- *Daniel Appiagyei | Embedded Software Engineer*