AI review of 2026-10-10_20-28-58-72fa07506cc7-results.txt PR: #8856 https://github.com/cppcheck-opensource/cppcheck/pull/8856 Tested: 72fa07506cc7c027a0ba9fbda37f5ff309cee70c Merge base: 275f16a5223230cdcadf3f3f92bf9716138ac4fc Reviewed: 2026-10-11 17:38:40 UTC Model: claude-opus-5-5 (effort high) Results: 50 reviewed of 145 in the report (random sample), 2 not reviewed: valueFlowMaxIterations Verdicts: 20 improvement, 29 regression, 1 unclear Tokens: 155778 input, 100360 cache read, 25090 cache write, 35713 output The verdicts are written by AI and can be wrong. ---- 1 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/a/avce00/avce00_2.0.0.orig.tar.gz Result: your avce00-2.0.0/avc_binwr.c:1217:15: style: Condition 'inumVerticesLine) - 1)`. `numVerticesLine` is an unknown struct member, so `numVertices` can be anywhere from 1 to 4 and the loop can run. Saying `idevice.mouse.tr_counter>=sizeof(mouse_delays)' is true blastem-0.6.3.4/io.c:629:77: note: Assignment 'delay_index=port->device.mouse.tr_counter>=sizeof(mouse_delays)?sizeof(mouse_delays)-1:port->device.mouse.tr_counter', assigned value is 31 blastem-0.6.3.4/io.c:630:66: note: Array index out of bounds Explanation: `mouse_delays` has 8 elements, and Cppcheck computes `sizeof(mouse_delays)` as 32, so each element is 4 bytes. The clamp `tr_counter >= sizeof(mouse_delays) ? sizeof(mouse_delays)-1 : tr_counter` therefore uses byte size instead of element count. When the condition is true, `delay_index` is 31, which is out of bounds for an 8-element array. Any `tr_counter` from 8 to 31 is also out of bounds. This is a real bug: the code should use `sizeof(mouse_delays)/sizeof(*mouse_delays)`. The PR now propagates values through the `?:` branches, which lets Cppcheck find this true positive. ---- 3 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/f/feedreader/feedreader_2.10.0.orig.tar.gz Result: your FeedReader-2.10.0/libraries/libnxml/nxml_parser.c:113:8: error: Array 'buf[2048]' accessed at index 2048, which is out of bounds. [arrayIndexOutOfBounds] FeedReader-2.10.0/libraries/libnxml/nxml_parser.c:111:24: note: Assuming condition 'k-(i+2)>sizeof(buf)' is true FeedReader-2.10.0/libraries/libnxml/nxml_parser.c:111:38: note: Assignment 'last=k-(i+2)>sizeof(buf)?sizeof(buf):k-(i+2)', assigned value is 2048 FeedReader-2.10.0/libraries/libnxml/nxml_parser.c:113:8: note: Array index out of bounds Explanation: Line 111 caps `last` at sizeof(buf) (2048) when `k-(i+2) > sizeof(buf)`. Line 113 then writes `buf[last] = 0`, which is `buf[2048]`, one past the end of the array. That is a real off-by-one overflow: the cap should be `sizeof(buf)-1`. The condition can be true, since `k` scans until ';' or `size`, and `size` can be large. The PR now propagates the value of the ternary in this case, so this true positive is newly found. ---- 4 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/f/fltk1.4/fltk1.4_1.4.4.orig.tar.gz Result: your fltk-1.4.4/fluid/Fl_Function_Type.cxx:100:22: warning: Either the condition 'a' is redundant or there is pointer arithmetic with NULL pointer. [nullPointerArithmeticRedundantCheck] fltk-1.4.4/fluid/Fl_Function_Type.cxx:1560:23: note: Assuming that condition 'a' is not redundant fltk-1.4.4/fluid/Fl_Function_Type.cxx:1560:24: note: Assuming condition 'a&&a[0]=='#'' is false fltk-1.4.4/fluid/Fl_Function_Type.cxx:1560:36: note: Calling function 'c_check', 1st argument 'a&&a[0]=='#'?a+1:a' value is 0 fltk-1.4.4/fluid/Fl_Function_Type.cxx:168:19: note: Calling function '_c_check', 1st argument 'c' value is 0 fltk-1.4.4/fluid/Fl_Function_Type.cxx:100:22: note: Null pointer addition Explanation: At line 1560 the code checks `a` for null (`a && a[0]=='#' ? a+1 : a`). That means `a` may be null. When `a` is null, the condition is false, so the ternary yields `a`, which is null. That null goes to c_check(), which calls _c_check() without a null check, and _c_check() does `*c++` at line 100. So the null value really does reach `c++` and the dereference. Either the `a` check is redundant or this is a real null pointer bug. This is the kind of value flow through `?:` that the PR enables, and the path is correct. The arithmetic warning overlaps with the deref warning on the same line, but it is still accurate. ---- 5 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/f/fltk1.4/fltk1.4_1.4.4.orig.tar.gz Result: your fltk-1.4.4/fluid/Fl_Function_Type.cxx:100:22: warning: Either the condition 'a' is redundant or there is possible null pointer dereference: c++. [nullPointerRedundantCheck] fltk-1.4.4/fluid/Fl_Function_Type.cxx:1560:23: note: Assuming that condition 'a' is not redundant fltk-1.4.4/fluid/Fl_Function_Type.cxx:1560:24: note: Assuming condition 'a&&a[0]=='#'' is false fltk-1.4.4/fluid/Fl_Function_Type.cxx:1560:36: note: Calling function 'c_check', 1st argument 'a&&a[0]=='#'?a+1:a' value is 0 fltk-1.4.4/fluid/Fl_Function_Type.cxx:168:19: note: Calling function '_c_check', 1st argument 'c' value is 0 fltk-1.4.4/fluid/Fl_Function_Type.cxx:100:22: note: Null pointer dereference Explanation: Line 1560 calls `c_check(a && a[0]=='#' ? a+1 : a)`. The `a &&` test means the author thinks `a` can be NULL. When `a` is NULL the ternary takes the false branch and yields `a`, which is NULL. That NULL is passed through c_check to `_c_check`, which dereferences it with `*c++` at line 100. So either the null check is redundant or there is a real null dereference, which is exactly what nullPointerRedundantCheck reports. The PR lets cppcheck carry the null value through the ternary, which is a correct inference. This is a new true positive. Line 1560 itself is not shown, so confidence is medium. ---- 6 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/g/gammaray/gammaray_3.4.1.orig.tar.gz Result: your surveytargetexpressionlexer.cpp:1487:2: warning: Possible null pointer dereference: b [nullPointer] surveytargetexpressionlexer.cpp:1376:17: note: Assuming condition 'yyg->yy_buffer_stack' is false surveytargetexpressionlexer.cpp:1376:17: note: Calling function 'yy_init_buffer', 1st argument 'yyg->yy_buffer_stack?yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]:NULL' value is 0 surveytargetexpressionlexer.cpp:1487:2: note: Null pointer dereference Explanation: Line 1376 is flex's yyrestart: `if (!YY_CURRENT_BUFFER) { yyensure_buffer_stack(); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(...); } yy_init_buffer(YY_CURRENT_BUFFER, ...)`. The `if` block guarantees that `yy_buffer_stack` is allocated and the current buffer is non-null before `yy_init_buffer` runs, and `yy_create_buffer` aborts on allocation failure. So the NULL branch of the `YY_CURRENT_BUFFER` ternary cannot be reached here. The PR removed the guard that stopped a conditional ternary value from propagating when the condition involves other variables. Cppcheck now passes a possible NULL into `yy_init_buffer` without seeing that `yyensure_buffer_stack` initialized the stack. This is a new false positive; the PR itself had to add a nullPointer suppression in its own test code. ---- 7 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/g/gammaray/gammaray_3.4.1.orig.tar.gz Result: your surveytargetexpressionlexer.cpp:1488:2: warning: Possible null pointer dereference: b [nullPointer] surveytargetexpressionlexer.cpp:1376:17: note: Assuming condition 'yyg->yy_buffer_stack' is false surveytargetexpressionlexer.cpp:1376:17: note: Calling function 'yy_init_buffer', 1st argument 'yyg->yy_buffer_stack?yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]:NULL' value is 0 surveytargetexpressionlexer.cpp:1488:2: note: Null pointer dereference Explanation: Line 1376 is flex's yyrestart(), which calls yy_init_buffer(YY_CURRENT_BUFFER, ...). Just before that call, a `!YY_CURRENT_BUFFER` check calls yyensure_buffer_stack() and yy_create_buffer() and stores the result as the current buffer. yy_create_buffer either returns a valid buffer or calls the noreturn YY_FATAL_ERROR. So yy_buffer_stack is non-null and the current buffer is non-null when yy_init_buffer runs. The PR now lets the `?:` condition value (NULL when yy_buffer_stack is false) reach the call, but it ignores that the preceding block allocated the stack. The new nullPointer warning is a false positive. ---- 8 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/g/giada/giada_1.6.0.orig.tar.gz Result: your monocasual-giada-f0c71ed/src/gui/elems/actionEditor/pianoRoll.cpp:243:38: warning: Possible null pointer dereference: a2 [nullPointer] monocasual-giada-f0c71ed/src/gui/elems/actionEditor/pianoRoll.cpp:238:43: note: Assuming condition 'a1->nextId.isValid()' is false monocasual-giada-f0c71ed/src/gui/elems/actionEditor/pianoRoll.cpp:238:46: note: Assignment 'a2=a1->nextId.isValid()?c::actionEditor::findAction(a1->nextId):nullptr', assigned value is 0 monocasual-giada-f0c71ed/src/gui/elems/actionEditor/pianoRoll.cpp:243:38: note: Null pointer dereference Explanation: Line 238 sets `a2 = a1->nextId.isValid() ? findAction(...) : nullptr`, so `a2` is explicitly null whenever `nextId` is invalid. The source comment even says "a2 might be null if orphaned". Line 243 then passes `*a2` to `getPianoItemW`, which binds a reference to a null pointer. That is undefined behavior, even though the callee tries to handle the orphan case through `a2.isValid()`. The PR makes Cppcheck infer the null value from the ternary, so this new warning is a true positive. ---- 9 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/g/giada/giada_1.6.0.orig.tar.gz Result: your monocasual-giada-f0c71ed/src/gui/elems/actionEditor/pianoRoll.cpp:245:45: warning: Possible null pointer dereference: a2 [nullPointer] monocasual-giada-f0c71ed/src/gui/elems/actionEditor/pianoRoll.cpp:238:43: note: Assuming condition 'a1->nextId.isValid()' is false monocasual-giada-f0c71ed/src/gui/elems/actionEditor/pianoRoll.cpp:238:46: note: Assignment 'a2=a1->nextId.isValid()?c::actionEditor::findAction(a1->nextId):nullptr', assigned value is 0 monocasual-giada-f0c71ed/src/gui/elems/actionEditor/pianoRoll.cpp:245:45: note: Null pointer dereference Explanation: On line 238, `a2` is explicitly set to `nullptr` when `a1->nextId.isValid()` is false, and the comment even says "a2 might be null if orphaned". Line 245 then does `*a2` to bind a reference for `gePianoItem`, so a null pointer is dereferenced. That is undefined behavior and a likely crash. The `a2.isValid()` check inside the callee cannot help, because the dereference has already happened. The PR now infers the null value through the `?:` result, so this is a real bug newly found. ---- 10 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/i/intel-graphics-compiler2/intel-graphics-compiler2_2.40.14.orig.tar.gz Result: your lex.yy.cpp:1763:3: warning: Possible null pointer dereference: b [nullPointer] lex.yy.cpp:1656:18: note: Assuming condition 'yyg->yy_buffer_stack' is false lex.yy.cpp:1656:18: note: Calling function 'yy_init_buffer', 1st argument 'yyg->yy_buffer_stack?yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]:NULL' value is 0 lex.yy.cpp:1763:3: note: Null pointer dereference Explanation: This is standard flex code: yyrestart() calls yy_init_buffer(YY_CURRENT_BUFFER, ...) at line 1656. Just before that, it checks `if (!YY_CURRENT_BUFFER)` and, if so, calls yyensure_buffer_stack() and yy_create_buffer(). So by the time yy_init_buffer runs, yy_buffer_stack is allocated and the current buffer is non-null. Cppcheck instead assumes the ternary condition `yyg->yy_buffer_stack` is false and passes NULL into yy_init_buffer, which dereferences b. That path is infeasible. The PR removed the guard in setTokenValue that stopped conditional values from spreading out of a ?: operator. That lets the NULL branch of the YY_CURRENT_BUFFER macro escape as a possible value, so this new nullPointer warning is a false positive. ---- 11 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/i/intel-graphics-compiler2/intel-graphics-compiler2_2.40.14.orig.tar.gz Result: your lex.yy.cpp:1764:3: warning: Possible null pointer dereference: b [nullPointer] lex.yy.cpp:1656:18: note: Assuming condition 'yyg->yy_buffer_stack' is false lex.yy.cpp:1656:18: note: Calling function 'yy_init_buffer', 1st argument 'yyg->yy_buffer_stack?yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]:NULL' value is 0 lex.yy.cpp:1764:3: note: Null pointer dereference Explanation: This is flex-generated code. At line 1656 (yyrestart), `yy_init_buffer(YY_CURRENT_BUFFER, ...)` is called right after `if (!YY_CURRENT_BUFFER) { yyensure_buffer_stack(); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(...); }`. So `yy_buffer_stack` is always allocated and the current buffer is non-null at that call; allocation failures call yy_fatal_error. The ternary's NULL branch cannot be reached there. The PR removed the safeguard that blocked conditional values from multi-variable conditions. Cppcheck now passes the NULL arm of the `?:` into yy_init_buffer and reports a dereference of `b`. The displayed source lines don't line up with the reported line numbers, but the note trace points to a false positive. ---- 12 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/libd/libdrm/libdrm_2.4.134.orig.tar.xz Result: your libdrm-2.4.134/tests/util/pattern.c:2035:33: error: Signed integer overflow for expression '0xfffff<yy_buffer_stack' is false lexer.c:2112:18: note: Calling function 'mimetypes_yy_init_buffer', 1st argument 'yyg->yy_buffer_stack?yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]:NULL' value is 0 lexer.c:2254:2: note: Null pointer dereference Explanation: Line 2112 is flex's yyrestart(). It calls yy_init_buffer(YY_CURRENT_BUFFER, ...), where YY_CURRENT_BUFFER expands to 'yy_buffer_stack ? yy_buffer_stack[top] : NULL'. Just before that call, flex runs `if (!YY_CURRENT_BUFFER) { yyensure_buffer_stack(); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(...); }`. So the stack and the current buffer are guaranteed to be non-NULL at the call; yy_create_buffer reports a fatal error on allocation failure. The PR removed the check that stopped conditional values from propagating through '?:'. Cppcheck now assigns the NULL branch as a possible value of the argument, ignoring the preceding guard. This is a new false positive in common generated flex code. ---- 14 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/m/mailutils/mailutils_3.21.orig.tar.xz Result: your lexer.c:2258:2: warning: Possible null pointer dereference: b [nullPointer] lexer.c:2112:18: note: Assuming condition 'yyg->yy_buffer_stack' is false lexer.c:2112:18: note: Calling function 'mimetypes_yy_init_buffer', 1st argument 'yyg->yy_buffer_stack?yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]:NULL' value is 0 lexer.c:2258:2: note: Null pointer dereference Explanation: This is flex-generated code. Line 2112 is in yyrestart, which calls `yy_init_buffer(YY_CURRENT_BUFFER, ...)`. Here `YY_CURRENT_BUFFER` expands to `yyg->yy_buffer_stack ? yyg->yy_buffer_stack[top] : NULL`. Just before that call, `if (!YY_CURRENT_BUFFER) { yyensure_buffer_stack(); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(...); }` guarantees the buffer stack exists and the current buffer is non-null. Allocation failures go to YY_FATAL_ERROR instead. So the NULL branch of the ternary cannot reach yy_init_buffer, and the warning is a false positive. The PR removed the check in vf_settokenvalue that stopped conditional values from being created when the condition depends on several variables or function calls. That lets the ternary's NULL value leak through here, so this new warning is a false positive. ---- 15 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/m/multicat/multicat_2.4.orig.tar.bz2 Result: main multicat-2.4/multicat.c:1125:30: error: If memory allocation fails: pointer addition with NULL pointer. [nullPointerArithmeticOutOfMemory] multicat-2.4/multicat.c:1123:22: note: Assuming allocation function fails multicat-2.4/multicat.c:1123:22: note: Assignment 'p_buffer=malloc((i_max_read_size>i_max_write_size)?i_max_read_size:i_max_write_size)', assigned value is 0 multicat-2.4/multicat.c:1125:30: note: Null pointer addition Explanation: The code calls malloc at line 1123 and never checks the result. It then computes `p_buffer + (cond ? RTP_HEADER_SIZE : 0)`. If the allocation fails and the condition is true, this adds 12 to a NULL pointer, which is undefined behaviour. The pointer is later passed to pf_Read. So the out-of-memory warning was a true positive. The PR makes the ternary carry possible values such as 0, and that apparently suppresses the null-pointer-arithmetic check. Nothing in the code changed to make the warning wrong, so losing it is a lost true positive. ---- 16 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/o/osra/osra_2.2.4.orig.tar.gz Result: your osra-2.2.4/src/CImg.h:17967:25: warning: Expression 'nx0=nx1`, the `-1` really is converted to unsigned and multiplied in unsigned arithmetic. The code only works because the result wraps back when stored in `const int offx`. That is exactly the pattern signConversion is meant to flag. Before the PR, the ternary got no value because of the 'only one variable' bailout. Now it correctly carries the possible value -1. The new warning is a valid true positive, though harmless in practice. ---- 17 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/o/osra/osra_2.2.4.orig.tar.gz Result: your osra-2.2.4/src/CImg.h:18268:24: warning: Expression 'nx0=nx1`, the int `-1` is converted to unsigned before the multiplication, which is exactly what signConversion reports. The PR now gives the `?:` expression its possible values (1 and -1), so Cppcheck finds this real negative-to-unsigned conversion. The code only works because the wrapped result is converted back to `int offx`, which relies on modular arithmetic and implementation-defined conversion. That makes the warning accurate rather than a false positive, though in practice it may not be a functional bug. ---- 18 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/o/osra/osra_2.2.4.orig.tar.gz Result: your osra-2.2.4/src/CImg.h:18434:24: warning: Expression 'nx0=nx1`, -1 becomes UINT_MAX and is multiplied in unsigned arithmetic. Code that relies on wrap-around when converting back to `int` is exactly what signConversion is meant to flag. The PR removes the bailout for conditions that depend on more than one variable, so the ternary now gets its possible value -1. The new warning is a correct, newly found issue. ---- 19 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/p/py-tree-sitter/py-tree-sitter_0.25.1+repack.orig.tar.xz Result: your py-tree-sitter-0.25.1/tree_sitter/core/lib/src/subtree.c:264:24: warning: Possible null pointer dereference: old_children [nullPointer] py-tree-sitter-0.25.1/tree_sitter/core/lib/src/subtree.c:263:27: note: Assuming condition '(self).data.is_inline' is true py-tree-sitter-0.25.1/tree_sitter/core/lib/src/subtree.c:263:27: note: Assignment 'old_children=(self).data.is_inline?NULL:(union Subtree*)(self.ptr)-(self).ptr->child_count', assigned value is 0 py-tree-sitter-0.25.1/tree_sitter/core/lib/src/subtree.c:264:24: note: Null pointer dereference Explanation: `ts_subtree_children(self)` expands to `self.data.is_inline ? NULL : (Subtree*)self.ptr - child_count`. `ts_subtree_clone` is only meant for heap (non-inline) subtrees. Its caller `ts_subtree_make_mut` returns early when `is_inline` is set, and line 261 already uses `self.ptr->child_count`, which only makes sense for a heap subtree. So the NULL branch of the macro cannot be taken at the `memcpy`. The PR removed the check that suppressed conditional values from ternaries depending on more than one variable or on a member, so Cppcheck now passes the NULL arm into the `memcpy` argument. This is a new false positive. ---- 20 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/p/py-tree-sitter/py-tree-sitter_0.25.1+repack.orig.tar.xz Result: your py-tree-sitter-0.25.1/tree_sitter/core/lib/src/subtree.c:579:25: warning: Possible null pointer dereference: children [nullPointer] py-tree-sitter-0.25.1/tree_sitter/core/lib/src/subtree.c:577:27: note: Assuming condition '(tree).data.is_inline' is true py-tree-sitter-0.25.1/tree_sitter/core/lib/src/subtree.c:577:27: note: Assignment 'children=(tree).data.is_inline?NULL:(union Subtree*)(tree.ptr)-(tree).ptr->child_count', assigned value is 0 py-tree-sitter-0.25.1/tree_sitter/core/lib/src/subtree.c:579:25: note: Null pointer dereference Explanation: `ts_subtree_children(tree)` expands to `tree.data.is_inline ? NULL : (Subtree*)tree.ptr - child_count`. Here `tree` is popped from `pool->tree_stack`, which only ever receives non-inline subtrees (inline ones are skipped by the early return and the `continue`). The code also dereferences `tree.ptr->child_count` just before, which would be invalid for an inline subtree. So the NULL branch of the ternary is unreachable here. The new nullPointer warning comes from the PR removing the check that suppressed conditional values from ternaries. It is a false positive. ---- 21 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/p/pytorch/pytorch_2.12.1+dfsg.orig.tar.xz Result: your pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:117:3: error: Null pointer dereference: consumer [ctunullpointer] pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:297:7: note: Assuming condition '!initial_fusion_groups.empty()' is false pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:297:38: note: Assignment 'prev_fusion_group=!initial_fusion_groups.empty()?initial_fusion_groups[0]:nullptr', assigned value is 0 pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:299:34: note: Assuming container is not empty pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:310:21: note: Calling function tryMerge, 1st argument is null pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:172:8: note: Calling function canMerge, 1st argument is null pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:117:3: note: Dereferencing argument consumer that is null Explanation: `prev_fusion_group` is null only when `initial_fusion_groups` is empty. The loop at line 299 iterates `c10::irange(1, initial_fusion_groups.size())`, so its body (including the `tryMerge`/`canMerge` call) runs only when the vector has at least two elements. In that case `prev_fusion_group` is `initial_fusion_groups[0]`, which is non-null. The trace combines the contradictory assumptions 'container is empty' and 'container is not empty', so this is a new false positive. It appears because the PR removed the check that kept the ternary's null value from propagating. ---- 22 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/p/pytorch/pytorch_2.12.1+dfsg.orig.tar.xz Result: your pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:117:3: warning: Possible null pointer dereference: consumer [nullPointer] pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:297:7: note: Assuming condition '!initial_fusion_groups.empty()' is false pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:297:38: note: Assignment 'prev_fusion_group=!initial_fusion_groups.empty()?initial_fusion_groups[0]:nullptr', assigned value is 0 pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:299:34: note: Assuming container is not empty pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:310:22: note: Calling function 'tryMerge', 1st argument 'prev_fusion_group' value is 0 pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:172:17: note: Calling function 'canMerge', 1st argument 'fusion_group' value is 0 pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:117:3: note: Null pointer dereference Explanation: `prev_fusion_group` is set to null only when `initial_fusion_groups` is empty. The loop at line 299 runs over indices 1..size(), so it never executes in that case, and `tryMerge(prev_fusion_group, ...)` is never called with null. The trace contradicts itself: it assumes the container is empty at line 297 and not empty at line 299. The PR now lets values flow through the `?:` branches without the old single-variable check, which produces this new false positive. ---- 23 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/p/pytorch/pytorch_2.12.1+dfsg.orig.tar.xz Result: your pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:162:21: error: Null pointer dereference: n [ctunullpointer] pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:297:7: note: Assuming condition '!initial_fusion_groups.empty()' is false pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:297:38: note: Assignment 'prev_fusion_group=!initial_fusion_groups.empty()?initial_fusion_groups[0]:nullptr', assigned value is 0 pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:299:34: note: Assuming container is not empty pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:307:25: note: Calling function debugDumpFusionGroup, 2nd argument is null pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:162:21: note: Dereferencing argument n that is null Explanation: `prev_fusion_group` is null only when `initial_fusion_groups` is empty. The loop at line 299 iterates `i` from 1 to `initial_fusion_groups.size()`, so it runs only when the container has at least 2 elements. In that case `prev_fusion_group` was set to `initial_fusion_groups[0]` and is non-null. The trace itself is contradictory: it assumes the container is empty (line 297) and then assumes it is not empty (line 299). The PR now gives the ternary a conditional possible null value that leaks into the loop, so this new ctunullpointer warning is a false positive. ---- 24 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/p/pytorch/pytorch_2.12.1+dfsg.orig.tar.xz Result: your pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:162:21: warning:inconclusive: Possible null pointer dereference: n [nullPointer] pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:297:7: note: Assuming condition '!initial_fusion_groups.empty()' is false pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:297:38: note: Assignment 'prev_fusion_group=!initial_fusion_groups.empty()?initial_fusion_groups[0]:nullptr', assigned value is 0 pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:299:34: note: Assuming container is not empty pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:308:61: note: Calling function 'debugDumpFusionGroup', 2nd argument 'prev_fusion_group' value is 0 pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:162:21: note: Null pointer dereference Explanation: `prev_fusion_group` is null only when `initial_fusion_groups` is empty. The loop at line 299 iterates `c10::irange(1, initial_fusion_groups.size())`, so its body (which calls `debugDumpFusionGroup(..., prev_fusion_group)`) only runs when the vector has at least two elements. At that point `prev_fusion_group` is `initial_fusion_groups[0]`, which is non-null. The trace's own notes contradict each other: it assumes the vector is empty, then assumes it is not empty. The PR's change to the `?:` handling makes the nullptr branch value flow here without this correlation being tracked, so this is a new false positive. ---- 25 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/p/pytorch/pytorch_2.12.1+dfsg.orig.tar.xz Result: your pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:163:7: warning:inconclusive: Possible null pointer dereference: n [nullPointer] pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:297:7: note: Assuming condition '!initial_fusion_groups.empty()' is false pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:297:38: note: Assignment 'prev_fusion_group=!initial_fusion_groups.empty()?initial_fusion_groups[0]:nullptr', assigned value is 0 pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:299:34: note: Assuming container is not empty pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:308:61: note: Calling function 'debugDumpFusionGroup', 2nd argument 'prev_fusion_group' value is 0 pytorch-v2.12.1/torch/csrc/jit/runtime/static/fusion.cpp:163:7: note: Null pointer dereference Explanation: `prev_fusion_group` is null only when `initial_fusion_groups` is empty. The loop that calls `debugDumpFusionGroup(..., prev_fusion_group)` iterates from 1 to `initial_fusion_groups.size()`. So it only runs when the container has at least two elements, and then `prev_fusion_group` is `initial_fusion_groups[0]`, which is non-null. The warning's own trace contradicts itself: it assumes the container is empty at line 297 and not empty at line 299. The PR now lets the possible 0 from the ternary propagate, which creates this new false positive. ---- 26 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/q/qzxing/qzxing_3.3.0+dfsg.orig.tar.xz Result: your qzxing-3.3.0/src/zxing/zxing/common/BitArray.cpp:89:23: error: Signed integer overflow for expression '2<firstInt' is true qzxing-3.3.0/src/zxing/zxing/common/BitArray.cpp:86:37: note: Assignment 'firstBit=i>firstInt?0:start&0x1F', assigned value is 0 qzxing-3.3.0/src/zxing/zxing/common/BitArray.cpp:89:35: note: Integer overflow Explanation: When `i` is strictly between `firstInt` and `lastInt`, which happens whenever the range spans three or more ints, `lastBit` is 31 and `firstBit` is 0. So `(2 << 31) - (1 << 0)` is evaluated on signed ints. `2 << 31` overflows a 32-bit int, which is undefined behaviour before C++20. This is a known bug from porting Java ZXing, where the shift simply wraps. The PR now passes values through the `?:` condition, so Cppcheck sees this real path. The warning on the subtraction largely repeats the overflow of the shift. Still, the whole expression does contain undefined behaviour, and its mathematical value (2^32-1) does not fit in an int. It points at a real defect, so it is a true positive. ---- 29 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/r/raptor2/raptor2_2.0.16.orig.tar.gz Result: your turtle_lexer.c:2381:2: warning: Possible null pointer dereference: b [nullPointer] turtle_lexer.c:2270:18: note: Assuming condition 'yyg->yy_buffer_stack' is false turtle_lexer.c:2270:18: note: Calling function 'turtle_lexer__init_buffer', 1st argument 'yyg->yy_buffer_stack?yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]:NULL' value is 0 turtle_lexer.c:2381:2: note: Null pointer dereference Explanation: Line 2270 is flex's yyrestart: `yy_init_buffer(YY_CURRENT_BUFFER, ...)`, where YY_CURRENT_BUFFER expands to `yy_buffer_stack ? yy_buffer_stack[top] : NULL`. Just before that call, `if (!YY_CURRENT_BUFFER)` runs yyensure_buffer_stack() and yy_create_buffer(). Those calls allocate the stack and store a buffer in the current slot, so the argument cannot be NULL at the call. Cppcheck does not see that the guarded block changes yyg->yy_buffer_stack through yyscanner. The PR removed the 'condition depends on only one variable' restriction for ternary values, so the NULL branch now propagates. This new nullPointer warning is a false positive. ---- 30 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/r/raptor2/raptor2_2.0.16.orig.tar.gz Result: your turtle_lexer.c:2382:2: warning: Possible null pointer dereference: b [nullPointer] turtle_lexer.c:2270:18: note: Assuming condition 'yyg->yy_buffer_stack' is false turtle_lexer.c:2270:18: note: Calling function 'turtle_lexer__init_buffer', 1st argument 'yyg->yy_buffer_stack?yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]:NULL' value is 0 turtle_lexer.c:2382:2: note: Null pointer dereference Explanation: Line 2270 is flex's yyrestart calling yy_init_buffer(YY_CURRENT_BUFFER, ...), where YY_CURRENT_BUFFER expands to `yy_buffer_stack ? yy_buffer_stack[top] : NULL`. Just before that call, yyrestart checks `if (!YY_CURRENT_BUFFER)`; in that case it calls yyensure_buffer_stack and assigns a newly created buffer, and yy_create_buffer fails fatally on allocation error. So the argument is never NULL when it reaches yy_init_buffer. The PR now propagates the NULL branch of the ternary as a possible value even though the condition depends on more than one variable. That produces this new false-positive nullPointer warning in generated flex code. ---- 31 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/r/rasmol/rasmol_2.7.6.0.orig.tar.gz Result: your rasmol-2.7.6.0/src/pixutils.c:3115:15: warning: Either the condition 'lx>0' is redundant or there is division by zero at line 3115. [zerodivcond] rasmol-2.7.6.0/src/pixutils.c:3113:11: note: Assuming that condition 'lx>0' is not redundant rasmol-2.7.6.0/src/pixutils.c:3114:17: note: Assignment 'ax=-lx', assigned value is 0 rasmol-2.7.6.0/src/pixutils.c:3113:11: note: Assuming condition is false rasmol-2.7.6.0/src/pixutils.c:3115:16: note: Assuming condition '(ax)>(ay)' is true rasmol-2.7.6.0/src/pixutils.c:3115:15: note: Division by zero Explanation: `MaxFun(ax,ay)` is a max macro, roughly `((ax)>(ay)?(ax):(ay))`. When `lx==0`, `ax` is 0, and the condition `ax>ay` cannot be true because `ay=|ly|>=0`. So the ternary returns `ay`, not `ax`. Also, the early return at line 3091 handles `x1==x2 && y1==y2`, so when `ax==0`, `ay` is nonzero. The divisor `max(ax,ay)` therefore can never be zero. The warning comes from the PR removing the single-variable check in conditional value propagation through `?`. That lets the value `ax=0` flow through a branch whose condition (`0>ay`) is infeasible. This is a new false positive. ---- 32 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/r/rasmol/rasmol_2.7.6.0.orig.tar.gz Result: your rasmol-2.7.6.0/src/pixutils.c:3391:15: warning: Either the condition 'lx>0' is redundant or there is division by zero at line 3391. [zerodivcond] rasmol-2.7.6.0/src/pixutils.c:3389:11: note: Assuming that condition 'lx>0' is not redundant rasmol-2.7.6.0/src/pixutils.c:3390:17: note: Assignment 'ax=-lx', assigned value is 0 rasmol-2.7.6.0/src/pixutils.c:3389:11: note: Assuming condition is false rasmol-2.7.6.0/src/pixutils.c:3391:16: note: Assuming condition '(ax)>(ay)' is true rasmol-2.7.6.0/src/pixutils.c:3391:15: note: Division by zero Explanation: `MaxFun(ax,ay)` is a max macro (`(ax)>(ay)?(ax):(ay)`). For the divisor to be 0, `ax` would have to be 0 while `ax>ay` holds. That needs `ay<0`, which is impossible because `ay` is the absolute value of `ly`. In addition, the early return when `x1==x2 && y1==y2` guarantees that at least one of `ax`/`ay` is positive, so the max is never 0. The PR removed the guard that stopped value propagation through `?:` when the condition depends on more than one variable. Cppcheck now carries `ax`=0 through the ternary even though the condition also involves `ay`. The new zerodivcond warning is a false positive. ---- 33 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/s/snpomatic/snpomatic_1.0.orig.tar.gz Result: your snpomatic-1.0/src/TChromosomeAlign.cpp:407:19: warning: Expression '(int)(pa.reverse_complement?-1:1)' can have a negative value. That is converted to an unsigned value and used in an unsigned calculation. [signConversion] snpomatic-1.0/src/TChromosomeAlign.cpp:407:29: note: Assuming condition 'pa.reverse_complement' is true snpomatic-1.0/src/TChromosomeAlign.cpp:407:19: note: Negative value is converted to an unsigned value Explanation: In `(int)(pa.reverse_complement ? -1 : 1) * seq1.length()`, the int result of the ternary is multiplied by a `size_t`. When `reverse_complement` is true, -1 is converted to a huge unsigned value. The result only happens to work through modular wraparound when it is added to `position`. This is exactly what signConversion is meant to catch. Before the PR, the ternary got no values because the removed 'condition depends on one variable' bailout rejected `pa.reverse_complement`. Now the possible values -1 and 1 propagate and the real issue is reported. The code sits after a `return` and is unreachable, which makes it less important, but the warning is technically correct. ---- 34 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/s/snpomatic/snpomatic_1.0.orig.tar.gz Result: your snpomatic-1.0/src/TChromosomeAlign.cpp:408:19: warning: Expression '(int)(pb.reverse_complement?-1:1)' can have a negative value. That is converted to an unsigned value and used in an unsigned calculation. [signConversion] snpomatic-1.0/src/TChromosomeAlign.cpp:408:29: note: Assuming condition 'pb.reverse_complement' is true snpomatic-1.0/src/TChromosomeAlign.cpp:408:19: note: Negative value is converted to an unsigned value Explanation: In `(int)(pb.reverse_complement ? -1 : 1) * seq2.length()`, the int operand is multiplied by `size_t`. When the condition is true, -1 is converted to a huge unsigned value. That is exactly what signConversion is meant to report. The PR now lets the ternary's possible values (-1, 1) through even though the condition reads a member variable, which the removed restriction used to block, so Cppcheck finds this real issue. The wrapped arithmetic may happen to give the intended result after truncation. The code also sits after a `return` and is unreachable. Even so, the pattern is a genuine signed-to-unsigned conversion, so the new warning is a valid true positive. ---- 35 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/s/spirv-llvm-translator-22/spirv-llvm-translator-22_22.1.0.orig.tar.gz Result: your SPIRV-LLVM-Translator-22.1.0/lib/SPIRV/LLVMToSPIRVDbgTran.cpp:1348:34: warning: Possible null pointer dereference: BB [nullPointer] SPIRV-LLVM-Translator-22.1.0/lib/SPIRV/LLVMToSPIRVDbgTran.cpp:1344:44: note: Assuming condition 'F->getNumBasicBlock()' is false SPIRV-LLVM-Translator-22.1.0/lib/SPIRV/LLVMToSPIRVDbgTran.cpp:1344:47: note: Assignment 'BB=F->getNumBasicBlock()?F->getBasicBlock(0):nullptr', assigned value is 0 SPIRV-LLVM-Translator-22.1.0/lib/SPIRV/LLVMToSPIRVDbgTran.cpp:1348:34: note: Null pointer dereference Explanation: Line 1344 sets `BB` to `nullptr` when `F->getNumBasicBlock()` is 0. Line 1348 then calls `BB->getInst(0)` with no check, so for a function with no basic blocks this dereferences a null pointer. The author explicitly coded the null case, so the warning points at a real inconsistency rather than inventing an impossible path. Previously Cppcheck did not pass the ternary's value through because of the 'function call in condition' bailout, which this PR removed. Reporting it now is a true positive. ---- 36 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/s/suckless-tools/suckless-tools_49.orig.tar.xz Result: your suckless-tools-49/dmenu/stest.c:73:30: warning: Possible null pointer dereference: file [nullPointer] suckless-tools-49/dmenu/stest.c:72:10: note: Assuming condition 'argv[0][1]=='\0'&&argv[1]==NULL' is true suckless-tools-49/dmenu/stest.c:72:10: note: Assignment 'file=(argv[0][1]=='\0'&&argv[1]==NULL)?(usage(),abort(),(char*)0):(brk_=1,(argv[0][1]!='\0')?(&argv[0][1]):(argc--,argv++,argv[0]))', assigned value is 0 suckless-tools-49/dmenu/stest.c:73:30: note: Null pointer dereference Explanation: EARGF expands to `(cond) ? (usage(), abort(), (char*)0) : ...`. In the branch that yields NULL, usage() calls exit() and abort() is noreturn, so `file` can never be NULL when it reaches stat() and perror(). The PR removed the check in vf_settokenvalue that skipped propagating ternary branch values when the condition depends on several variables or function calls. Now the (char*)0 from the noreturn branch flows into `file`, producing a new false-positive nullPointer warning. ---- 37 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/t/telegram-desktop/telegram-desktop_5.7.2+ds.orig.tar.xz Result: your tdesktop-5.7.2-full/Telegram/SourceFiles/boxes/sticker_set_box.cpp:599:8: portability: Undefined behaviour, pointer arithmetic 'part+'/'' is out of bounds. [pointerOutOfBounds] Explanation: `u"addemoji"_q` is a QString user-defined literal, so the ternary yields a QString and `part + '/' + ...` is QString concatenation, not pointer arithmetic. Cppcheck appears to treat `part` as the `const char*` from "addstickers" and `'/'` (47) as an offset past the 12-byte literal. The PR's new ternary value propagation produced this, so the added pointerOutOfBounds is a false positive. ---- 38 / 50 ---- Verdict: UNCLEAR (low confidence) Package: https://ftp.debian.org/debian/pool/main/t/tgl/tgl_2.0.1+git20160323.ffb04cac.orig.tar.xz Result: your tgl/mtproto-common.c:227:17: error: Null pointer dereference: str [ctunullpointer] tgl/queries.c:3431:16: note: Assuming condition 'DS_EA->bytes' is false tgl/queries.c:3431:15: note: Calling function tgl_out_cstring, 1st argument is null tgl/mtproto-common.c:227:17: note: Dereferencing argument str that is null Explanation: The PR removed the bailout that kept ternaries whose condition uses more than one variable (such as `DS_EA->bytes ? ...->data : NULL`) from passing a possible null to the ternary result. Cppcheck now reports a null `str` reaching `memcpy(dest, str, len)` in `tgl_out_cstring`. The call site at queries.c:3431 is not shown. In tgl it is most likely a DS_STR-style macro that also passes `len = 0` when `bytes` is NULL. In that case the code only does `memcpy(dest, NULL, 0)`. That is technically undefined behaviour before C2y but harmless in practice, and most users would see it as noise. If `len` is not tied to the same condition, it would be a real bug. Without the call site the verdict cannot be settled. ---- 39 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/t/tgl/tgl_2.0.1+git20160323.ffb04cac.orig.tar.xz Result: your tgl/structures.c:400:34: warning: Possible null pointer dereference: src [nullPointer] tgl/structures.c:1437:25: note: Assuming condition 'DS_DMA->g_a' is false tgl/structures.c:1437:25: note: Calling function 'str_to_256', 2nd argument '(DS_DMA->g_a)?(DS_DMA->g_a)->data:NULL' value is 0 tgl/structures.c:400:34: note: Null pointer dereference Explanation: At line 1437 the caller almost certainly passes DS_STR(DS_DMA->g_a), which expands to `(g_a ? g_a->data : NULL), (g_a ? g_a->len : 0)`. So src is NULL only when src_len is 0, and line 400 then becomes memcpy(dst+256, NULL, 0), which copies nothing. Cppcheck does not link the two ternaries. The PR removed the check that stopped conditional values from spreading through conditions involving more than one variable. That now lets the NULL branch of the ternary reach str_to_256 on its own, without the matching length of 0. NULL with length 0 is technically undefined behaviour before C2y, but it is harmless in practice and the protocol field is normally present. Users would see this as a new false positive caused by less precise value tracking. ---- 40 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/t/tgl/tgl_2.0.1+git20160323.ffb04cac.orig.tar.xz Result: your tgl/structures.c:409:33: warning: Possible null pointer dereference: src [nullPointer] tgl/structures.c:1358:39: note: Assuming condition 'DS_DMM->key' is false tgl/structures.c:1358:39: note: Calling function 'str_to_32', 2nd argument '(DS_DMM->key)?(DS_DMM->key)->data:NULL' value is 0 tgl/structures.c:409:33: note: Null pointer dereference Explanation: At line 1358 the call is presumably `str_to_32(key, DS_STR(DS_DMM->key))`. The macro passes `(key ? key->data : NULL)` and `(key ? key->len : 0)`, so a NULL `src` always comes with `src_len == 0`. In that case `str_to_32` runs `memcpy(dst + 32, NULL, 0)`, which reads nothing. Cppcheck does not link the two arguments: it only sees a possible NULL `src` and ignores that the length is then 0. The new warning comes from the PR removing the guard that stopped conditional ternary values from propagating. Calling memcpy with NULL and size 0 is formally undefined in older C standards, but it is not a real null dereference. Users will see this as a noisy false positive. ---- 41 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/u/universal-ctags/universal-ctags_6.2.1.orig.tar.gz Result: your ctags-6.2.1/parsers/cxx/cxx_parser_using.c:109:6: warning: Possible null pointer dereference: t [nullPointer] ctags-6.2.1/parsers/cxx/cxx_parser_using.c:105:18: note: Assuming condition 'g_cxx.pTokenChain' is false ctags-6.2.1/parsers/cxx/cxx_parser_using.c:105:18: note: Assignment 't=g_cxx.pTokenChain?g_cxx.pTokenChain->pHead:NULL', assigned value is 0 ctags-6.2.1/parsers/cxx/cxx_parser_using.c:109:6: note: Null pointer dereference Explanation: `cxxTokenChainFirst()` is a macro that expands to `chain ? chain->pHead : NULL`. The null check is generic defensive code inside the macro; it does not mean `g_cxx.pTokenChain` can be null here. `g_cxx.pTokenChain` is the parser's global token chain and is always allocated while parsing. The code just before (the debug assert on `g_cxx.pTokenChain->iCount`) and just after (line 121, `g_cxx.pTokenChain->iCount`) also dereferences the chain directly. The PR stopped skipping ternary conditions in `setTokenValue`, so the null value from the macro's else-branch now reaches `t`. This is a new false positive. ---- 42 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/u/upse/upse_1.0.0.orig.tar.gz Result: your upse-1.0.0/src/libupse/upse_ps1_bios_base.c:273:2: warning: Possible null pointer dereference: jmp_buf [nullPointer] upse-1.0.0/src/libupse/upse_ps1_bios_base.c:266:28: note: Assuming condition 'upse_ps1_memory_LUT[upse_r3000_cpu_regs.GPR.n.a0>>16]==0' is true upse-1.0.0/src/libupse/upse_ps1_bios_base.c:266:20: note: Assignment 'jmp_buf=(u32*)((char*)(upse_ps1_memory_LUT[upse_r3000_cpu_regs.GPR.n.a0>>16]==0?NULL:(void*)(upse_ps1_memory_LUT[upse_r3000_cpu_regs.GPR.n.a0>>16]+(upse_r3000_cpu_regs.GPR.n.a0&0xffff))))', assigned value is 0 upse-1.0.0/src/libupse/upse_ps1_bios_base.c:273:2: note: Null pointer dereference Explanation: `Ra0` expands to `LUT[a0>>16]==0 ? NULL : LUT[...]+offset`, so the macro explicitly yields NULL when the guest address is unmapped. `bios_setjmp` then writes `jmp_buf[3+i]` without any NULL check. The address comes from emulated guest code, so NULL is a real possibility. Other functions in the same file (e.g. `bios_strcat`) do check for NULL, which shows the authors know this can happen. Before the PR, Cppcheck dropped the ternary's NULL value because the condition involved more than one variable; it now propagates it. The new warning is a genuine possible null dereference, although this many similar reports may feel noisy. ---- 43 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/u/upse/upse_1.0.0.orig.tar.gz Result: your upse-1.0.0/src/libupse/upse_ps1_executive.c:102:44: warning: Possible null pointer dereference: header [nullPointer] upse-1.0.0/src/libupse/upse_ps1_executive.c:96:85: note: Assuming condition 'upse_ps1_memory_LUT[upse_r3000_cpu_regs.GPR.n.s0>>16]==0' is true upse-1.0.0/src/libupse/upse_ps1_executive.c:96:48: note: Assignment 'header=(struct upse_ps1_executive_exec_record_t*)(upse_ps1_memory_LUT[upse_r3000_cpu_regs.GPR.n.s0>>16]==0?NULL:(void*)(upse_ps1_memory_LUT[upse_r3000_cpu_regs.GPR.n.s0>>16]+(upse_r3000_cpu_regs.GPR.n.s0&0xffff)))', assigned value is 0 upse-1.0.0/src/libupse/upse_ps1_executive.c:102:44: note: Null pointer dereference Explanation: PSXM(addr) expands to `LUT[addr>>16]==0 ? NULL : LUT[addr>>16]+(addr&0xffff)`, so the macro itself says the result can be NULL for unmapped emulated memory. `header` is set from PSXM(s0), and s0 is a guest-controlled emulated register. `header` is then dereferenced on lines 100-104 with no NULL check. A malformed PS1 program pointing s0 at unmapped memory would crash the emulator, so the null dereference is reachable. The old code skipped this case only because the condition used more than one variable. That was a heuristic, not proof that the NULL branch is impossible. The new warning is a plausible true positive, though it is noisy in this package. ---- 44 / 50 ---- Verdict: IMPROVEMENT (low confidence) Package: https://ftp.debian.org/debian/pool/main/u/upse/upse_1.0.0.orig.tar.gz Result: your upse-1.0.0/src/libupse/upse_ps1_executive.c:103:44: warning: Possible null pointer dereference: header [nullPointer] upse-1.0.0/src/libupse/upse_ps1_executive.c:96:85: note: Assuming condition 'upse_ps1_memory_LUT[upse_r3000_cpu_regs.GPR.n.s0>>16]==0' is true upse-1.0.0/src/libupse/upse_ps1_executive.c:96:48: note: Assignment 'header=(struct upse_ps1_executive_exec_record_t*)(upse_ps1_memory_LUT[upse_r3000_cpu_regs.GPR.n.s0>>16]==0?NULL:(void*)(upse_ps1_memory_LUT[upse_r3000_cpu_regs.GPR.n.s0>>16]+(upse_r3000_cpu_regs.GPR.n.s0&0xffff)))', assigned value is 0 upse-1.0.0/src/libupse/upse_ps1_executive.c:103:44: note: Null pointer dereference Explanation: PSXM(addr) expands to `LUT[addr>>16]==0 ? NULL : LUT[...] + offset`, so it explicitly yields NULL for unmapped memory. upse_ps1_executive_task_switch takes the address from the guest register s0 and dereferences `header` without any check. A guest program (e.g. a crafted PSF file) can set s0 to an unmapped address, so the crash is possible. Main used to drop the conditional NULL value because the ternary condition involves more than one variable; the PR removes that heuristic. The new warning therefore points at a real unchecked NULL path. Confidence is low: these macro-generated warnings are numerous in emulator code, and some users may see them as noise. ---- 45 / 50 ---- Verdict: IMPROVEMENT (low confidence) Package: https://ftp.debian.org/debian/pool/main/u/upse/upse_1.0.0.orig.tar.gz Result: your upse-1.0.0/src/libupse/upse_ps1_spu_dma_handler.c:65:26: warning: Possible null pointer dereference: (u16*)(upse_ps1_memory_LUT[(usPSXMem)>>16]==0?NULL:(void*)(upse_ps1_memory_LUT[(usPSXMem)>>16]+((usPSXMem)&0xffff))) [nullPointer] upse-1.0.0/src/libupse/upse_ps1_spu_dma_handler.c:65:34: note: Assuming condition 'upse_ps1_memory_LUT[(usPSXMem)>>16]==0' is true upse-1.0.0/src/libupse/upse_ps1_spu_dma_handler.c:65:26: note: Null pointer dereference Explanation: The PSXM(addr) macro expands to `LUT[addr>>16]==0 ? NULL : LUT[...]+offset`. Line 65 dereferences that result directly with no NULL guard. The NULL branch is explicit in the code, and addr comes from emulated DMA, so it is driven by the loaded PSF file and can hit an unmapped page. So a null dereference is genuinely possible and the warning is technically correct. Main suppressed it only because of the removed heuristic that skipped conditions involving more than one variable (here the LUT and usPSXMem). The new warning reflects real dataflow, not a misunderstanding of the code. However, it is one of many similar macro-driven warnings, and the authors may assume every address is mapped, so it may be seen as noise. ---- 46 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/x/xchpst/xchpst_0.8.6.orig.tar.xz Result: your xchpst-0.8.6/options.c:512:13: error: Null pointer dereference: path [ctunullpointer] xchpst-0.8.6/options.c:650:35: note: Assuming condition 'optdef->has_arg==no_argument' is true xchpst-0.8.6/options.c:649:18: note: Calling function handle_option, 3rd argument is null xchpst-0.8.6/options.c:686:5: note: Calling function read_options_file, 1st argument is null xchpst-0.8.6/options.c:512:13: note: Dereferencing argument path that is null Explanation: The new warning comes from a ternary at line 649/650. It most likely passes NULL as the option value when `optdef->has_arg == no_argument` and the real argument otherwise. `handle_option` then forwards that value to `read_options_file` (line 686), presumably for the options-file option. That option needs an argument to name the file, so it would not be defined with `no_argument`, and the NULL branch should never reach line 686. Cppcheck cannot connect the option kind to the NULL argument. The PR removed the check that stopped conditional values from flowing through `?:` when the condition depends on other variables. Now the NULL from the ternary reaches `open(path, ...)` on a path that cannot happen. This is most likely a new false positive. Lines 649–686 were not shown, which is why confidence is medium. ---- 47 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/x/xen/xen_4.20.3+127-gc42374a105.orig.tar.xz Result: your libxlu_cfg_l.c:1763:2: warning: Possible null pointer dereference: b [nullPointer] libxlu_cfg_l.c:1652:18: note: Assuming condition 'yyg->yy_buffer_stack' is false libxlu_cfg_l.c:1652:18: note: Calling function 'xlu__cfg_yy_init_buffer', 1st argument 'yyg->yy_buffer_stack?yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]:NULL' value is 0 libxlu_cfg_l.c:1763:2: note: Null pointer dereference Explanation: Line 1652 is flex's yyrestart: `yy_init_buffer(YY_CURRENT_BUFFER, ...)`, where YY_CURRENT_BUFFER expands to `yyg->yy_buffer_stack ? yyg->yy_buffer_stack[top] : NULL`. Just before that, the code checks `if (!YY_CURRENT_BUFFER)` and then calls yyensure_buffer_stack() and stores the result of yy_create_buffer() into the current slot. So yy_buffer_stack cannot be NULL at the call, and the NULL branch of the ternary is never passed to yy_init_buffer. The PR stopped dropping conditional ternary values when the condition depends on other variables. That lets the impossible NULL branch flow into the function, so the new nullPointer warning is a false positive in standard flex-generated code. ---- 48 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/x/xen/xen_4.20.3+127-gc42374a105.orig.tar.xz Result: your libxlu_cfg_l.c:1764:2: warning: Possible null pointer dereference: b [nullPointer] libxlu_cfg_l.c:1652:18: note: Assuming condition 'yyg->yy_buffer_stack' is false libxlu_cfg_l.c:1652:18: note: Calling function 'xlu__cfg_yy_init_buffer', 1st argument 'yyg->yy_buffer_stack?yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]:NULL' value is 0 libxlu_cfg_l.c:1764:2: note: Null pointer dereference Explanation: Line 1652 is the flex-generated `yyrestart()`, which calls `yy_init_buffer(YY_CURRENT_BUFFER, ...)`. Just before that call, `if (!YY_CURRENT_BUFFER)` runs `yyensure_buffer_stack()` and creates a buffer. So `yy_buffer_stack` is non-null at the call and the ternary cannot yield NULL; an allocation failure goes to a fatal error instead. Cppcheck now treats the ternary's NULL branch as a possible value of the whole expression without honoring the earlier guard. The PR removed the check in `setTokenValue` that skipped ternaries whose condition depends on more than one variable or on a function call. The new nullPointer warning is a false positive. ---- 49 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/x/xen/xen_4.20.3+127-gc42374a105.orig.tar.xz Result: your libxlu_disk_l.c:2431:2: warning: Possible null pointer dereference: b [nullPointer] libxlu_disk_l.c:2320:18: note: Assuming condition 'yyg->yy_buffer_stack' is false libxlu_disk_l.c:2320:18: note: Calling function 'xlu__disk_yy_init_buffer', 1st argument 'yyg->yy_buffer_stack?yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]:NULL' value is 0 libxlu_disk_l.c:2431:2: note: Null pointer dereference Explanation: This is flex-generated `yyrestart` code. If `YY_CURRENT_BUFFER` is NULL, the code first calls `yyensure_buffer_stack`, then assigns a newly created buffer to `YY_CURRENT_BUFFER_LVALUE`. Only after that does it call `yy_init_buffer(YY_CURRENT_BUFFER, ...)`, so `yy_buffer_stack` cannot still be NULL at the call. The PR now lets the ternary `yy_buffer_stack ? ... : NULL` take a possible 0 value even though the condition depends on member state that was changed before the call. The new nullPointer warning is a false positive. ---- 50 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/x/xen/xen_4.20.3+127-gc42374a105.orig.tar.xz Result: your libxlu_disk_l.c:2432:2: warning: Possible null pointer dereference: b [nullPointer] libxlu_disk_l.c:2320:18: note: Assuming condition 'yyg->yy_buffer_stack' is false libxlu_disk_l.c:2320:18: note: Calling function 'xlu__disk_yy_init_buffer', 1st argument 'yyg->yy_buffer_stack?yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]:NULL' value is 0 libxlu_disk_l.c:2432:2: note: Null pointer dereference Explanation: Line 2320 is flex's `yyrestart()`. It first checks `if (!YY_CURRENT_BUFFER)` and, in that case, calls `yyensure_buffer_stack()` and assigns a newly created buffer to `YY_CURRENT_BUFFER_LVALUE`. Only then does it call `yy_init_buffer(YY_CURRENT_BUFFER, ...)`. So the ternary `yyg->yy_buffer_stack ? ... : NULL` cannot yield NULL at that call. Allocation failure inside `yy_create_buffer` goes through `YY_FATAL_ERROR` rather than returning NULL. The PR now gives the `?:` expression a possible 0 value from its 'false' branch, which ignores the earlier initialization. This is a new false positive. The PR even had to add a nullPointer suppression to its own test code (ticket #9747), which shows the same kind of new false positive.