From b53f8c187de8c8aff5989e4a0a460970f89b9011 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 10 Jun 2010 13:27:51 -0700 Subject: Since idtree assigns sequentially, it rarely reaches high numbers. But such numbers can be forced with idr_get_new_above(), and that reveals two bugs: 1) Crash in sub_remove() caused by pa array being too short. 2) Shift by more than 32 in _idr_find(), which is undefined, causing the "outside the current tree" optimization to misfire and return NULL. --- lib/util/idtree.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/util') diff --git a/lib/util/idtree.c b/lib/util/idtree.c index 0af93a229d..c14796101a 100644 --- a/lib/util/idtree.c +++ b/lib/util/idtree.c @@ -240,7 +240,7 @@ build_up: static int sub_remove(struct idr_context *idp, int shift, int id) { struct idr_layer *p = idp->top; - struct idr_layer **pa[MAX_LEVEL]; + struct idr_layer **pa[1+MAX_LEVEL]; struct idr_layer ***paa = &pa[0]; int n; @@ -280,8 +280,10 @@ static void *_idr_find(struct idr_context *idp, int id) * This tests to see if bits outside the current tree are * present. If so, tain't one of ours! */ - if ((id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS)) - return NULL; + if (n + IDR_BITS < 31 && + ((id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS))) { + return NULL; + } /* Mask off upper bits we don't use for the search. */ id &= MAX_ID_MASK; -- cgit