diff options
author | Alex Gorrod <alexander.gorrod@mongodb.com> | 2015-07-21 10:56:10 +1000 |
---|---|---|
committer | Michael Cahill <michael.cahill@mongodb.com> | 2015-08-04 14:41:03 +1000 |
commit | dc059f27e99dad651adc26155cc73ab54a3d2807 (patch) | |
tree | 3ec0f0d65cdfecf6003458a786a4c3fd7ba3d4ff | |
parent | c02a9f3c8af6348af59d77f505c7117d4ff5e0a3 (diff) | |
download | mongo-dc059f27e99dad651adc26155cc73ab54a3d2807.tar.gz |
Merge pull request #2069 from wiredtiger/rewrite-err-use-after-free
WT-1996 If there is an error applying updates during a page rewrite, don't free the first update
(cherry picked from commit f8dc12bead0d8b3ea05144599d2ab218e5fbdb9a)
-rw-r--r-- | src/btree/row_modify.c | 12 | ||||
-rw-r--r-- | src/include/extern.h | 2 |
2 files changed, 8 insertions, 6 deletions
diff --git a/src/btree/row_modify.c b/src/btree/row_modify.c index d56b44bbd95..f0a10cdf528 100644 --- a/src/btree/row_modify.c +++ b/src/btree/row_modify.c @@ -47,13 +47,13 @@ __wt_page_modify_alloc(WT_SESSION_IMPL *session, WT_PAGE *page) */ int __wt_row_modify(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, - WT_ITEM *key, WT_ITEM *value, WT_UPDATE *upd, int is_remove) + WT_ITEM *key, WT_ITEM *value, WT_UPDATE *upd_arg, int is_remove) { WT_DECL_RET; WT_INSERT *ins; WT_INSERT_HEAD *ins_head, **ins_headp; WT_PAGE *page; - WT_UPDATE *old_upd, **upd_entry; + WT_UPDATE *old_upd, *upd, **upd_entry; size_t ins_size, upd_size; uint32_t ins_slot; u_int i, skipdepth; @@ -61,6 +61,7 @@ __wt_row_modify(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, ins = NULL; page = cbt->ref->page; + upd = upd_arg; logged = 0; /* This code expects a remove to have a NULL value. */ @@ -90,7 +91,7 @@ __wt_row_modify(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, } else upd_entry = &cbt->ins->upd; - if (upd == NULL) { + if (upd_arg == NULL) { /* Make sure the update can proceed. */ WT_ERR(__wt_txn_update_check( session, old_upd = *upd_entry)); @@ -165,7 +166,7 @@ __wt_row_modify(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, cbt->ins_head = ins_head; cbt->ins = ins; - if (upd == NULL) { + if (upd_arg == NULL) { WT_ERR( __wt_update_alloc(session, value, &upd, &upd_size)); WT_ERR(__wt_txn_modify(session, upd)); @@ -218,7 +219,8 @@ err: /* __wt_txn_unmodify(session); __wt_free(session, ins); cbt->ins = NULL; - __wt_free(session, upd); + if (upd_arg == NULL) + __wt_free(session, upd); } return (ret); diff --git a/src/include/extern.h b/src/include/extern.h index 530a84014ab..774e3b445ff 100644 --- a/src/include/extern.h +++ b/src/include/extern.h @@ -171,7 +171,7 @@ extern int __wt_row_ikey_alloc(WT_SESSION_IMPL *session, uint32_t cell_offset, c extern int __wt_row_ikey_incr(WT_SESSION_IMPL *session, WT_PAGE *page, uint32_t cell_offset, const void *key, size_t size, WT_REF *ref); extern int __wt_row_ikey(WT_SESSION_IMPL *session, uint32_t cell_offset, const void *key, size_t size, WT_REF *ref); extern int __wt_page_modify_alloc(WT_SESSION_IMPL *session, WT_PAGE *page); -extern int __wt_row_modify(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, WT_ITEM *key, WT_ITEM *value, WT_UPDATE *upd, int is_remove); +extern int __wt_row_modify(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, WT_ITEM *key, WT_ITEM *value, WT_UPDATE *upd_arg, int is_remove); extern int __wt_row_insert_alloc(WT_SESSION_IMPL *session, WT_ITEM *key, u_int skipdepth, WT_INSERT **insp, size_t *ins_sizep); extern int __wt_update_alloc( WT_SESSION_IMPL *session, WT_ITEM *value, WT_UPDATE **updp, size_t *sizep); extern WT_UPDATE *__wt_update_obsolete_check( WT_SESSION_IMPL *session, WT_PAGE *page, WT_UPDATE *upd); |