From 854c5f0aac03c7c6d7e1b37997dcdc848fec1499 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 May 2013 13:01:27 +0200 Subject: [PATCH] tdb: add overflow detection to tdb_expand_adjust() We round up at maximun to a new size of 4GB, but still return at least the given size. The caller has to deal with ENOSPC itself. Pair-Programmed-With: Volker Lendecke Signed-off-by: Stefan Metzmacher Signed-off-by: Volker Lendecke Reviewed-by: Rusty Russell --- lib/tdb/common/io.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/lib/tdb/common/io.c b/lib/tdb/common/io.c index d17764008f6..c9c9fa8dc93 100644 --- a/lib/tdb/common/io.c +++ b/lib/tdb/common/io.c @@ -363,14 +363,32 @@ static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t ad /* You need 'size', this tells you how much you should expand by. */ tdb_off_t tdb_expand_adjust(tdb_off_t map_size, tdb_off_t size, int page_size) { - tdb_off_t new_size, top_size; + tdb_off_t new_size, top_size, increment; + tdb_off_t max_size = UINT32_MAX - map_size; + + if (size > max_size) { + /* + * We can't round up anymore, just give back + * what we're asked for. + * + * The caller has to take care of the ENOSPC handling. + */ + return size; + } /* limit size in order to avoid using up huge amounts of memory for * in memory tdbs if an oddball huge record creeps in */ if (size > 100 * 1024) { - top_size = map_size + size * 2; + increment = size * 2; } else { - top_size = map_size + size * 100; + increment = size * 100; + } + if (increment < size) { + goto overflow; + } + + if (!tdb_add_off_t(map_size, increment, &top_size)) { + goto overflow; } /* always make room for at least top_size more records, and at @@ -381,10 +399,20 @@ tdb_off_t tdb_expand_adjust(tdb_off_t map_size, tdb_off_t size, int page_size) } else { new_size = map_size * 1.25; } + if (new_size < map_size) { + goto overflow; + } /* Round the database up to a multiple of the page size */ new_size = MAX(top_size, new_size); return TDB_ALIGN(new_size, page_size) - map_size; + +overflow: + /* + * Somewhere in between we went over 4GB. Make one big jump to + * exactly 4GB database size. + */ + return max_size; } /* expand the database at least size bytes by expanding the underlying -- 2.11.4.GIT