diff options
author | Volker Lendecke <vl@samba.org> | 2015-07-18 21:50:55 +0200 |
---|---|---|
committer | Ralph Böhme <slow@samba.org> | 2015-07-20 23:18:23 +0200 |
commit | 64a88f74ca5309dce1d3ec0755ceba4af5144dbd (patch) | |
tree | 13297452ff8f6745fa53779a2c4fd16e3ccb4d92 | |
parent | d87877251a553ac60f314ebe435ec33f46fb6b98 (diff) | |
download | samba-64a88f74ca5309dce1d3ec0755ceba4af5144dbd.tar.gz |
dbwrap_rbt: Make "key" and "value" aligned to 16 byte
Reported by Uri Simchoni <urisimchoni@gmail.com>. Thanks!
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Autobuild-User(master): Ralph Böhme <slow@samba.org>
Autobuild-Date(master): Mon Jul 20 23:18:23 CEST 2015 on sn-devel-104
-rw-r--r-- | lib/dbwrap/dbwrap_rbt.c | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/lib/dbwrap/dbwrap_rbt.c b/lib/dbwrap/dbwrap_rbt.c index 3f970865982..03f2f576256 100644 --- a/lib/dbwrap/dbwrap_rbt.c +++ b/lib/dbwrap/dbwrap_rbt.c @@ -38,13 +38,6 @@ struct db_rbt_rec { struct db_rbt_node { struct rb_node rb_node; size_t keysize, valuesize; - - /* - * key and value are appended implicitly, "data" is only here as a - * target for offsetof() - */ - - char data[1]; }; /* @@ -83,12 +76,43 @@ static int db_rbt_compare(TDB_DATA a, TDB_DATA b) static void db_rbt_parse_node(struct db_rbt_node *node, TDB_DATA *key, TDB_DATA *value) { - key->dptr = ((uint8_t *)node) + offsetof(struct db_rbt_node, data); + size_t key_offset, value_offset; + + key_offset = DBWRAP_RBT_ALIGN(sizeof(struct db_rbt_node)); + key->dptr = ((uint8_t *)node) + key_offset; key->dsize = node->keysize; - value->dptr = key->dptr + node->keysize; + + value_offset = DBWRAP_RBT_ALIGN(node->keysize); + value->dptr = key->dptr + value_offset; value->dsize = node->valuesize; } +static ssize_t db_rbt_reclen(size_t keylen, size_t valuelen) +{ + size_t len, tmp; + + len = DBWRAP_RBT_ALIGN(sizeof(struct db_rbt_node)); + + tmp = DBWRAP_RBT_ALIGN(keylen); + if (tmp < keylen) { + goto overflow; + } + + len += tmp; + if (len < tmp) { + goto overflow; + } + + len += valuelen; + if (len < valuelen) { + goto overflow; + } + + return len; +overflow: + return -1; +} + static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag) { struct db_rbt_ctx *db_ctx = talloc_get_type_abort( @@ -99,6 +123,7 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag) struct rb_node ** p; struct rb_node * parent; + ssize_t reclen; TDB_DATA this_key, this_val; if (rec_priv->node != NULL) { @@ -123,10 +148,12 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag) } } - node = (struct db_rbt_node *)talloc_size(db_ctx, - offsetof(struct db_rbt_node, data) + rec->key.dsize - + data.dsize); + reclen = db_rbt_reclen(rec->key.dsize, data.dsize); + if (reclen == -1) { + return NT_STATUS_INSUFFICIENT_RESOURCES; + } + node = talloc_size(db_ctx, reclen); if (node == NULL) { return NT_STATUS_NO_MEMORY; } |