shithub: rio

Download patch

ref: 5ac6c1f2faef87d74d686546615332320ede3f14
parent: 7539ef43361f1579bd03b0b4007465adb8872aa0
author: glenda <glenda@cirno>
date: Sun Mar 23 07:08:56 EDT 2025

more defensive coding for history

--- a/wind.c
+++ b/wind.c
@@ -1411,11 +1411,13 @@
 	Rectangle r;
 
 	w = emalloc(sizeof(Window));
-	w->history = emalloc(w->maxhistory * sizeof(Rune*));
-	w->historylens = emalloc(w->maxhistory * sizeof(int));
 	w->nhistory = 0;
 	w->maxhistory = 100;
 	w->histpos = -1;
+	w->history = emalloc(w->maxhistory * sizeof(Rune*));
+	w->historylens = emalloc(w->maxhistory * sizeof(int));
+	for(int i = 0; i < w->maxhistory; i++)
+		w->history[i] = nil;
 	w->savedcmd = nil;
 	w->nsavedcmd = 0;
 	w->screenr = i->r;
@@ -1497,32 +1499,55 @@
 wclose(Window *w)
 {
 	int i;
-
+	static void *already_closing = nil;
+	
+	/* Prevent recursion */
+	if(w == already_closing)
+		return 0;
+		
 	i = decref(w);
 	if(i > 0)
 		return 0;
-	if(i < 0)
-		error("negative ref count");
+	if(i < 0) {
+		fprint(2, "rio: negative ref count in wclose\n");
+		i = 0;
+	}
 	
-	/* we might get receieve multiple close requests */
-	if(w->history) {
-		for(i = 0; i < w->nhistory; i++)
-			free(w->history[i]);
+	already_closing = w;
+	
+	if(w->history != nil) {
+		if(w->nhistory > 0 && w->nhistory <= w->maxhistory) {
+			for(i = 0; i < w->nhistory; i++) {
+				if(w->history[i] != nil) {
+					free(w->history[i]);
+					w->history[i] = nil;
+				}
+			}
+		}
 		free(w->history);
-		free(w->historylens);
 		w->history = nil;
-		w->historylens = nil;
+		
+		if(w->historylens != nil) {
+			free(w->historylens);
+			w->historylens = nil;
+		}
 		w->nhistory = 0;
+		w->maxhistory = 0;
 	}
 	
-	if(w->savedcmd) {
+	if(w->savedcmd != nil) {
 		free(w->savedcmd);
 		w->savedcmd = nil;
 		w->nsavedcmd = 0;
 	}
 	
+	w->histpos = -1;
+	
 	wclunk(w);
 	wsendctlmesg(w, Exited, ZR, nil);
+	
+	already_closing = nil;
+	
 	return 1;
 }
 
@@ -1541,6 +1566,16 @@
 wctlmesg(Window *w, int m, Rectangle r, void *p)
 {
 	Image *i = p;
+	Channel *mc = w->mc.c; 
+	Channel *ck = w->ck;
+	Channel *cctl = w->cctl;
+	Channel *conswrite = w->conswrite;
+	Channel *consread = w->consread;
+	Channel *mouseread = w->mouseread;
+	Channel *wctlread = w->wctlread;
+	Channel *kbdread = w->kbdread;
+	Channel *complete = w->complete;
+	Channel *gone = w->gone;
 
 	switch(m){
 	default:
@@ -1623,21 +1658,25 @@
 		flushimage(display, 1);
 		break;
 	case Exited:
+
+		
 		wclosewin(w);
 		frclear(w, TRUE);
 		flushimage(display, 1);
 		if(w->notefd >= 0)
 			close(w->notefd);
-		chanfree(w->mc.c);
-		chanfree(w->ck);
-		chanfree(w->cctl);
-		chanfree(w->conswrite);
-		chanfree(w->consread);
-		chanfree(w->mouseread);
-		chanfree(w->wctlread);
-		chanfree(w->kbdread);
-		chanfree(w->complete);
-		chanfree(w->gone);
+			
+		chanfree(mc);
+		chanfree(ck);
+		chanfree(cctl);
+		chanfree(conswrite);
+		chanfree(consread);
+		chanfree(mouseread);
+		chanfree(wctlread);
+		chanfree(kbdread);
+		chanfree(complete);
+		chanfree(gone);
+		
 		free(w->raw);
 		free(w->r);
 		free(w->dir);
@@ -1847,10 +1886,12 @@
 			if(wctlmesg(w, wcm.type, wcm.r, wcm.p) == Exited){
 				while(kbdqr != kbdqw)
 					free(kbdq[kbdqr++ % nelem(kbdq)]);
+				
 				chanfree(crm.c1);
 				chanfree(crm.c2);
 				chanfree(mrm.cm);
 				chanfree(cwm.cw);
+			
 				threadexits(nil);
 			}
 			continue;