[RFC PATCH 13/23] vinyl: fix potential use-after-free in vy_read_view_merge
Vladimir Davydov
vdavydov.dev at gmail.com
Sun Jul 8 19:48:44 MSK 2018
If is_first_insert flag is set and vy_stmt_type(rv->tuple) equals
IPROTO_DELETE, we free rv->tuple, but then we dereference it via
an on-stack variable to check if we need to turn a REPLACE into an
INSERT or vice versa. Fix this.
---
src/box/vy_write_iterator.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/box/vy_write_iterator.c b/src/box/vy_write_iterator.c
index 7d2ec955..4e758be8 100644
--- a/src/box/vy_write_iterator.c
+++ b/src/box/vy_write_iterator.c
@@ -792,8 +792,7 @@ vy_read_view_merge(struct vy_write_iterator *stream, struct tuple *hint,
/* Not the first statement. */
return 0;
}
- struct tuple *tuple = rv->tuple;
- if (is_first_insert && vy_stmt_type(tuple) == IPROTO_DELETE) {
+ if (is_first_insert && vy_stmt_type(rv->tuple) == IPROTO_DELETE) {
/*
* Optimization 6: discard the first DELETE if
* the oldest statement for the current key among
@@ -801,11 +800,12 @@ vy_read_view_merge(struct vy_write_iterator *stream, struct tuple *hint,
* statements for this key in older runs or the
* last statement is a DELETE.
*/
- vy_stmt_unref_if_possible(tuple);
+ vy_stmt_unref_if_possible(rv->tuple);
rv->tuple = NULL;
- }
- if ((is_first_insert && vy_stmt_type(tuple) == IPROTO_REPLACE) ||
- (!is_first_insert && vy_stmt_type(tuple) == IPROTO_INSERT)) {
+ } else if ((is_first_insert &&
+ vy_stmt_type(rv->tuple) == IPROTO_REPLACE) ||
+ (!is_first_insert &&
+ vy_stmt_type(rv->tuple) == IPROTO_INSERT)) {
/*
* If the oldest statement among all sources is an
* INSERT, convert the first REPLACE to an INSERT
@@ -818,14 +818,14 @@ vy_read_view_merge(struct vy_write_iterator *stream, struct tuple *hint,
* compaction.
*/
uint32_t size;
- const char *data = tuple_data_range(tuple, &size);
+ const char *data = tuple_data_range(rv->tuple, &size);
struct tuple *copy = is_first_insert ?
vy_stmt_new_insert(stream->format, data, data + size) :
vy_stmt_new_replace(stream->format, data, data + size);
if (copy == NULL)
return -1;
- vy_stmt_set_lsn(copy, vy_stmt_lsn(tuple));
- vy_stmt_unref_if_possible(tuple);
+ vy_stmt_set_lsn(copy, vy_stmt_lsn(rv->tuple));
+ vy_stmt_unref_if_possible(rv->tuple);
rv->tuple = copy;
}
return 0;
--
2.11.0
More information about the Tarantool-patches
mailing list