diff options
author | Rusty Russell <rusty@rustorp.com.au> | 2010-06-10 13:27:51 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2010-06-10 13:27:51 -0700 |
commit | b53f8c187de8c8aff5989e4a0a460970f89b9011 (patch) | |
tree | 7f0fa2500047f31199931a23c10328ea6d859b2e /lib/util | |
parent | 321d7a6303b651cc2533f4b72dc7cef6b7d64da4 (diff) | |
download | samba-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/util')
-rw-r--r-- | lib/util/idtree.c | 8 |
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; |