Ncurses crashes programs on anything other than PuTTY

I have an older ncurses based program that performs a few simple I / O operations in multiple files (i.e.: installer). However, from a terminal other than PuTTY, it crashes with SIGBUS

Program received signal SIGBUS, Bus error. 0x00000000004028b1 in fDisplay (ptr=Variable "ptr" is not available. ) at file_cpy.c:676 676 sprintf(p, " %-36s ", (*ptr)->datainfo.option); (gdb) where #0 0x00000000004028b1 in fDisplay (ptr=Variable "ptr" is not available. ) at file_cpy.c:676 #1 0x0000000000402cdb in fredraw (c=0x7fffffffe860) at file_cpy.c:696 #2 0x0000000000401996 in ls_dispatch (c=0x2020202020202020) at ds_cell.c:324 #3 0x0000000000403bf2 in main_dir (c=0x2020202020202020) at file_cpy.c:811 #4 0x0000000000403cb3 in main () at file_cpy.c:1345 (gdb) x/i $pc 0x4028b1 <fDisplay+17>: mov (%rax),%rdx (gdb) 

This happens on Linux and FreeBSD, regardless of the ncurses version and 32/64-bit architecture. I am completely at a dead end.

fDisplay () is called here:

 /* * File redraw routine. Draws current list on screen. */ int fredraw (CELL * c) { register int row = c->srow; dlistptr p = c->list_start; int i = 0; char buff[200]; if (c->ecol - c->scol) sprintf(buff, "%*s",c->ecol - c->scol + 1, " "); while (i <= c->erow - c->srow && p != NULL) { if (p == c->current) wattron(c->window,A_REVERSE); mvaddstr (row , c->scol, fDisplay(&p)); if (p == c->current) wattroff(c->window,A_REVERSE); row++; i++; p = p->nextlistptr; } if (row <= c -> erow) for (; row <= c -> erow ; row++) mvaddstr(row, c->scol, buff); wrefresh(c->window); c -> redraw = FALSE; return TRUE; } 

This calls fredraw ():

 int main_dir(CELL *c) { int i; getcwd(current_path, sizeof(current_path)); strcat(current_path, "/.config.h"); load_file(current_path); c->keytable = file_cpy_menu; c->func_table = file_cpy_table; c->ListEntryProc = File_Entry; c->UpdateStatusProc = status_update; c->redraw = TRUE; c->ListExitProc = List_Exit; c->ListPaintProc = fredraw; c->srow = 3; c->scol = 1; c->erow = c->window->_maxy - 5; c->ecol = c->window->_maxx - 1; c->max_rows = c->window->_maxy; c->max_cols = c->window->_maxx; c->filename = "[ Config ]"; c->menu_bar = 0; c->normcolor = 0x07; c->barcolor = 0x1f; init_dlist(c); for (i = 0; config_type[i].option; i++) insert_fdlist(c, &config_type[i]); /* * Go Do It */ do { c->redraw = TRUE; ls_dispatch(c); } while (c->termkey != ESC && c->termkey != ALT_X); return TRUE; } 

Finally, main () calls the above functions:

 int main() { CELL file_cpy = {0}; WINDOW *mainwin; mainwin = initscr(); start_color(); setup_colors(); cbreak(); noecho(); keypad(mainwin, TRUE); meta(mainwin, TRUE); raw(); leaveok(mainwin, TRUE); wbkgd(mainwin, COLOR_PAIR(COLOR_MAIN)); wattron(mainwin, COLOR_PAIR(COLOR_MAIN)); werase(mainwin); refresh(); file_cpy.window = mainwin; main_dir(&file_cpy); wbkgd(mainwin, A_NORMAL); werase(mainwin); echo(); nocbreak(); noraw(); refresh(); endwin(); return TRUE; } 
+4
source share
1 answer

Apparently you are calling main_dir and ls_dispatch with pointer c initialized to 0x2020202020202020 . Although this is not entirely impossible, I find it very unlikely, and it looks like you are rewriting a pointer with spaces.

valgrind will probably help or do some kind of memory check or stack check.

Why it depends on the terminal, I could not say; there may be some TERM-specific code (for example, "select as many lines as there are on the screen"). In any case, this is not an error: it is only a condition that brings an error to the open. Such an error is usually caused by a wired constant, which sometimes exceeds the real value (in the example above, I could say โ€œselect 96 linesโ€, assuming that 96 lines will always be sufficient for everyone, while TERM with 100 lines suppresses the assumption and leads to overflow buffers).

It can also be a debugger artifact, seeing how c stands out on the stack (but I donโ€™t think so: it should be c=0x7fffsomething - at least on the systems where I checked). Anyway, I would repeat this test as follows: file_cpy dynamic dynamics:

 int main() { CELL *file_cpy = NULL; WINDOW *mainwin; file_cpy = malloc(sizeof(CELL)); ... file_cpy->window = mainwin; main_dir(file_cpy); ... free(file_cpy); // file_cpy = NULL; // we immediately return return TRUE; 

and then I will try to tabulate the pointer value in the whole main_dir function if it is overwritten.

+1
source

Source: https://habr.com/ru/post/1439046/


All Articles