panelreel: fix some NULL dereferences

ncurses getbegy() and friends, as it turns out, check for
a NULL input and return -1. we've been blindly passing
NULL in a few places on the ncurses side--with its own
problems--but that rapidly led to crashes here.
This commit is contained in:
nick black 2019-12-03 03:21:51 -05:00
parent f7437d2e68
commit 35badf8ae7
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
2 changed files with 35 additions and 27 deletions

View File

@ -240,7 +240,7 @@ handle_input(struct notcurses* nc, struct panelreel* pr, int efd,
static struct panelreel* static struct panelreel*
panelreel_demo_core(struct notcurses* nc, int efd, tabletctx** tctxs){ panelreel_demo_core(struct notcurses* nc, int efd, tabletctx** tctxs){
bool done = false; bool done = false;
int x = 8, y = 8; int x = 8, y = 4;
panelreel_options popts = { panelreel_options popts = {
.infinitescroll = true, .infinitescroll = true,
.circular = true, .circular = true,

View File

@ -228,16 +228,16 @@ panelreel_draw_tablet(const panelreel* pr, tablet* t, int frontiery,
ncplane* fp = t->p; ncplane* fp = t->p;
if(tablet_columns(pr, &begx, &begy, &lenx, &leny, frontiery, direction)){ if(tablet_columns(pr, &begx, &begy, &lenx, &leny, frontiery, direction)){
//fprintf(stderr, "no room: %p:%p base %d/%d len %d/%d\n", t, fp, begx, begy, lenx, leny); //fprintf(stderr, "no room: %p:%p base %d/%d len %d/%d\n", t, fp, begx, begy, lenx, leny);
// fprintf(stderr, "FRONTIER DONE!!!!!!\n"); //fprintf(stderr, "FRONTIER DONE!!!!!!\n");
if(fp){ if(fp){
// fprintf(stderr, "HIDING %p at frontier %d (dir %d) with %d\n", t, frontiery, direction, leny); //fprintf(stderr, "HIDING %p at frontier %d (dir %d) with %d\n", t, frontiery, direction, leny);
ncplane_destroy(fp); ncplane_destroy(fp);
t->p = NULL; t->p = NULL;
} }
return -1; return -1;
} }
// fprintf(stderr, "tplacement: %p:%p base %d/%d len %d/%d\n", t, fp, begx, begy, lenx, leny); //fprintf(stderr, "tplacement: %p:%p base %d/%d len %d/%d\n", t, fp, begx, begy, lenx, leny);
// fprintf(stderr, "DRAWING %p at frontier %d (dir %d) with %d\n", t, frontiery, direction, leny); //fprintf(stderr, "DRAWING %p at frontier %d (dir %d) with %d\n", t, frontiery, direction, leny);
if(fp == NULL){ // create a panel for the tablet if(fp == NULL){ // create a panel for the tablet
t->p = notcurses_newplane(pr->p->nc, leny + 1, lenx, begy, begx, NULL); t->p = notcurses_newplane(pr->p->nc, leny + 1, lenx, begy, begx, NULL);
if((fp = t->p) == NULL){ if((fp = t->p) == NULL){
@ -346,14 +346,22 @@ draw_focused_tablet(const panelreel* pr){
int dontcarex; int dontcarex;
ncplane_yx(pr->tablets->p, &fulcrum, &dontcarex); ncplane_yx(pr->tablets->p, &fulcrum, &dontcarex);
// FIXME ugh can't we just remember the previous fulcrum? // FIXME ugh can't we just remember the previous fulcrum?
int prevfulcrum; if(pr->last_traveled_direction > 0){
ncplane_yx(pr->tablets->prev->p, &prevfulcrum, &dontcarex); if(pr->tablets->prev->p){
int nextfulcrum; int prevfulcrum;
ncplane_yx(pr->tablets->next->p, &nextfulcrum, &dontcarex); ncplane_yx(pr->tablets->prev->p, &prevfulcrum, &dontcarex);
if(pr->last_traveled_direction > 0 && fulcrum < prevfulcrum){ if(fulcrum < prevfulcrum){
fulcrum = pleny + pbegy - !(pr->popts.bordermask & BORDERMASK_BOTTOM); fulcrum = pleny + pbegy - !(pr->popts.bordermask & BORDERMASK_BOTTOM);
}else if(pr->last_traveled_direction < 0 && fulcrum > nextfulcrum){ }
fulcrum = pbegy + !(pr->popts.bordermask & BORDERMASK_TOP); }
}else if(pr->last_traveled_direction < 0){
if(pr->tablets->next->p){
int nextfulcrum;
ncplane_yx(pr->tablets->next->p, &nextfulcrum, &dontcarex);
if(fulcrum > nextfulcrum){
fulcrum = pbegy + !(pr->popts.bordermask & BORDERMASK_TOP);
}
}
} }
} }
//fprintf(stderr, "PR dims: %d/%d + %d/%d fulcrum: %d\n", pbegy, pbegx, pleny, plenx, fulcrum); //fprintf(stderr, "PR dims: %d/%d + %d/%d fulcrum: %d\n", pbegy, pbegx, pleny, plenx, fulcrum);
@ -393,14 +401,16 @@ draw_previous_tablets(const panelreel* pr, const tablet* otherend){
int frontiery; int frontiery;
while(upworking->prev != otherend || otherend->p == NULL){ while(upworking->prev != otherend || otherend->p == NULL){
window_coordinates(upworking->p, &wbegy, &wbegx, &wleny, &wlenx); window_coordinates(upworking->p, &wbegy, &wbegx, &wleny, &wlenx);
//fprintf(stderr, "MOVIN' ON UP: %d %d\n", frontiery, wbegy - 2);
frontiery = wbegy - 2; frontiery = wbegy - 2;
//fprintf(stderr, "MOVIN' ON UP: %d %d\n", frontiery, wbegy - 2);
upworking = upworking->prev; upworking = upworking->prev;
panelreel_draw_tablet(pr, upworking, frontiery, -1); panelreel_draw_tablet(pr, upworking, frontiery, -1);
if(upworking->p){ if(upworking->p){
window_coordinates(upworking->p, &wbegy, &wbegx, &wleny, &wlenx); window_coordinates(upworking->p, &wbegy, &wbegx, &wleny, &wlenx);
//fprintf(stderr, "new up coords: %d/%d + %d/%d, %d\n", wbegy, wbegx, wleny, wlenx, frontiery); //fprintf(stderr, "new up coords: %d/%d + %d/%d, %d\n", wbegy, wbegx, wleny, wlenx, frontiery);
frontiery = wbegy - 2; frontiery = wbegy - 2;
}else{
break;
} }
if(upworking == otherend){ if(upworking == otherend){
otherend = otherend->prev; otherend = otherend->prev;
@ -435,6 +445,7 @@ find_topmost(panelreel* pr){
// good god almighty, this is some fucking garbage. // good god almighty, this is some fucking garbage.
static int static int
panelreel_arrange_denormalized(panelreel* pr){ panelreel_arrange_denormalized(panelreel* pr){
//fprintf(stderr, "denormalized devolution (are we men?)\n");
// we'll need the starting line of the tablet which just lost focus, and the // we'll need the starting line of the tablet which just lost focus, and the
// starting line of the tablet which just gained focus. // starting line of the tablet which just gained focus.
int fromline, nowline; int fromline, nowline;
@ -460,7 +471,7 @@ panelreel_arrange_denormalized(panelreel* pr){
topmost = topmost->prev; topmost = topmost->prev;
} }
} }
// fprintf(stderr, "gotta draw 'em all FROM: %d NOW: %d!\n", fromline, nowline); //fprintf(stderr, "gotta draw 'em all FROM: %d NOW: %d!\n", fromline, nowline);
tablet* t = topmost; tablet* t = topmost;
do{ do{
int broken; int broken;
@ -490,12 +501,17 @@ panelreel_arrange_denormalized(panelreel* pr){
// focus, if we're not filling out the reel. // focus, if we're not filling out the reel.
// //
// This can still leave a gap plus a partially-onscreen tablet FIXME // This can still leave a gap plus a partially-onscreen tablet FIXME
static int int panelreel_redraw(panelreel* pr){
panelreel_arrange(panelreel* pr){ //fprintf(stderr, "--------> BEGIN REDRAW <--------\n");
if(draw_panelreel_borders(pr)){
return -1; // enforces specified dimensional minima
}
tablet* focused = pr->tablets; tablet* focused = pr->tablets;
if(focused == NULL){ if(focused == NULL){
//fprintf(stderr, "no focus!\n");
return 0; // if none are focused, none exist return 0; // if none are focused, none exist
} }
//fprintf(stderr, "focused %p!\n", focused);
// FIXME we special-cased this because i'm dumb and couldn't think of a more // FIXME we special-cased this because i'm dumb and couldn't think of a more
// elegant way to do this. we keep 'all_visible' as boolean state to avoid // elegant way to do this. we keep 'all_visible' as boolean state to avoid
// having to do an o(n) iteration each round, but this is still grotesque, and // having to do an o(n) iteration each round, but this is still grotesque, and
@ -503,7 +519,9 @@ panelreel_arrange(panelreel* pr){
if(pr->all_visible){ if(pr->all_visible){
return panelreel_arrange_denormalized(pr); return panelreel_arrange_denormalized(pr);
} }
//fprintf(stderr, "drawing focused tablet %p dir: %d!\n", focused, pr->last_traveled_direction);
draw_focused_tablet(pr); draw_focused_tablet(pr);
//fprintf(stderr, "drew focused tablet %p dir: %d!\n", focused, pr->last_traveled_direction);
tablet* otherend = focused; tablet* otherend = focused;
if(pr->last_traveled_direction >= 0){ if(pr->last_traveled_direction >= 0){
otherend = draw_previous_tablets(pr, otherend); otherend = draw_previous_tablets(pr, otherend);
@ -517,16 +535,6 @@ panelreel_arrange(panelreel* pr){
return 0; return 0;
} }
int panelreel_redraw(panelreel* pr){
//fprintf(stderr, "--------> BEGIN REDRAW <--------\n");
int ret = 0;
if(draw_panelreel_borders(pr)){
return -1; // enforces specified dimensional minima
}
ret |= panelreel_arrange(pr);
return ret;
}
static bool static bool
validate_panelreel_opts(ncplane* w, const panelreel_options* popts){ validate_panelreel_opts(ncplane* w, const panelreel_options* popts){
if(w == NULL){ if(w == NULL){