diff options
author | Stefan Metzmacher <metze@samba.org> | 2013-05-28 13:01:27 +0200 |
---|---|---|
committer | Volker Lendecke <vl@samba.org> | 2013-06-03 10:21:28 +0200 |
commit | 854c5f0aac03c7c6d7e1b37997dcdc848fec1499 (patch) | |
tree | 6c83492bdef9a447149748ed33ce58b2aa1c720c | |
parent | e19d46f7e31a32e2b5ae3ec05e13f32b8ac2109d (diff) | |
download | samba-854c5f0aac03c7c6d7e1b37997dcdc848fec1499.tar.gz samba-854c5f0aac03c7c6d7e1b37997dcdc848fec1499.tar.bz2 samba-854c5f0aac03c7c6d7e1b37997dcdc848fec1499.zip |
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 <vl@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | lib/tdb/common/io.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/lib/tdb/common/io.c b/lib/tdb/common/io.c index d17764008f..c9c9fa8dc9 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 |