fix(coverity): DEADCODE, FORWARD_NULL, UNINIT #41667

Problem:

    CID 655469:           (DEADCODE)
    /build/src/nvim/auto/lua_api_c_bindings.generated.h: 7696             in nlua_api_nvim__mcursor_cascading()
    7690
    7691     exit_0:
    7692       arena_mem_free(arena_finish(&arena));
    7693       if (ERROR_SET(&err)) {
    7694         luaL_where(lstate, 1);
    7695         if (err_param) {
    >>>     CID 655469:           (DEADCODE)
    >>>     Execution cannot reach this statement: "lua_pushstring(lstate, "Inv...".
    7696           lua_pushstring(lstate, "Invalid '");
    7697           lua_pushstring(lstate, err_param);
    7698           lua_pushstring(lstate, "': ");
    7699         }
    7700         lua_pushstring(lstate, err.msg);
    7701         api_clear_error(&err);
    /build/src/nvim/auto/lua_api_c_bindings.generated.h: 7702             in nlua_api_nvim__mcursor_cascading()
    7696           lua_pushstring(lstate, "Invalid '");
    7697           lua_pushstring(lstate, err_param);
    7698           lua_pushstring(lstate, "': ");
    7699         }
    7700         lua_pushstring(lstate, err.msg);
    7701         api_clear_error(&err);
    >>>     CID 655469:           (DEADCODE)
    >>>     Execution cannot reach the expression "5" inside this statement: "lua_concat(lstate, (err_par...".
    7702         lua_concat(lstate, err_param ? 5 : 2);
    7703         return lua_error(lstate);
    7704       }
    7705
    7706       return 1;
    7707     }

    CID 655468:         Null pointer dereferences  (FORWARD_NULL)
    /src/nvim/mcursor.c: 833             in mc_ins_cascade()
    827           mc_ins_span_push(keys.items, NULL);
    828           mc_ins_preview_rebase();
    829         }
    830       } else if (ins.data != NULL && ins.size < mc_ins_span.done_len) {
    831         // Capture shrank without a restart signal, e.g. completion surgery rewrote the pending keys.
    832         mc_ins_cascade_restart();
    >>>     CID 655468:         Null pointer dereferences  (FORWARD_NULL)
    >>>     Passing null pointer "ins.data + mc_ins_span.done_len" to "mc_ins_keys_nonliteral", which dereferences it.
    833       } else if (ins.size > mc_ins_span.done_len
    834                  && mc_ins_keys_nonliteral(ins.data + mc_ins_span.done_len,
    835                                            ins.size - mc_ins_span.done_len)) {
    836         // Non-literal keys pending (BS, CTRL-U, ...): re-execute instead of previewing.
    837         mc_ins_span_flush(&ins, false);
    838       } else {

    CID 655467:         Uninitialized variables  (UNINIT)
    /src/nvim/mcursor.c: 1041             in mc_vsel_refresh()
    1035       for (size_t i = 0; i < kv_size(mc_cursors); i++) {
    1036         Context *ctx = &kv_A(mc_cursors, i);
    1037         pos_T pos;
    1038         if (!mc_ctx_resolve(ctx, &pos)) {
    1039           continue;
    1040         }
    >>>     CID 655467:         Uninitialized variables  (UNINIT)
    >>>     Using uninitialized value "pos". Field "pos.coladd" is uninitialized.
    1041         curwin->w_cursor = pos;
    1042         check_cursor(curwin);
    1044         Visual.select = false;
    1045         nvim_feedkeys(span, cstr_as_string("nix"), false);
    1046         if (!Visual.active) {

Solution:

- CID 655467 UNINIT: real (minor). `mc_vsel_refresh()` copied
  uninitialized local into `curwin->w_cursor`, and garbage coladd
  survived into the Visual replay (`equalpos()` compares it).
  - Fix: `pos_T pos = { 0 }`
- CID 655468 FORWARD_NULL: false positive
- CID 655469 DEADCODE: generated code. `nvim__mcursor_cascading`
  is flagged bc it is new,
- TODO: teach `gen_api_dispatch.lua` to omit the branch for
  parameterless functions.
This commit is contained in:
Justin M. Keyes
2026-09-03 12:41:40 -04:00
committed by GitHub
parent e1a28e52b2
commit ba0ee081c8

View File

@@ -694,7 +694,7 @@ static void mc_ins_preview_rebase(void)
mc_ins_regions_clear();
for (size_t i = 0; i < kv_size(mc_cursors); i++) {
Context *ctx = &kv_A(mc_cursors, i);
pos_T pos;
pos_T pos = { 0 };
uint32_t mark = 0;
if (mc_ctx_resolve(ctx, &pos)) {
mc_region_mark_set(&mark, pos);
@@ -822,6 +822,7 @@ void mc_ins_cascade(void)
return;
}
String ins = redo_keys(NULL);
assert(ins.data != NULL || ins.size == 0); // Coverity: NULL only when empty.
if (mc_ins_span.first) {
// Not with a pending autoindent ("o" + 'autoindent'): the entry span's replay ends in <Esc>,
// which would delete the indent.
@@ -1045,7 +1046,7 @@ void mc_vsel_refresh(void)
for (size_t i = 0; i < kv_size(mc_cursors); i++) {
Context *ctx = &kv_A(mc_cursors, i);
pos_T pos;
pos_T pos = { 0 };
if (!mc_ctx_resolve(ctx, &pos)) {
continue;
}