martanne / vis

A vi-like editor based on Plan 9's structural regular expressions
Other
4.23k stars 256 forks source link

gcc10 -fanalyzer results #839

Closed mcepl closed 4 years ago

mcepl commented 4 years ago

When running gcc10 with -fanalyzer it has this to say:

[   93s] make[1]: Entering directory '/home/abuild/rpmbuild/BUILD/vis-0.6'
[   93s] cc -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -flto=auto -g -fcommon -fanalyzer -pipe -O2 -ffunction-sections -fdata-sections -fPIE -fstack-protector-all  -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -I/usr/include/ncursesw     -I/usr/include/lua5.3  -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 -DLUA_COMPAT_ALL  -std=c99 -D_POSIX_C_SOURCE=200809L -U_XOPEN_SOURCE -D_XOPEN_SOURCE=700 -DNDEBUG -D_FORTIFY_SOURCE=2 -DVERSION=\"v0.6\" -DHAVE_MEMRCHR=1 -DVIS_PATH=\"/usr/share/vis\" -DCONFIG_HELP=1 -DCONFIG_CURSES=1 -DCONFIG_LUA=1 -DCONFIG_LPEG=0 -DCONFIG_TRE=1 -DCONFIG_SELINUX=0 -DCONFIG_ACL=0 -U_FORTIFY_SOURCE -UNDEBUG -O0 -g3 -ggdb -Wall -Wextra -pedantic -Wno-missing-field-initializers -Wno-unused-parameter array.c buffer.c libutf.c main.c map.c sam.c text.c text-motions.c text-objects.c text-util.c ui-terminal.c view.c vis.c vis-lua.c vis-modes.c vis-motions.c vis-operators.c vis-registers.c vis-marks.c vis-prompt.c vis-text-objects.c text-regex-tre.c -flto=auto -Wl,-z,now -Wl,-z,relro -Wl,--gc-sections -pie -ltermkey  -Wl,-O2 -Wl,-Bsymbolic-functions -Wl,--as-needed -lncursesw -ltinfo    -ltre -flto=auto  -llua5.3 -lm   -lc -o vis
[   93s] vis-marks.c: In function 'marklist_push':
[   93s] vis-marks.c:145:7: warning: dereference of NULL 'tmp_40' [CWE-690] [-Wanalyzer-null-dereference]
[   93s]   145 |   arr = *tmp;
[   93s]       |       ^
[   93s]   'vis_jumplist_save': events 1-2
[   93s]     |
[   93s]     |  152 | bool vis_jumplist_save(Vis *vis) {
[   93s]     |      |      ^
[   93s]     |      |      |
[   93s]     |      |      (1) entry to 'vis_jumplist_save'
[   93s]     |  153 |  View *view = vis->win->view;
[   93s]     |  154 |  Array sel = view_selections_get_all(view);
[   93s]     |      |              ~
[   93s]     |      |              |
[   93s]     |      |              (2) calling 'view_selections_get_all' from 'vis_jumplist_save'
[   93s]     |
[   93s]     +--> 'view_selections_get_all': events 3-4
[   93s]            |
[   93s]            |view.c:1288:7:
[   93s]            | 1288 | Array view_selections_get_all(View *view) {
[   93s]            |      |       ^
[   93s]            |      |       |
[   93s]            |      |       (3) entry to 'view_selections_get_all'
[   93s]            |......
[   93s]            | 1291 |  if (!array_reserve(&arr, view_selections_count(view)))
[   93s]            |      |       ~
[   93s]            |      |       |
[   93s]            |      |       (4) calling 'array_reserve' from 'view_selections_get_all'
[   93s]            |
[   93s]            +--> 'array_reserve': events 5-9
[   93s]                   |
[   93s]                   |array.c:23:6:
[   93s]                   |   23 | bool array_reserve(Array *arr, size_t count) {
[   93s]                   |      |      ^
[   93s]                   |      |      |
[   93s]                   |      |      (5) entry to 'array_reserve'
[   93s]                   |......
[   93s]                   |   26 |  if (arr->count < count) {
[   93s]                   |      |     ~ 
[   93s]                   |      |     |
[   93s]                   |      |     (6) following 'true' branch...
[   93s]                   |   27 |   count = MAX(count, arr->count*2);
[   93s]                   |      |           ~
[   93s]                   |      |           |
[   93s]                   |      |           (7) ...to here
[   93s]                   |   28 |   char *items = realloc(arr->items, count * arr->elem_size);
[   93s]                   |   29 |   if (!items)
[   93s]                   |      |      ~
[   93s]                   |      |      |
[   93s]                   |      |      (8) following 'true' branch (when 'items_17' is NULL)...
[   93s]                   |   30 |    return false;
[   93s]                   |      |           ~
[   93s]                   |      |           |
[   93s]                   |      |           (9) ...to here
[   93s]                   |
[   93s]            <------+
[   93s]            |
[   93s]          'view_selections_get_all': event 10
[   93s]            |
[   93s]            |view.c:1291:7:
[   93s]            | 1291 |  if (!array_reserve(&arr, view_selections_count(view)))
[   93s]            |      |       ^
[   93s]            |      |       |
[   93s]            |      |       (10) returning to 'view_selections_get_all' from 'array_reserve'
[   93s]            |
[   93s]     <------+
[   93s]     |
[   93s]   'vis_jumplist_save': events 11-12
[   93s]     |
[   93s]     |vis-marks.c:154:14:
[   93s]     |  154 |  Array sel = view_selections_get_all(view);
[   93s]     |      |              ^
[   93s]     |      |              |
[   93s]     |      |              (11) returning to 'vis_jumplist_save' from 'view_selections_get_all'
[   93s]     |  155 |  bool ret = marklist_push(vis->win, &vis->win->jumplist, &sel);
[   93s]     |      |             ~ 
[   93s]     |      |             |
[   93s]     |      |             (12) calling 'marklist_push' from 'vis_jumplist_save'
[   93s]     |
[   93s]     +--> 'marklist_push': events 13-14
[   93s]            |
[   93s]            |  128 | static bool marklist_push(Win *win, MarkList *list, Array *sel) {
[   93s]            |      |             ^
[   93s]            |      |             |
[   93s]            |      |             (13) entry to 'marklist_push'
[   93s]            |  129 |  Array *top = array_peek(&list->prev);
[   93s]            |      |               ~
[   93s]            |      |               |
[   93s]            |      |               (14) calling 'array_peek' from 'marklist_push'
[   93s]            |
[   93s]            +--> 'array_peek': events 15-17
[   93s]                   |
[   93s]                   |array.c:168:7:
[   93s]                   |  168 | void *array_peek(Array *arr) {
[   93s]                   |      |       ^
[   93s]                   |      |       |
[   93s]                   |      |       (15) entry to 'array_peek'
[   93s]                   |  169 |  if (arr->len == 0)
[   93s]                   |      |     ~  
[   93s]                   |      |     |
[   93s]                   |      |     (16) following 'true' branch...
[   93s]                   |  170 |   return NULL;
[   93s]                   |      |          ~
[   93s]                   |      |          |
[   93s]                   |      |          (17) ...to here
[   93s]                   |
[   93s]            <------+
[   93s]            |
[   93s]          'marklist_push': events 18-23
[   93s]            |
[   93s]            |vis-marks.c:129:15:
[   93s]            |  129 |  Array *top = array_peek(&list->prev);
[   93s]            |      |               ^
[   93s]            |      |               |
[   93s]            |      |               (18) returning to 'marklist_push' from 'array_peek'
[   93s]            |  130 |  if (top) {
[   93s]            |      |     ~          
[   93s]            |      |     |
[   93s]            |      |     (19) following 'false' branch (when 'top_22' is NULL)...
[   93s]            |......
[   93s]            |  138 |  for (size_t i = 0, len = array_length(&list->next); i < len; i++)
[   93s]            |      |              ~ 
[   93s]            |      |              |
[   93s]            |      |              (20) ...to here
[   93s]            |......
[   93s]            |  143 |  if (array_length(&list->prev) >= array_capacity(&list->prev)) {
[   93s]            |      |     ~          
[   93s]            |      |     |
[   93s]            |      |     (21) following 'true' branch...
[   93s]            |  144 |   Array *tmp = array_get(&list->prev, 0);
[   93s]            |      |                ~
[   93s]            |      |                |
[   93s]            |      |                (22) ...to here
[   93s]            |      |                (23) calling 'array_get' from 'marklist_push'
[   93s]            |
[   93s]            +--> 'array_get': events 24-26
[   93s]                   |
[   93s]                   |array.c:58:7:
[   93s]                   |   58 | void *array_get(Array *arr, size_t idx) {
[   93s]                   |      |       ^
[   93s]                   |      |       |
[   93s]                   |      |       (24) entry to 'array_get'
[   93s]                   |   59 |  if (idx >= arr->len) {
[   93s]                   |      |     ~  
[   93s]                   |      |     |
[   93s]                   |      |     (25) following 'true' branch...
[   93s]                   |   60 |   errno = EINVAL;
[   93s]                   |      |   ~    
[   93s]                   |      |   |
[   93s]                   |      |   (26) ...to here
[   93s]                   |
[   93s]                 'array_get': event 27
[   93s]                   |
[   93s]                   |lto1:
[   93s]                   | (27): '<anonymous>' is NULL
[   93s]                   |
[   93s]            <------+
[   93s]            |
[   93s]          'marklist_push': events 28-29
[   93s]            |
[   93s]            |vis-marks.c:144:16:
[   93s]            |  144 |   Array *tmp = array_get(&list->prev, 0);
[   93s]            |      |                ^
[   93s]            |      |                |
[   93s]            |      |                (28) return of NULL to 'marklist_push' from 'array_get'
[   93s]            |  145 |   arr = *tmp;
[   93s]            |      |       ~         
[   93s]            |      |       |
[   93s]            |      |       (29) dereference of NULL 'tmp_40'
[   93s]            |
[   93s] vis-marks.c: In function 'vis_lua_win_close':
[   93s] vis-lua.c:3011:21: warning: dereference of NULL 'win_10(D)' [CWE-690] [-Wanalyzer-null-dereference]
[   93s]  3011 |  obj_ref_free(L, win->view);
[   93s]       |                     ^
[   93s]   'vis_lua_win_close': events 1-6
[   93s]     |
[   93s]     | 3001 | void vis_lua_win_close(Vis *vis, Win *win) {
[   93s]     |      |      ^
[   93s]     |      |      |
[   93s]     |      |      (1) entry to 'vis_lua_win_close'
[   93s]     |......
[   93s]     | 3004 |  if (!L)
[   93s]     |      |     ~ 
[   93s]     |      |     |
[   93s]     |      |     (2) following 'false' branch (when 'L_7' is non-NULL)...
[   93s]     | 3005 |   return;
[   93s]     | 3006 |  vis_lua_event_get(L, "win_close");
[   93s]     |      |  ~    
[   93s]     |      |  |
[   93s]     |      |  (3) ...to here
[   93s]     | 3007 |  if (lua_isfunction(L, -1)) {
[   93s]     |      |     ~ 
[   93s]     |      |     |
[   93s]     |      |     (4) following 'true' branch...
[   93s]     | 3008 |   obj_ref_new(L, win, VIS_LUA_TYPE_WINDOW);
[   93s]     |      |   ~   
[   93s]     |      |   |
[   93s]     |      |   (5) ...to here
[   93s]     |      |   (6) calling 'obj_ref_new' from 'vis_lua_win_close'
[   93s]     |
[   93s]     +--> 'obj_ref_new': events 7-9
[   93s]            |
[   93s]            |  413 | static void *obj_ref_new(lua_State *L, void *addr, const char *type) {
[   93s]            |      |              ^
[   93s]            |      |              |
[   93s]            |      |              (7) entry to 'obj_ref_new'
[   93s]            |  414 |  if (!addr) {
[   93s]            |      |     ~         
[   93s]            |      |     |
[   93s]            |      |     (8) following 'true' branch (when 'addr_6(D)' is NULL)...
[   93s]            |  415 |   lua_pushnil(L);
[   93s]            |      |   ~           
[   93s]            |      |   |
[   93s]            |      |   (9) ...to here
[   93s]            |
[   93s]     <------+
[   93s]     |
[   93s]   'vis_lua_win_close': events 10-11
[   93s]     |
[   93s]     | 3008 |   obj_ref_new(L, win, VIS_LUA_TYPE_WINDOW);
[   93s]     |      |   ^
[   93s]     |      |   |
[   93s]     |      |   (10) returning to 'vis_lua_win_close' from 'obj_ref_new'
[   93s]     |......
[   93s]     | 3011 |  obj_ref_free(L, win->view);
[   93s]     |      |                     ~
[   93s]     |      |                     |
[   93s]     |      |                     (11) dereference of NULL 'win_10(D)'
[   93s]     |
[   93s] vis-marks.c: In function 'vis_lua_file_close':
[   93s] vis-lua.c:2971:22: warning: dereference of NULL 'file_11(D)' [CWE-690] [-Wanalyzer-null-dereference]
[   93s]  2971 |  obj_ref_free(L, file->text);
[   93s]       |                      ^
[   93s]   'vis_lua_file_close': events 1-6
[   93s]     |
[   93s]     | 2960 | void vis_lua_file_close(Vis *vis, File *file) {
[   93s]     |      |      ^
[   93s]     |      |      |
[   93s]     |      |      (1) entry to 'vis_lua_file_close'
[   93s]     |......
[   93s]     | 2963 |  if (!L)
[   93s]     |      |     ~ 
[   93s]     |      |     |
[   93s]     |      |     (2) following 'false' branch (when 'L_8' is non-NULL)...
[   93s]     | 2964 |   return;
[   93s]     | 2965 |  vis_lua_event_get(L, "file_close");
[   93s]     |      |  ~    
[   93s]     |      |  |
[   93s]     |      |  (3) ...to here
[   93s]     | 2966 |  if (lua_isfunction(L, -1)) {
[   93s]     |      |     ~ 
[   93s]     |      |     |
[   93s]     |      |     (4) following 'true' branch...
[   93s]     | 2967 |   obj_ref_new(L, file, VIS_LUA_TYPE_FILE);
[   93s]     |      |   ~   
[   93s]     |      |   |
[   93s]     |      |   (5) ...to here
[   93s]     |      |   (6) calling 'obj_ref_new' from 'vis_lua_file_close'
[   93s]     |
[   93s]     +--> 'obj_ref_new': events 7-9
[   93s]            |
[   93s]            |  413 | static void *obj_ref_new(lua_State *L, void *addr, const char *type) {
[   93s]            |      |              ^
[   93s]            |      |              |
[   93s]            |      |              (7) entry to 'obj_ref_new'
[   93s]            |  414 |  if (!addr) {
[   93s]            |      |     ~         
[   93s]            |      |     |
[   93s]            |      |     (8) following 'true' branch (when 'addr_6(D)' is NULL)...
[   93s]            |  415 |   lua_pushnil(L);
[   93s]            |      |   ~           
[   93s]            |      |   |
[   93s]            |      |   (9) ...to here
[   93s]            |
[   93s]     <------+
[   93s]     |
[   93s]   'vis_lua_file_close': events 10-11
[   93s]     |
[   93s]     | 2967 |   obj_ref_new(L, file, VIS_LUA_TYPE_FILE);
[   93s]     |      |   ^
[   93s]     |      |   |
[   93s]     |      |   (10) returning to 'vis_lua_file_close' from 'obj_ref_new'
[   93s]     |......
[   93s]     | 2971 |  obj_ref_free(L, file->text);
[   93s]     |      |                      ~
[   93s]     |      |                      |
[   93s]     |      |                      (11) dereference of NULL 'file_11(D)'
[   93s]     |
[   93s] vis-marks.c: In function 'absolute_path':
[   93s] vis.c:172:2: warning: double-'free' of 'path_absolute_3' [CWE-415] [-Wanalyzer-double-free]
[   93s]   172 |  free(path_absolute);
[   93s]       |  ^
[   93s]   'file_name_set': events 1-4
[   93s]     |
[   93s]     |  223 | void file_name_set(File *file, const char *name) {
[   93s]     |      |      ^
[   93s]     |      |      |
[   93s]     |      |      (1) entry to 'file_name_set'
[   93s]     |  224 |  if (name == file->name)
[   93s]     |      |     ~ 
[   93s]     |      |     |
[   93s]     |      |     (2) following 'false' branch...
[   93s]     |  225 |   return;
[   93s]     |  226 |  free((char*)file->name);
[   93s]     |      |                  ~
[   93s]     |      |                  |
[   93s]     |      |                  (3) ...to here
[   93s]     |  227 |  file->name = absolute_path(name);
[   93s]     |      |               ~
[   93s]     |      |               |
[   93s]     |      |               (4) calling 'absolute_path' from 'file_name_set'
[   93s]     |
[   93s]     +--> 'absolute_path': events 5-12
[   93s]            |
[   93s]            |  149 | char *absolute_path(const char *name) {
[   93s]            |      |       ^
[   93s]            |      |       |
[   93s]            |      |       (5) entry to 'absolute_path'
[   93s]            |  150 |  if (!name)
[   93s]            |      |     ~  
[   93s]            |      |     |
[   93s]            |      |     (6) following 'false' branch (when 'name_10(D)' is non-NULL)...
[   93s]            |  151 |   return NULL;
[   93s]            |  152 |  char *copy1 = strdup(name);
[   93s]            |      |                ~
[   93s]            |      |                |
[   93s]            |      |                (7) ...to here
[   93s]            |      |                (8) 'path_absolute_16' is NULL
[   93s]            |......
[   93s]            |  157 |  if (!copy1 || !copy2)
[   93s]            |      |     ~  
[   93s]            |      |     |
[   93s]            |      |     (9) following 'true' branch (when 'copy1_13' is NULL)...
[   93s]            |  158 |   goto err;
[   93s]            |      |   ~    
[   93s]            |      |   |
[   93s]            |      |   (10) ...to here
[   93s]            |......
[   93s]            |  169 | err:
[   93s]            |      | ~      
[   93s]            |      | |
[   93s]            |      | (11) first 'free' here
[   93s]            |......
[   93s]            |  172 |  free(path_absolute);
[   93s]            |      |  ~     
[   93s]            |      |  |
[   93s]            |      |  (12) second 'free' here; first 'free' was at (11)
[   93s]            |
[   93s] vis-marks.c: In function 'view_regions_save':
[   93s] view.c:1252:31: warning: dereference of NULL 'r_18(D)' [CWE-690] [-Wanalyzer-null-dereference]
[   93s]  1252 |  if (!text_range_valid(r) || r->start >= max)
[   93s]       |                               ^
[   93s]   'vis_mark_set': events 1-2
[   93s]     |
[   93s]     |vis-marks.c:105:6:
[   93s]     |  105 | void vis_mark_set(Win *win, enum VisMark id, Array *sel) {
[   93s]     |      |      ^
[   93s]     |      |      |
[   93s]     |      |      (1) entry to 'vis_mark_set'
[   93s]     |  106 |  mark_set(win, mark_from(win->vis, id), sel);
[   93s]     |      |  ~    
[   93s]     |      |  |
[   93s]     |      |  (2) calling 'mark_from' from 'vis_mark_set'
[   93s]     |
[   93s]     +--> 'mark_from': events 3-7
[   93s]            |
[   93s]            |   50 | static Array *mark_from(Vis *vis, enum VisMark id) {
[   93s]            |      |               ^
[   93s]            |      |               |
[   93s]            |      |               (3) entry to 'mark_from'
[   93s]            |   51 |  if (!vis->win)
[   93s]            |      |     ~          
[   93s]            |      |     |
[   93s]            |      |     (4) following 'false' branch...
[   93s]            |   52 |   return NULL;
[   93s]            |   53 |  if (id == VIS_MARK_SELECTION)
[   93s]            |      |     ~          
[   93s]            |      |     |
[   93s]            |      |     (5) ...to here
[   93s]            |      |     (6) following 'true' branch (when 'id_7(D) == 1')...
[   93s]            |   54 |   return &vis->win->saved_selections;
[   93s]            |      |              ~ 
[   93s]            |      |              |
[   93s]            |      |              (7) ...to here
[   93s]            |
[   93s]     <------+
[   93s]     |
[   93s]   'vis_mark_set': events 8-9
[   93s]     |
[   93s]     |  106 |  mark_set(win, mark_from(win->vis, id), sel);
[   93s]     |      |  ^
[   93s]     |      |  |
[   93s]     |      |  (8) returning to 'vis_mark_set' from 'mark_from'
[   93s]     |      |  (9) calling 'mark_set' from 'vis_mark_set'
[   93s]     |
[   93s]     +--> 'mark_set': events 10-15
[   93s]            |
[   93s]            |   92 | static void mark_set(Win *win, Array *mark, Array *sel) {
[   93s]            |      |             ^
[   93s]            |      |             |
[   93s]            |      |             (10) entry to 'mark_set'
[   93s]            |   93 |  if (!mark)
[   93s]            |      |     ~        
[   93s]            |      |     |
[   93s]            |      |     (11) following 'false' branch (when 'mark_6(D)' is non-NULL)...
[   93s]            |   94 |   return;
[   93s]            |   95 |  array_clear(mark);
[   93s]            |      |  ~           
[   93s]            |      |  |
[   93s]            |      |  (12) ...to here
[   93s]            |   96 |  View *view = win->view;
[   93s]            |   97 |  for (size_t i = 0, len = array_length(sel); i < len; i++) {
[   93s]            |      |  ~           
[   93s]            |      |  |
[   93s]            |      |  (13) following 'true' branch (when 'i_2 < len_14')...
[   93s]            |   98 |   SelectionRegion ss;
[   93s]            |   99 |   Filerange *r = array_get(sel, i);
[   93s]            |      |                  ~
[   93s]            |      |                  |
[   93s]            |      |                  (14) ...to here
[   93s]            |      |                  (15) calling 'array_get' from 'mark_set'
[   93s]            |
[   93s]            +--> 'array_get': events 16-18
[   93s]                   |
[   93s]                   |array.c:58:7:
[   93s]                   |   58 | void *array_get(Array *arr, size_t idx) {
[   93s]                   |      |       ^
[   93s]                   |      |       |
[   93s]                   |      |       (16) entry to 'array_get'
[   93s]                   |   59 |  if (idx >= arr->len) {
[   93s]                   |      |     ~  
[   93s]                   |      |     |
[   93s]                   |      |     (17) following 'true' branch...
[   93s]                   |   60 |   errno = EINVAL;
[   93s]                   |      |   ~    
[   93s]                   |      |   |
[   93s]                   |      |   (18) ...to here
[   93s]                   |
[   93s]                 'array_get': event 19
[   93s]                   |
[   93s]                   |lto1:
[   93s]                   | (19): '<anonymous>' is NULL
[   93s]                   |
[   93s]            <------+
[   93s]            |
[   93s]          'mark_set': events 20-21
[   93s]            |
[   93s]            |vis-marks.c:99:18:
[   93s]            |   99 |   Filerange *r = array_get(sel, i);
[   93s]            |      |                  ^
[   93s]            |      |                  |
[   93s]            |      |                  (20) return of NULL to 'mark_set' from 'array_get'
[   93s]            |  100 |   if (view_regions_save(view, r, &ss))
[   93s]            |      |       ~           
[   93s]            |      |       |
[   93s]            |      |       (21) calling 'view_regions_save' from 'mark_set'
[   93s]            |
[   93s]            +--> 'view_regions_save': events 22-23
[   93s]                   |
[   93s]                   |view.c:1249:6:
[   93s]                   | 1249 | bool view_regions_save(View *view, Filerange *r, SelectionRegion *s) {
[   93s]                   |      |      ^
[   93s]                   |      |      |
[   93s]                   |      |      (22) entry to 'view_regions_save'
[   93s]                   |......
[   93s]                   | 1252 |  if (!text_range_valid(r) || r->start >= max)
[   93s]                   |      |       ~
[   93s]                   |      |       |
[   93s]                   |      |       (23) calling 'text_range_valid' from 'view_regions_save'
[   93s]                   |
[   93s]                   +--> 'text_range_valid': events 24-31
[   93s]                          |
[   93s]                          |text-util.c:7:6:
[   93s]                          |    7 | bool text_range_valid(const Filerange *r) {
[   93s]                          |      |      ^
[   93s]                          |      |      |
[   93s]                          |      |      (24) entry to 'text_range_valid'
[   93s]                          |    8 |  return r->start != EPOS && r->end != EPOS && r->start <= r->end;
[   93s]                          |      |          ~               ~   ~             ~   ~
[   93s]                          |      |          |               |   |             |   |
[   93s]                          |      |          |               |   |             |   (29) ...to here
[   93s]                          |      |          |               |   |             (26) following 'true' branch...
[   93s]                          |      |          |               |   |             (30) following 'true' branch...
[   93s]                          |      |          |               |   |             (31) ...to here
[   93s]                          |      |          |               |   (27) ...to here
[   93s]                          |      |          |               (28) following 'true' branch...
[   93s]                          |      |          (25) state of 'r_7(D)': 'null' -> 'stop' (origin: NULL)
[   93s]                          |
[   93s]                   <------+
[   93s]                   |
[   93s]                 'view_regions_save': events 32-35
[   93s]                   |
[   93s]                   |view.c:1252:7:
[   93s]                   | 1252 |  if (!text_range_valid(r) || r->start >= max)
[   93s]                   |      |     ~ ^                       ~
[   93s]                   |      |     | |                       |
[   93s]                   |      |     | |                       (34) ...to here
[   93s]                   |      |     | |                       (35) dereference of NULL 'r_18(D)'
[   93s]                   |      |     | (32) returning to 'view_regions_save' from 'text_range_valid'
[   93s]                   |      |     (33) following 'false' branch...
[   93s]                   |
[   93s] vis-marks.c: In function 'view_regions_restore':
[   93s] view.c:1241:18: warning: dereference of NULL 's_10(D)' [CWE-690] [-Wanalyzer-null-dereference]
[   93s]  1241 |  size_t anchor = text_mark_get(txt, s->anchor);
[   93s]       |                  ^
[   93s]   'vis_mark_get': events 1-2
[   93s]     |
[   93s]     |vis-marks.c:88:7:
[   93s]     |   88 | Array vis_mark_get(Win *win, enum VisMark id) {
[   93s]     |      |       ^
[   93s]     |      |       |
[   93s]     |      |       (1) entry to 'vis_mark_get'
[   93s]     |   89 |  return mark_get(win, mark_from(win->vis, id));
[   93s]     |      |         ~
[   93s]     |      |         |
[   93s]     |      |         (2) calling 'mark_from' from 'vis_mark_get'
[   93s]     |
[   93s]     +--> 'mark_from': events 3-7
[   93s]            |
[   93s]            |   50 | static Array *mark_from(Vis *vis, enum VisMark id) {
[   93s]            |      |               ^
[   93s]            |      |               |
[   93s]            |      |               (3) entry to 'mark_from'
[   93s]            |   51 |  if (!vis->win)
[   93s]            |      |     ~          
[   93s]            |      |     |
[   93s]            |      |     (4) following 'false' branch...
[   93s]            |   52 |   return NULL;
[   93s]            |   53 |  if (id == VIS_MARK_SELECTION)
[   93s]            |      |     ~          
[   93s]            |      |     |
[   93s]            |      |     (5) ...to here
[   93s]            |      |     (6) following 'true' branch (when 'id_7(D) == 1')...
[   93s]            |   54 |   return &vis->win->saved_selections;
[   93s]            |      |              ~ 
[   93s]            |      |              |
[   93s]            |      |              (7) ...to here
[   93s]            |
[   93s]     <------+
[   93s]     |
[   93s]   'vis_mark_get': events 8-9
[   93s]     |
[   93s]     |   89 |  return mark_get(win, mark_from(win->vis, id));
[   93s]     |      |         ^
[   93s]     |      |         |
[   93s]     |      |         (8) returning to 'vis_mark_get' from 'mark_from'
[   93s]     |      |         (9) calling 'mark_get' from 'vis_mark_get'
[   93s]     |
[   93s]     +--> 'mark_get': events 10-13
[   93s]            |
[   93s]            |   70 | static Array mark_get(Win *win, Array *mark) {
[   93s]            |      |              ^
[   93s]            |      |              |
[   93s]            |      |              (10) entry to 'mark_get'
[   93s]            |......
[   93s]            |   73 |  if (!mark)
[   93s]            |      |     ~         
[   93s]            |      |     |
[   93s]            |      |     (11) following 'false' branch (when 'mark_8(D)' is non-NULL)...
[   93s]            |   74 |   return sel;
[   93s]            |   75 |  View *view = win->view;
[   93s]            |      |        ~      
[   93s]            |      |        |
[   93s]            |      |        (12) ...to here
[   93s]            |   76 |  size_t len = array_length(mark);
[   93s]            |   77 |  array_reserve(&sel, len);
[   93s]            |      |  ~            
[   93s]            |      |  |
[   93s]            |      |  (13) calling 'array_reserve' from 'mark_get'
[   93s]            |
[   93s]            +--> 'array_reserve': events 14-18
[   93s]                   |
[   93s]                   |array.c:23:6:
[   93s]                   |   23 | bool array_reserve(Array *arr, size_t count) {
[   93s]                   |      |      ^
[   93s]                   |      |      |
[   93s]                   |      |      (14) entry to 'array_reserve'
[   93s]                   |......
[   93s]                   |   26 |  if (arr->count < count) {
[   93s]                   |      |     ~ 
[   93s]                   |      |     |
[   93s]                   |      |     (15) following 'true' branch...
[   93s]                   |   27 |   count = MAX(count, arr->count*2);
[   93s]                   |      |           ~
[   93s]                   |      |           |
[   93s]                   |      |           (16) ...to here
[   93s]                   |   28 |   char *items = realloc(arr->items, count * arr->elem_size);
[   93s]                   |   29 |   if (!items)
[   93s]                   |      |      ~
[   93s]                   |      |      |
[   93s]                   |      |      (17) following 'true' branch (when 'items_17' is NULL)...
[   93s]                   |   30 |    return false;
[   93s]                   |      |           ~
[   93s]                   |      |           |
[   93s]                   |      |           (18) ...to here
[   93s]                   |
[   93s]            <------+
[   93s]            |
[   93s]          'mark_get': events 19-22
[   93s]            |
[   93s]            |vis-marks.c:77:2:
[   93s]            |   77 |  array_reserve(&sel, len);
[   93s]            |      |  ^
[   93s]            |      |  |
[   93s]            |      |  (19) returning to 'mark_get' from 'array_reserve'
[   93s]            |   78 |  for (size_t i = 0; i < len; i++) {
[   93s]            |      |  ~
[   93s]            |      |  |
[   93s]            |      |  (20) following 'true' branch (when 'i_2 < len_12')...
[   93s]            |   79 |   SelectionRegion *sr = array_get(mark, i);
[   93s]            |      |                         ~
[   93s]            |      |                         |
[   93s]            |      |                         (21) ...to here
[   93s]            |      |                         (22) calling 'array_get' from 'mark_get'
[   93s]            |
[   93s]            +--> 'array_get': events 23-25
[   93s]                   |
[   93s]                   |array.c:58:7:
[   93s]                   |   58 | void *array_get(Array *arr, size_t idx) {
[   93s]                   |      |       ^
[   93s]                   |      |       |
[   93s]                   |      |       (23) entry to 'array_get'
[   93s]                   |   59 |  if (idx >= arr->len) {
[   93s]                   |      |     ~  
[   93s]                   |      |     |
[   93s]                   |      |     (24) following 'true' branch...
[   93s]                   |   60 |   errno = EINVAL;
[   93s]                   |      |   ~    
[   93s]                   |      |   |
[   93s]                   |      |   (25) ...to here
[   93s]                   |
[   93s]                 'array_get': event 26
[   93s]                   |
[   93s]                   |lto1:
[   93s]                   | (26): '<anonymous>' is NULL
[   93s]                   |
[   93s]            <------+
[   93s]            |
[   93s]          'mark_get': events 27-28
[   93s]            |
[   93s]            |vis-marks.c:79:25:
[   93s]            |   79 |   SelectionRegion *sr = array_get(mark, i);
[   93s]            |      |                         ^
[   93s]            |      |                         |
[   93s]            |      |                         (27) return of NULL to 'mark_get' from 'array_get'
[   93s]            |   80 |   Filerange r = view_regions_restore(view, sr);
[   93s]            |      |                 ~        
[   93s]            |      |                 |
[   93s]            |      |                 (28) calling 'view_regions_restore' from 'mark_get'
[   93s]            |
[   93s]            +--> 'view_regions_restore': events 29-30
[   93s]                   |
[   93s]                   |view.c:1239:11:
[   93s]                   | 1239 | Filerange view_regions_restore(View *view, SelectionRegion *s) {
[   93s]                   |      |           ^
[   93s]                   |      |           |
[   93s]                   |      |           (29) entry to 'view_regions_restore'
[   93s]                   | 1240 |  Text *txt = view->text;
[   93s]                   | 1241 |  size_t anchor = text_mark_get(txt, s->anchor);
[   93s]                   |      |                  ~
[   93s]                   |      |                  |
[   93s]                   |      |                  (30) dereference of NULL 's_10(D)'
[   93s]                   |
[   93s] vis-marks.c: In function 'text_range_valid':
[   93s] text-util.c:8:10: warning: dereference of NULL 'r_7(D)' [CWE-690] [-Wanalyzer-null-dereference]
[   93s]     8 |  return r->start != EPOS && r->end != EPOS && r->start <= r->end;
[   93s]       |          ^
[   93s]   'vis_mark_equal': events 1-6
[   93s]     |
[   93s]     |vis-marks.c:28:6:
[   93s]     |   28 | bool vis_mark_equal(Array *a, Array *b) {
[   93s]     |      |      ^
[   93s]     |      |      |
[   93s]     |      |      (1) entry to 'vis_mark_equal'
[   93s]     |   29 |  size_t len = array_length(a);
[   93s]     |   30 |  if (len != array_length(b))
[   93s]     |      |     ~ 
[   93s]     |      |     |
[   93s]     |      |     (2) following 'false' branch...
[   93s]     |   31 |   return false;
[   93s]     |   32 |  for (size_t i = 0; i < len; i++) {
[   93s]     |      |  ~           ~
[   93s]     |      |  |           |
[   93s]     |      |  |           (3) ...to here
[   93s]     |      |  (4) following 'true' branch (when 'i_6 < len_13')...
[   93s]     |   33 |   if (!text_range_equal(array_get(a, i), array_get(b, i)))
[   93s]     |      |                                          ~
[   93s]     |      |                                          |
[   93s]     |      |                                          (5) ...to here
[   93s]     |      |                                          (6) calling 'array_get' from 'vis_mark_equal'
[   93s]     |
[   93s]     +--> 'array_get': events 7-9
[   93s]            |
[   93s]            |array.c:58:7:
[   93s]            |   58 | void *array_get(Array *arr, size_t idx) {
[   93s]            |      |       ^
[   93s]            |      |       |
[   93s]            |      |       (7) entry to 'array_get'
[   93s]            |   59 |  if (idx >= arr->len) {
[   93s]            |      |     ~  
[   93s]            |      |     |
[   93s]            |      |     (8) following 'true' branch...
[   93s]            |   60 |   errno = EINVAL;
[   93s]            |      |   ~    
[   93s]            |      |   |
[   93s]            |      |   (9) ...to here
[   93s]            |
[   93s]     <------+
[   93s]     |
[   93s]   'vis_mark_equal': events 10-11
[   93s]     |
[   93s]     |vis-marks.c:33:42:
[   93s]     |   33 |   if (!text_range_equal(array_get(a, i), array_get(b, i)))
[   93s]     |      |                         ~                ^
[   93s]     |      |                         |                |
[   93s]     |      |                         |                (10) returning to 'vis_mark_equal' from 'array_get'
[   93s]     |      |                         (11) calling 'array_get' from 'vis_mark_equal'
[   93s]     |
[   93s]     +--> 'array_get': events 12-14
[   93s]            |
[   93s]            |array.c:58:7:
[   93s]            |   58 | void *array_get(Array *arr, size_t idx) {
[   93s]            |      |       ^
[   93s]            |      |       |
[   93s]            |      |       (12) entry to 'array_get'
[   93s]            |   59 |  if (idx >= arr->len) {
[   93s]            |      |     ~  
[   93s]            |      |     |
[   93s]            |      |     (13) following 'true' branch...
[   93s]            |   60 |   errno = EINVAL;
[   93s]            |      |   ~    
[   93s]            |      |   |
[   93s]            |      |   (14) ...to here
[   93s]            |
[   93s]          'array_get': event 15
[   93s]            |
[   93s]            |lto1:
[   93s]            | (15): '<anonymous>' is NULL
[   93s]            |
[   93s]     <------+
[   93s]     |
[   93s]   'vis_mark_equal': events 16-17
[   93s]     |
[   93s]     |vis-marks.c:33:25:
[   93s]     |   33 |   if (!text_range_equal(array_get(a, i), array_get(b, i)))
[   93s]     |      |        ~                ^
[   93s]     |      |        |                |
[   93s]     |      |        |                (16) return of NULL to 'vis_mark_equal' from 'array_get'
[   93s]     |      |        (17) calling 'text_range_equal' from 'vis_mark_equal'
[   93s]     |
[   93s]     +--> 'text_range_equal': events 18-19
[   93s]            |
[   93s]            |text-util.c:43:6:
[   93s]            |   43 | bool text_range_equal(const Filerange *r1, const Filerange *r2) {
[   93s]            |      |      ^
[   93s]            |      |      |
[   93s]            |      |      (18) entry to 'text_range_equal'
[   93s]            |   44 |  if (!text_range_valid(r1) && !text_range_valid(r2))
[   93s]            |      |       ~
[   93s]            |      |       |
[   93s]            |      |       (19) calling 'text_range_valid' from 'text_range_equal'
[   93s]            |
[   93s]            +--> 'text_range_valid': events 20-21
[   93s]                   |
[   93s]                   |    7 | bool text_range_valid(const Filerange *r) {
[   93s]                   |      |      ^
[   93s]                   |      |      |
[   93s]                   |      |      (20) entry to 'text_range_valid'
[   93s]                   |    8 |  return r->start != EPOS && r->end != EPOS && r->start <= r->end;
[   93s]                   |      |          ~
[   93s]                   |      |          |
[   93s]                   |      |          (21) dereference of NULL 'r_7(D)'
[   93s]                   |
[   93s] vis-marks.c: In function 'map_delete':
[   93s] map.c:189:10: warning: leak of 'map' [CWE-401] [-Wanalyzer-malloc-leak]
[   93s]   189 |   return NULL;
[   93s]       |          ^
[   93s]   'vis_window_mode_map': events 1-4
[   93s]     |
[   93s]     |vis-modes.c:137:6:
[   93s]     |  137 | bool vis_window_mode_map(Win *win, enum VisMode id, bool force, const char *key, const KeyBinding *binding) {
[   93s]     |      |      ^
[   93s]     |      |      |
[   93s]     |      |      (1) entry to 'vis_window_mode_map'
[   93s]     |  138 |  return id < LENGTH(win->modes) && mode_map(win->vis, &win->modes[id], force, key, binding);
[   93s]     |      |                                 ~  ~
[   93s]     |      |                                 |  |
[   93s]     |      |                                 |  (3) ...to here
[   93s]     |      |                                 |  (4) calling 'mode_map' from 'vis_window_mode_map'
[   93s]     |      |                                 (2) following 'true' branch (when 'id_8(D) <= 5')...
[   93s]     |
[   93s]     +--> 'mode_map': events 5-10
[   93s]            |
[   93s]            |  121 | static bool mode_map(Vis *vis, Mode *mode, bool force, const char *key, const KeyBinding *binding) {
[   93s]            |      |             ^
[   93s]            |      |             |
[   93s]            |      |             (5) entry to 'mode_map'
[   93s]            |  122 |  if (!mode)
[   93s]            |      |     ~        
[   93s]            |      |     |
[   93s]            |      |     (6) following 'false' branch (when 'mode_15(D)' is non-NULL)...
[   93s]            |  123 |   return false;
[   93s]            |  124 |  if (binding->alias && key[0] != '<' && strncmp(key, binding->alias, strlen(key)) == 0)
[   93s]            |      |             ~
[   93s]            |      |             |
[   93s]            |      |             (7) ...to here
[   93s]            |  125 |   return false;
[   93s]            |  126 |  if (!mode->bindings && !(mode->bindings = map_new()))
[   93s]            |      |     ~                                      ~
[   93s]            |      |     |                                      |
[   93s]            |      |     |                                      (9) ...to here
[   93s]            |      |     (8) following 'true' branch...         (10) calling 'map_new' from 'mode_map'
[   93s]            |
[   93s]            +--> 'map_new': events 11-12
[   93s]                   |
[   93s]                   |map.c:350:6:
[   93s]                   |  350 | Map *map_new(void)
[   93s]                   |      |      ^
[   93s]                   |      |      |
[   93s]                   |      |      (11) entry to 'map_new'
[   93s]                   |  351 | {
[   93s]                   |  352 |  return calloc(1, sizeof(Map));
[   93s]                   |      |         ~
[   93s]                   |      |         |
[   93s]                   |      |         (12) allocated here
[   93s]                   |
[   93s]            <------+
[   93s]            |
[   93s]          'mode_map': events 13-19
[   93s]            |
[   93s]            |vis-modes.c:126:44:
[   93s]            |  126 |  if (!mode->bindings && !(mode->bindings = map_new()))
[   93s]            |      |                      ~                     ^
[   93s]            |      |                      |                     |
[   93s]            |      |                      |                     (13) returning to 'mode_map' from 'map_new'
[   93s]            |      |                      (14) following 'false' branch...
[   93s]            |  127 |   return false;
[   93s]            |  128 |  if (force)
[   93s]            |      |     ~                                       
[   93s]            |      |     |
[   93s]            |      |     (15) ...to here
[   93s]            |      |     (16) following 'true' branch (when 'force_23(D) != 0')...
[   93s]            |  129 |   map_delete(mode->bindings, key);
[   93s]            |      |   ~                                         
[   93s]            |      |   |
[   93s]            |      |   (17) ...to here
[   93s]            |      |   (18) state of '_9': 'start' -> 'nonnull' (origin: 'mode_15(D)->bindings')
[   93s]            |      |   (19) calling 'map_delete' from 'mode_map'
[   93s]            |
[   93s]            +--> 'map_delete': events 20-23
[   93s]                   |
[   93s]                   |map.c:178:7:
[   93s]                   |  178 | void *map_delete(Map *map, const char *key)
[   93s]                   |      |       ^
[   93s]                   |      |       |
[   93s]                   |      |       (20) entry to 'map_delete'
[   93s]                   |......
[   93s]                   |  187 |  if (!map->u.n) {
[   93s]                   |      |     ~  
[   93s]                   |      |     |
[   93s]                   |      |     (21) following 'true' branch...
[   93s]                   |  188 |   errno = ENOENT;
[   93s]                   |      |   ~    
[   93s]                   |      |   |
[   93s]                   |      |   (22) ...to here
[   93s]                   |  189 |   return NULL;
[   93s]                   |      |          ~
[   93s]                   |      |          |
[   93s]                   |      |          (23) 'map' leaks here; was allocated at (12)
[   93s]                   |
[   93s] vis-marks.c: In function 'buffer_content':
[   93s] buffer.c:171:12: warning: dereference of NULL 'buf_2(D)' [CWE-690] [-Wanalyzer-null-dereference]
[   93s]   171 |  return buf->data;
[   93s]       |            ^
[   93s]   'vis_register_get': events 1-2
[   93s]     |
[   93s]     |vis-registers.c:245:7:
[   93s]     |  245 | Array vis_register_get(Vis *vis, enum VisRegister id) {
[   93s]     |      |       ^
[   93s]     |      |       |
[   93s]     |      |       (1) entry to 'vis_register_get'
[   93s]     |......
[   93s]     |  248 |  Register *reg = register_from(vis, id);
[   93s]     |      |                  ~
[   93s]     |      |                  |
[   93s]     |      |                  (2) calling 'register_from' from 'vis_register_get'
[   93s]     |
[   93s]     +--> 'register_from': events 3-5
[   93s]            |
[   93s]            |  221 | static Register *register_from(Vis *vis, enum VisRegister id) {
[   93s]            |      |                  ^
[   93s]            |      |                  |
[   93s]            |      |                  (3) entry to 'register_from'
[   93s]            |......
[   93s]            |  224 |  if (id < LENGTH(vis->registers))
[   93s]            |      |     ~             
[   93s]            |      |     |
[   93s]            |      |     (4) following 'true' branch (when 'id_1 <= 46')...
[   93s]            |  225 |   return &vis->registers[id];
[   93s]            |      |          ~        
[   93s]            |      |          |
[   93s]            |      |          (5) ...to here
[   93s]            |
[   93s]     <------+
[   93s]     |
[   93s]   'vis_register_get': events 6-9
[   93s]     |
[   93s]     |  248 |  Register *reg = register_from(vis, id);
[   93s]     |      |                  ^
[   93s]     |      |                  |
[   93s]     |      |                  (6) returning to 'vis_register_get' from 'register_from'
[   93s]     |  249 |  if (reg) {
[   93s]     |      |     ~             
[   93s]     |      |     |
[   93s]     |      |     (7) following 'true' branch (when 'reg_13' is non-NULL)...
[   93s]     |  250 |   size_t len = array_length(&reg->values);
[   93s]     |      |                ~  
[   93s]     |      |                |
[   93s]     |      |                (8) ...to here
[   93s]     |  251 |   array_reserve(&data, len);
[   93s]     |      |   ~               
[   93s]     |      |   |
[   93s]     |      |   (9) calling 'array_reserve' from 'vis_register_get'
[   93s]     |
[   93s]     +--> 'array_reserve': events 10-14
[   93s]            |
[   93s]            |array.c:23:6:
[   93s]            |   23 | bool array_reserve(Array *arr, size_t count) {
[   93s]            |      |      ^
[   93s]            |      |      |
[   93s]            |      |      (10) entry to 'array_reserve'
[   93s]            |......
[   93s]            |   26 |  if (arr->count < count) {
[   93s]            |      |     ~ 
[   93s]            |      |     |
[   93s]            |      |     (11) following 'true' branch...
[   93s]            |   27 |   count = MAX(count, arr->count*2);
[   93s]            |      |           ~
[   93s]            |      |           |
[   93s]            |      |           (12) ...to here
[   93s]            |   28 |   char *items = realloc(arr->items, count * arr->elem_size);
[   93s]            |   29 |   if (!items)
[   93s]            |      |      ~
[   93s]            |      |      |
[   93s]            |      |      (13) following 'true' branch (when 'items_17' is NULL)...
[   93s]            |   30 |    return false;
[   93s]            |      |           ~
[   93s]            |      |           |
[   93s]            |      |           (14) ...to here
[   93s]            |
[   93s]     <------+
[   93s]     |
[   93s]   'vis_register_get': events 15-18
[   93s]     |
[   93s]     |vis-registers.c:251:3:
[   93s]     |  251 |   array_reserve(&data, len);
[   93s]     |      |   ^
[   93s]     |      |   |
[   93s]     |      |   (15) returning to 'vis_register_get' from 'array_reserve'
[   93s]     |  252 |   for (size_t i = 0; i < len; i++) {
[   93s]     |      |   ~
[   93s]     |      |   |
[   93s]     |      |   (16) following 'true' branch (when 'i_5 < len_15')...
[   93s]     |  253 |    Buffer *buf = array_get(&reg->values, i);
[   93s]     |      |                  ~
[   93s]     |      |                  |
[   93s]     |      |                  (17) ...to here
[   93s]     |      |                  (18) calling 'array_get' from 'vis_register_get'
[   93s]     |
[   93s]     +--> 'array_get': events 19-21
[   93s]            |
[   93s]            |array.c:58:7:
[   93s]            |   58 | void *array_get(Array *arr, size_t idx) {
[   93s]            |      |       ^
[   93s]            |      |       |
[   93s]            |      |       (19) entry to 'array_get'
[   93s]            |   59 |  if (idx >= arr->len) {
[   93s]            |      |     ~  
[   93s]            |      |     |
[   93s]            |      |     (20) following 'true' branch...
[   93s]            |   60 |   errno = EINVAL;
[   93s]            |      |   ~    
[   93s]            |      |   |
[   93s]            |      |   (21) ...to here
[   93s]            |
[   93s]          'array_get': event 22
[   93s]            |
[   93s]            |lto1:
[   93s]            | (22): '<anonymous>' is NULL
[   93s]            |
[   93s]     <------+
[   93s]     |
[   93s]   'vis_register_get': events 23-24
[   93s]     |
[   93s]     |vis-registers.c:253:18:
[   93s]     |  253 |    Buffer *buf = array_get(&reg->values, i);
[   93s]     |      |                  ^
[   93s]     |      |                  |
[   93s]     |      |                  (23) return of NULL to 'vis_register_get' from 'array_get'
[   93s]     |  254 |    TextString string = {
[   93s]     |  255 |     .data = buffer_content(buf),
[   93s]     |      |             ~     
[   93s]     |      |             |
[   93s]     |      |             (24) calling 'buffer_content' from 'vis_register_get'
[   93s]     |
[   93s]     +--> 'buffer_content': events 25-26
[   93s]            |
[   93s]            |buffer.c:170:13:
[   93s]            |  170 | const char *buffer_content(Buffer *buf) {
[   93s]            |      |             ^
[   93s]            |      |             |
[   93s]            |      |             (25) entry to 'buffer_content'
[   93s]            |  171 |  return buf->data;
[   93s]            |      |            ~ 
[   93s]            |      |            |
[   93s]            |      |            (26) dereference of NULL 'buf_2(D)'
[   93s]            |
[   93s] vis-marks.c: In function 'buffer_clear':
[   93s] buffer.c:52:11: warning: dereference of NULL 'buf_2(D)' [CWE-690] [-Wanalyzer-null-dereference]
[   93s]    52 |  buf->len = 0;
[   93s]       |           ^
[   93s]   'vis_operator': events 1-4
[   93s]     |
[   93s]     |vis-operators.c:238:6:
[   93s]     |  238 | bool vis_operator(Vis *vis, enum VisOperator id, ...) {
[   93s]     |      |      ^
[   93s]     |      |      |
[   93s]     |      |      (1) entry to 'vis_operator'
[   93s]     |......
[   93s]     |  242 |  switch (id) {
[   93s]     |      |  ~    
[   93s]     |      |  |
[   93s]     |      |  (2) following 'case 8:' branch...
[   93s]     |......
[   93s]     |  265 |  case VIS_OP_REPLACE:
[   93s]     |      |  ~    
[   93s]     |      |  |
[   93s]     |      |  (3) ...to here
[   93s]     |  266 |  {
[   93s]     |  267 |   Macro *macro = macro_get(vis, VIS_REG_DOT);
[   93s]     |      |                  ~
[   93s]     |      |                  |
[   93s]     |      |                  (4) calling 'macro_get' from 'vis_operator'
[   93s]     |
[   93s]     +--> 'macro_get': events 5-12
[   93s]            |
[   93s]            |vis.c:1427:8:
[   93s]            | 1427 | Macro *macro_get(Vis *vis, enum VisRegister id) {
[   93s]            |      |        ^
[   93s]            |      |        |
[   93s]            |      |        (5) entry to 'macro_get'
[   93s]            | 1428 |  if (id == VIS_MACRO_LAST_RECORDED)
[   93s]            |      |     ~   
[   93s]            |      |     |
[   93s]            |      |     (6) following 'false' branch (when 'id_5(D) != 74')...
[   93s]            | 1429 |   return vis->last_recording;
[   93s]            | 1430 |  if (VIS_REG_A <= id && id <= VIS_REG_Z)
[   93s]            |      |     ~   
[   93s]            |      |     |
[   93s]            |      |     (7) ...to here
[   93s]            |      |     (8) following 'false' branch (when 'id_5(D) <= 47')...
[   93s]            | 1431 |   id -= VIS_REG_A;
[   93s]            | 1432 |  if (id < LENGTH(vis->registers))
[   93s]            |      |     ~   
[   93s]            |      |     |
[   93s]            |      |     (9) ...to here
[   93s]            |      |     (10) following 'true' branch (when 'id_2 <= 46')...
[   93s]            | 1433 |   return array_get(&vis->registers[id].values, 0);
[   93s]            |      |          ~
[   93s]            |      |          |
[   93s]            |      |          (11) ...to here
[   93s]            |      |          (12) calling 'array_get' from 'macro_get'
[   93s]            |
[   93s]            +--> 'array_get': events 13-15
[   93s]                   |
[   93s]                   |array.c:58:7:
[   93s]                   |   58 | void *array_get(Array *arr, size_t idx) {
[   93s]                   |      |       ^
[   93s]                   |      |       |
[   93s]                   |      |       (13) entry to 'array_get'
[   93s]                   |   59 |  if (idx >= arr->len) {
[   93s]                   |      |     ~  
[   93s]                   |      |     |
[   93s]                   |      |     (14) following 'true' branch...
[   93s]                   |   60 |   errno = EINVAL;
[   93s]                   |      |   ~    
[   93s]                   |      |   |
[   93s]                   |      |   (15) ...to here
[   93s]                   |
[   93s]            <------+
[   93s]            |
[   93s]          'macro_get': event 16
[   93s]            |
[   93s]            |vis.c:1433:10:
[   93s]            | 1433 |   return array_get(&vis->registers[id].values, 0);
[   93s]            |      |          ^
[   93s]            |      |          |
[   93s]            |      |          (16) returning to 'macro_get' from 'array_get'
[   93s]            |
[   93s]          'macro_get': event 17
[   93s]            |
[   93s]            |lto1:
[   93s]            | (17): '<anonymous>' is NULL
[   93s]            |
[   93s]     <------+
[   93s]     |
[   93s]   'vis_operator': events 18-19
[   93s]     |
[   93s]     |vis-operators.c:267:18:
[   93s]     |  267 |   Macro *macro = macro_get(vis, VIS_REG_DOT);
[   93s]     |      |                  ^
[   93s]     |      |                  |
[   93s]     |      |                  (18) return of NULL to 'vis_operator' from 'macro_get'
[   93s]     |  268 |   macro_reset(macro);
[   93s]     |      |   ~               
[   93s]     |      |   |
[   93s]     |      |   (19) calling 'buffer_clear' from 'vis_operator'
[   93s]     |
[   93s]     +--> 'buffer_clear': events 20-21
[   93s]            |
[   93s]            |buffer.c:51:6:
[   93s]            |   51 | void buffer_clear(Buffer *buf) {
[   93s]            |      |      ^
[   93s]            |      |      |
[   93s]            |      |      (20) entry to 'buffer_clear'
[   93s]            |   52 |  buf->len = 0;
[   93s]            |      |           ~
[   93s]            |      |           |
[   93s]            |      |           (21) dereference of NULL 'buf_2(D)'
[   93s]            |
[   93s] vis-marks.c: In function 'buffer_reserve':
[   93s] buffer.c:21:9: warning: dereference of NULL 'buf_12(D)' [CWE-690] [-Wanalyzer-null-dereference]
[   93s]    21 |  if (buf->size < size) {
[   93s]       |         ^
[   93s]   'macro_operator_stop': events 1-4
[   93s]     |
[   93s]     |vis.c:1444:6:
[   93s]     | 1444 | void macro_operator_stop(Vis *vis) {
[   93s]     |      |      ^
[   93s]     |      |      |
[   93s]     |      |      (1) entry to 'macro_operator_stop'
[   93s]     | 1445 |  if (!vis->macro_operator)
[   93s]     |      |     ~ 
[   93s]     |      |     |
[   93s]     |      |     (2) following 'false' branch...
[   93s]     | 1446 |   return;
[   93s]     | 1447 |  Macro *dot = macro_get(vis, VIS_REG_DOT);
[   93s]     |      |               ~
[   93s]     |      |               |
[   93s]     |      |               (3) ...to here
[   93s]     |      |               (4) calling 'macro_get' from 'macro_operator_stop'
[   93s]     |
[   93s]     +--> 'macro_get': events 5-12
[   93s]            |
[   93s]            | 1427 | Macro *macro_get(Vis *vis, enum VisRegister id) {
[   93s]            |      |        ^
[   93s]            |      |        |
[   93s]            |      |        (5) entry to 'macro_get'
[   93s]            | 1428 |  if (id == VIS_MACRO_LAST_RECORDED)
[   93s]            |      |     ~   
[   93s]            |      |     |
[   93s]            |      |     (6) following 'false' branch (when 'id_5(D) != 74')...
[   93s]            | 1429 |   return vis->last_recording;
[   93s]            | 1430 |  if (VIS_REG_A <= id && id <= VIS_REG_Z)
[   93s]            |      |     ~   
[   93s]            |      |     |
[   93s]            |      |     (7) ...to here
[   93s]            |      |     (8) following 'false' branch (when 'id_5(D) <= 47')...
[   93s]            | 1431 |   id -= VIS_REG_A;
[   93s]            | 1432 |  if (id < LENGTH(vis->registers))
[   93s]            |      |     ~   
[   93s]            |      |     |
[   93s]            |      |     (9) ...to here
[   93s]            |      |     (10) following 'true' branch (when 'id_2 <= 46')...
[   93s]            | 1433 |   return array_get(&vis->registers[id].values, 0);
[   93s]            |      |          ~
[   93s]            |      |          |
[   93s]            |      |          (11) ...to here
[   93s]            |      |          (12) calling 'array_get' from 'macro_get'
[   93s]            |
[   93s]            +--> 'array_get': events 13-15
[   93s]                   |
[   93s]                   |array.c:58:7:
[   93s]                   |   58 | void *array_get(Array *arr, size_t idx) {
[   93s]                   |      |       ^
[   93s]                   |      |       |
[   93s]                   |      |       (13) entry to 'array_get'
[   93s]                   |   59 |  if (idx >= arr->len) {
[   93s]                   |      |     ~  
[   93s]                   |      |     |
[   93s]                   |      |     (14) following 'true' branch...
[   93s]                   |   60 |   errno = EINVAL;
[   93s]                   |      |   ~    
[   93s]                   |      |   |
[   93s]                   |      |   (15) ...to here
[   93s]                   |
[   93s]            <------+
[   93s]            |
[   93s]          'macro_get': event 16
[   93s]            |
[   93s]            |vis.c:1433:10:
[   93s]            | 1433 |   return array_get(&vis->registers[id].values, 0);
[   93s]            |      |          ^
[   93s]            |      |          |
[   93s]            |      |          (16) returning to 'macro_get' from 'array_get'
[   93s]            |
[   93s]          'macro_get': event 17
[   93s]            |
[   93s]            |lto1:
[   93s]            | (17): '<anonymous>' is NULL
[   93s]            |
[   93s]     <------+
[   93s]     |
[   93s]   'macro_operator_stop': events 18-19
[   93s]     |
[   93s]     | 1447 |  Macro *dot = macro_get(vis, VIS_REG_DOT);
[   93s]     |      |               ^
[   93s]     |      |               |
[   93s]     |      |               (18) return of NULL to 'macro_operator_stop' from 'macro_get'
[   93s]     | 1448 |  buffer_put(dot, vis->macro_operator->data, vis->macro_operator->len);
[   93s]     |      |  ~             
[   93s]     |      |  |
[   93s]     |      |  (19) calling 'buffer_put' from 'macro_operator_stop'
[   93s]     |
[   93s]     +--> 'buffer_put': events 20-21
[   93s]            |
[   93s]            |buffer.c:55:6:
[   93s]            |   55 | bool buffer_put(Buffer *buf, const void *data, size_t len) {
[   93s]            |      |      ^
[   93s]            |      |      |
[   93s]            |      |      (20) entry to 'buffer_put'
[   93s]            |   56 |  if (!buffer_reserve(buf, len))
[   93s]            |      |       ~
[   93s]            |      |       |
[   93s]            |      |       (21) calling 'buffer_reserve' from 'buffer_put'
[   93s]            |
[   93s]            +--> 'buffer_reserve': events 22-25
[   93s]                   |
[   93s]                   |   17 | bool buffer_reserve(Buffer *buf, size_t size) {
[   93s]                   |      |      ^
[   93s]                   |      |      |
[   93s]                   |      |      (22) entry to 'buffer_reserve'
[   93s]                   |   18 |  /* ensure minimal buffer size, to avoid repeated realloc(3) calls */
[   93s]                   |   19 |  if (size < BUFFER_SIZE)
[   93s]                   |      |     ~ 
[   93s]                   |      |     |
[   93s]                   |      |     (23) following 'false' branch (when 'size_9(D) > 1023')...
[   93s]                   |   20 |   size = BUFFER_SIZE;
[   93s]                   |   21 |  if (buf->size < size) {
[   93s]                   |      |         ~
[   93s]                   |      |         |
[   93s]                   |      |         (24) ...to here
[   93s]                   |      |         (25) dereference of NULL 'buf_12(D)'
[   93s]                   |
[   93s] make[1]: Leaving directory '/home/abuild/rpmbuild/BUILD/vis-0.6'

Full build log with all details.

martanne commented 4 years ago

Thanks, I briefly looked through non-NULL dereference results:

vis.c:172:2: warning: double-'free' of 'path_absolute_3' [CWE-415] [-Wanalyzer-double-free]

As mentioned on IRC, either I'm missing something or this is a false positive. It seems to report a "double free" of NULL?

For easier investigation, I created a minimal reproducer of the issue. The output states that both path_absolute and copy1 are NULL, but then concludes that there is a double free!?

map.c:189:10: warning: leak of 'map' [CWE-401] [-Wanalyzer-malloc-leak]

I don't really understand this either, a reference to the newly allocated map is stored in mode->bindings from where it is later freed when the mode is no longer used.

To summarize: unless my analysis is wrong, these seem to be false positives. I don't have time to investigate this further right now, we should check it again once the next GCC release is available.

mcepl commented 4 years ago

Yes, these could very well be false positives. I just wanted to make sure you see them and tell me that it is nonsense, than just to hold my tongue.