From: Paolo Bonzini <pbonz...@redhat.com> hbitmap_iter_init causes an out-of-bounds access when the "first" argument is or greater than or equal to the size of the bitmap. Forbid this with an assertion, and remove the failing testcase.
Reported-by: Kevin Wolf <kw...@redhat.com> Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> Reviewed-by: Eric Blake <ebl...@redhat.com> Reviewed-by: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Kevin Wolf <kw...@redhat.com> --- include/qemu/hbitmap.h | 3 ++- tests/test-hbitmap.c | 13 +++---------- util/hbitmap.c | 1 + 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h index 7ddfb66..73f5d1d 100644 --- a/include/qemu/hbitmap.h +++ b/include/qemu/hbitmap.h @@ -128,7 +128,8 @@ void hbitmap_free(HBitmap *hb); * hbitmap_iter_init: * @hbi: HBitmapIter to initialize. * @hb: HBitmap to iterate on. - * @first: First bit to visit (0-based). + * @first: First bit to visit (0-based, must be strictly less than the + * size of the bitmap). * * Set up @hbi to iterate on the HBitmap @hb. hbitmap_iter_next will return * the lowest-numbered bit that is set in @hb, starting at @first. diff --git a/tests/test-hbitmap.c b/tests/test-hbitmap.c index fcc6a00..8c902f2 100644 --- a/tests/test-hbitmap.c +++ b/tests/test-hbitmap.c @@ -86,7 +86,9 @@ static void hbitmap_test_init(TestHBitmapData *data, data->bits = g_new0(unsigned long, n); data->size = size; data->granularity = granularity; - hbitmap_test_check(data, 0); + if (size) { + hbitmap_test_check(data, 0); + } } static void hbitmap_test_teardown(TestHBitmapData *data, @@ -198,14 +200,6 @@ static void test_hbitmap_iter_partial(TestHBitmapData *data, hbitmap_test_check(data, L3 / 2); } -static void test_hbitmap_iter_past(TestHBitmapData *data, - const void *unused) -{ - hbitmap_test_init(data, L3, 0); - hbitmap_test_set(data, 0, L3); - hbitmap_test_check(data, L3); -} - static void test_hbitmap_set_all(TestHBitmapData *data, const void *unused) { @@ -388,7 +382,6 @@ int main(int argc, char **argv) hbitmap_test_add("/hbitmap/size/0", test_hbitmap_zero); hbitmap_test_add("/hbitmap/size/unaligned", test_hbitmap_unaligned); hbitmap_test_add("/hbitmap/iter/empty", test_hbitmap_iter_empty); - hbitmap_test_add("/hbitmap/iter/past", test_hbitmap_iter_past); hbitmap_test_add("/hbitmap/iter/partial", test_hbitmap_iter_partial); hbitmap_test_add("/hbitmap/iter/granularity", test_hbitmap_iter_granularity); hbitmap_test_add("/hbitmap/get/all", test_hbitmap_get_all); diff --git a/util/hbitmap.c b/util/hbitmap.c index fb7e01e..2aa487d 100644 --- a/util/hbitmap.c +++ b/util/hbitmap.c @@ -147,6 +147,7 @@ void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first) hbi->hb = hb; pos = first >> hb->granularity; + assert(pos < hb->size); hbi->pos = pos >> BITS_PER_LEVEL; hbi->granularity = hb->granularity; -- 1.7.6.5