shithub: riscv

Download patch

ref: 2a94e1fc1929746039edc5f2544dd472056cddcc
parent: a84c51a1e3c1e9c7ed8cdaf427cc790dc17854cb
author: cinap_lenrek <[email protected]>
date: Fri May 31 14:55:01 EDT 2013

pool: do poolcheck when free nodes get corrupted instead of assert

doing poolcheck should give us better context to figure out
what memory blocks / owners corrupted the blocks after free.

this is for hunting down a memory corruption seen in connection
with usb serial.

--- a/sys/src/libc/port/pool.c
+++ b/sys/src/libc/port/pool.c
@@ -159,7 +159,6 @@
 static void*	poolreallocl(Pool*, void*, ulong);
 static Free*	treedelete(Free*, Free*);
 static Free*	treeinsert(Free*, Free*);
-static Free*	treelookup(Free*, ulong);
 static Free*	treelookupgt(Free*, ulong);
 
 /*
@@ -230,30 +229,21 @@
 static Free**
 ltreewalk(Free **t, ulong size)
 {
-	assert(t != nil /* ltreewalk */);
+	Free *f;
 
 	for(;;) {
-		if(*t == nil)
+		f = *t;
+		if(f == nil || f->magic != FREE_MAGIC)
 			return t;
-
-		assert((*t)->magic == FREE_MAGIC);
-
-		if(size == (*t)->size)
+		if(size == f->size)
 			return t;
-		if(size < (*t)->size)
-			t = &(*t)->left;
+		if(size < f->size)
+			t = &f->left;
 		else
-			t = &(*t)->right;
+			t = &f->right;
 	}
 }
 
-/* treelookup: find node in tree with size == size */
-static Free*
-treelookup(Free *t, ulong size)
-{
-	return *ltreewalk(&t, size);
-}
-
 /* treeinsert: insert node into tree */
 static Free*
 treeinsert(Free *tree, Free *node)
@@ -263,11 +253,11 @@
 	assert(node != nil /* treeinsert */);
 
 	loc = ltreewalk(&tree, node->size);
-	if(*loc == nil) {
+	repl = *loc;
+	if(repl == nil || repl->magic != FREE_MAGIC) {
 		node->left = nil;
 		node->right = nil;
 	} else {	/* replace existing node */
-		repl = *loc;
 		node->left = repl->left;
 		node->right = repl->right;
 	}
@@ -284,7 +274,8 @@
 	assert(node != nil /* treedelete */);
 
 	loc = ltreewalk(&tree, node->size);
-	assert(*loc == node);
+	if(*loc != node || node->magic != FREE_MAGIC)
+		return tree;	/* free nodes corrupted */
 
 	if(node->left == nil)
 		*loc = node->right;
@@ -300,7 +291,6 @@
 		succ->right = node->right;
 		*loc = succ;
 	}
-
 	node->left = node->right = Poison;
 	return tree;
 }
@@ -313,7 +303,7 @@
 
 	lastgood = nil;
 	for(;;) {
-		if(t == nil)
+		if(t == nil || t->magic != FREE_MAGIC)
 			return lastgood;
 		if(size == t->size)
 			return t;
@@ -387,6 +377,11 @@
 	node->magic = FREE_MAGIC;
 	parent = ltreewalk(&p->freeroot, node->size);
 	olst = *parent;
+	if(olst != nil && olst->magic != FREE_MAGIC){
+		/* corruption of free nodes */
+		poolcheckl(p);
+		olst = *parent = nil;
+	}
 	lst = listadd(olst, node);
 	if(olst != lst)	/* need to update tree */
 		*parent = treeinsert(*parent, lst);
@@ -403,14 +398,17 @@
 
 	parent = ltreewalk(&p->freeroot, node->size);
 	olst = *parent;
-	assert(olst != nil /* pooldel */);
-
-	lst = listdelete(olst, node);
-	if(lst == nil)
-		*parent = treedelete(*parent, olst);
-	else if(lst != olst)
-		*parent = treeinsert(*parent, lst);
-
+	if(olst == nil || olst->magic != FREE_MAGIC){
+		/* corruption of free nodes */
+		poolcheckl(p);
+		*parent = nil;
+	} else {
+		lst = listdelete(olst, node);
+		if(lst == nil)
+			*parent = treedelete(*parent, olst);
+		else if(lst != olst)
+			*parent = treeinsert(*parent, lst);
+	}
 	node->left = node->right = Poison;
 	p->curfree -= node->size;