summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2015-09-13 11:44:13 -0400
committerMichael Cahill <michael.cahill@mongodb.com>2015-09-18 12:18:45 +1000
commit828b4fffb727a419360a631cdd392dad005ca5e8 (patch)
tree2b9a10933c45e2268a6f05a7466837c6ace82675
parentee5e284a71ba6b063bce8aacb1c29ed29e153879 (diff)
downloadmongo-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.c6
-rw-r--r--src/include/btree.i8
-rw-r--r--src/include/cell.i26
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);
}
/*