summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Gorrod <alexander.gorrod@mongodb.com>2015-07-21 10:56:10 +1000
committerMichael Cahill <michael.cahill@mongodb.com>2015-08-04 14:41:03 +1000
commitdc059f27e99dad651adc26155cc73ab54a3d2807 (patch)
tree3ec0f0d65cdfecf6003458a786a4c3fd7ba3d4ff
parentc02a9f3c8af6348af59d77f505c7117d4ff5e0a3 (diff)
downloadmongo-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.c12
-rw-r--r--src/include/extern.h2
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);