summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustorp.com.au>2010-06-10 13:27:51 -0700
committerJeremy Allison <jra@samba.org>2010-06-10 13:27:51 -0700
commitb53f8c187de8c8aff5989e4a0a460970f89b9011 (patch)
tree7f0fa2500047f31199931a23c10328ea6d859b2e /lib
parent321d7a6303b651cc2533f4b72dc7cef6b7d64da4 (diff)
downloadsamba-b53f8c187de8c8aff5989e4a0a460970f89b9011.tar.gz
samba-b53f8c187de8c8aff5989e4a0a460970f89b9011.tar.bz2
samba-b53f8c187de8c8aff5989e4a0a460970f89b9011.zip
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/util/idtree.c8
1 files changed, 5 insertions, 3 deletions
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;