diff options
author | Keith Bostic <keith@wiredtiger.com> | 2015-09-13 11:44:13 -0400 |
---|---|---|
committer | Michael Cahill <michael.cahill@mongodb.com> | 2015-09-18 12:18:45 +1000 |
commit | 828b4fffb727a419360a631cdd392dad005ca5e8 (patch) | |
tree | 2b9a10933c45e2268a6f05a7466837c6ace82675 | |
parent | ee5e284a71ba6b063bce8aacb1c29ed29e153879 (diff) | |
download | mongo-828b4fffb727a419360a631cdd392dad005ca5e8.tar.gz |
WT-2105: If a corrupted WT_CELL_VALUE_COPY cell has an offset larger
than the current cell's offset in the page, we'll read memory outside
of the page image.
(cherry picked from commit 0e96683fc65845c015ed6ee7249ea1d9c3c9a67e)
-rw-r--r-- | src/btree/bt_vrfy_dsk.c | 6 | ||||
-rw-r--r-- | src/include/btree.i | 8 | ||||
-rw-r--r-- | src/include/cell.i | 26 |
3 files changed, 21 insertions, 19 deletions
diff --git a/src/btree/bt_vrfy_dsk.c b/src/btree/bt_vrfy_dsk.c index d6c300d200a..dbaf18c69f2 100644 --- a/src/btree/bt_vrfy_dsk.c +++ b/src/btree/bt_vrfy_dsk.c @@ -218,7 +218,7 @@ __verify_dsk_row( ++cell_num; /* Carefully unpack the cell. */ - if (__wt_cell_unpack_safe(cell, unpack, end) != 0) { + if (__wt_cell_unpack_safe(cell, unpack, dsk, end) != 0) { ret = __err_cell_corrupted(session, cell_num, addr); goto err; } @@ -485,7 +485,7 @@ __verify_dsk_col_int( ++cell_num; /* Carefully unpack the cell. */ - if (__wt_cell_unpack_safe(cell, unpack, end) != 0) + if (__wt_cell_unpack_safe(cell, unpack, dsk, end) != 0) return (__err_cell_corrupted(session, cell_num, addr)); /* Check the raw and collapsed cell types. */ @@ -552,7 +552,7 @@ __verify_dsk_col_var( ++cell_num; /* Carefully unpack the cell. */ - if (__wt_cell_unpack_safe(cell, unpack, end) != 0) + if (__wt_cell_unpack_safe(cell, unpack, dsk, end) != 0) return (__err_cell_corrupted(session, cell_num, addr)); /* Check the raw and collapsed cell types. */ diff --git a/src/include/btree.i b/src/include/btree.i index 20aa35c2fb9..5db6ff1f002 100644 --- a/src/include/btree.i +++ b/src/include/btree.i @@ -85,8 +85,8 @@ __wt_cache_decr_check_size( first = 0; } #else - WT_UNUSED(fld); - WT_UNUSED(session); + WT_UNUSED(fld); + WT_UNUSED(session); #endif } @@ -113,8 +113,8 @@ __wt_cache_decr_check_uint64( first = 0; } #else - WT_UNUSED(fld); - WT_UNUSED(session); + WT_UNUSED(fld); + WT_UNUSED(session); #endif } diff --git a/src/include/cell.i b/src/include/cell.i index 77e9fa1e3c1..880e4e2402f 100644 --- a/src/include/cell.i +++ b/src/include/cell.i @@ -547,7 +547,8 @@ __wt_cell_leaf_value_parse(WT_PAGE *page, WT_CELL *cell) * Unpack a WT_CELL into a structure during verification. */ static inline int -__wt_cell_unpack_safe(WT_CELL *cell, WT_CELL_UNPACK *unpack, uint8_t *end) +__wt_cell_unpack_safe( + WT_CELL *cell, WT_CELL_UNPACK *unpack, const void *start, const void *end) { uint64_t saved_v, v; uint32_t saved_len; @@ -559,14 +560,15 @@ __wt_cell_unpack_safe(WT_CELL *cell, WT_CELL_UNPACK *unpack, uint8_t *end) saved_v = 0; /* - * The verification code specifies an end argument, a pointer to 1 past - * the end-of-page. In that case, make sure we don't go past the end - * of the page when reading. If an error occurs, we simply return the - * error code, the verification code takes care of complaining (and, in - * the case of salvage, it won't complain at all, it's OK to fail). + * The verification code specifies start/end arguments, pointers to the + * start of the page and to 1 past the end-of-page. In which case, make + * sure all reads are inside the page image. If an error occurs, return + * an error code but don't output messages, our caller handles that. */ -#define WT_CELL_LEN_CHK(p, len) do { \ - if (end != NULL && (((uint8_t *)p) + (len)) > end) \ +#define WT_CELL_LEN_CHK(t, len) do { \ + if (start != NULL && \ + ((uint8_t *)t < (uint8_t *)start || \ + (((uint8_t *)t) + (len)) > (uint8_t *)end)) \ return (WT_ERROR); \ } while (0) @@ -620,7 +622,7 @@ restart: */ if (cell->__chunk[0] & WT_CELL_64V) /* skip value */ WT_RET(__wt_vunpack_uint( - &p, end == NULL ? 0 : (size_t)(end - p), &unpack->v)); + &p, end == NULL ? 0 : WT_PTRDIFF(end, p), &unpack->v)); /* * Handle special actions for a few different cell types and set the @@ -637,7 +639,7 @@ restart: * earlier cell. */ WT_RET(__wt_vunpack_uint( - &p, end == NULL ? 0 : (size_t)(end - p), &v)); + &p, end == NULL ? 0 : WT_PTRDIFF(end, p), &v)); saved_len = WT_PTRDIFF32(p, cell); saved_v = unpack->v; cell = (WT_CELL *)((uint8_t *)cell - v); @@ -666,7 +668,7 @@ restart: * data. */ WT_RET(__wt_vunpack_uint( - &p, end == NULL ? 0 : (size_t)(end - p), &v)); + &p, end == NULL ? 0 : WT_PTRDIFF(end, p), &v)); if (unpack->raw == WT_CELL_KEY || unpack->raw == WT_CELL_KEY_PFX || @@ -707,7 +709,7 @@ done: WT_CELL_LEN_CHK(cell, unpack->__len); static inline void __wt_cell_unpack(WT_CELL *cell, WT_CELL_UNPACK *unpack) { - (void)__wt_cell_unpack_safe(cell, unpack, NULL); + (void)__wt_cell_unpack_safe(cell, unpack, NULL, NULL); } /* |