summaryrefslogtreecommitdiff
path: root/storage/innobase/row
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-07-01 17:23:00 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2020-07-01 17:23:00 +0300
commitc36834c8324974f26770d64192898f4f45d9f772 (patch)
tree772101777e3754b53bf752c25e93b9b8638ac0f3 /storage/innobase/row
parent5a097c5556dffc1aec73616f58cecf9345d96050 (diff)
downloadmariadb-git-c36834c8324974f26770d64192898f4f45d9f772.tar.gz
MDEV-20377: Make WITH_MSAN more usable
MemorySanitizer (clang -fsanitize=memory) requires that all code be compiled with instrumentation enabled. The only exception is the C runtime library. Failure to use instrumented libraries will cause bogus messages about memory being uninitialized. In WITH_MSAN builds, we must avoid calling getservbyname(), because even though it is a standard library function, it is not instrumented, not even in clang 10. Note: Before MariaDB Server 10.5, ./mtr will typically fail due to the old PCRE library, which was updated in MDEV-14024. The following cmake options were tested on 10.5 in commit 94d0bb4dbeb28a94d1f87fdd55f4297ff3df0157: cmake \ -DCMAKE_C_FLAGS='-march=native -O2' \ -DCMAKE_CXX_FLAGS='-stdlib=libc++ -march=native -O2' \ -DWITH_EMBEDDED_SERVER=OFF -DWITH_UNIT_TESTS=OFF -DCMAKE_BUILD_TYPE=Debug \ -DWITH_INNODB_{BZIP2,LZ4,LZMA,LZO,SNAPPY}=OFF \ -DPLUGIN_{ARCHIVE,TOKUDB,MROONGA,OQGRAPH,ROCKSDB,CONNECT,SPIDER}=NO \ -DWITH_SAFEMALLOC=OFF \ -DWITH_{ZLIB,SSL,PCRE}=bundled \ -DHAVE_LIBAIO_H=0 \ -DWITH_MSAN=ON MEM_MAKE_DEFINED(): An alias for VALGRIND_MAKE_MEM_DEFINED() and __msan_unpoison(). MEM_GET_VBITS(), MEM_SET_VBITS(): Aliases for VALGRIND_GET_VBITS(), VALGRIND_SET_VBITS(), __msan_copy_shadow(). InnoDB: Replace the UNIV_MEM_ macros with corresponding MEM_ macros. ut_crc32_8_hw(), ut_crc32_64_low_hw(): Use the compiler built-in functions instead of inline assembler when building WITH_MSAN. This will require at least -msse4.2 when building for IA-32 or AMD64. The inline assembler would not be instrumented, and would thus cause bogus failures.
Diffstat (limited to 'storage/innobase/row')
-rw-r--r--storage/innobase/row/row0ext.cc6
-rw-r--r--storage/innobase/row/row0ftsort.cc10
-rw-r--r--storage/innobase/row/row0ins.cc6
-rw-r--r--storage/innobase/row/row0log.cc40
-rw-r--r--storage/innobase/row/row0merge.cc41
-rw-r--r--storage/innobase/row/row0mysql.cc4
-rw-r--r--storage/innobase/row/row0sel.cc38
-rw-r--r--storage/innobase/row/row0upd.cc4
8 files changed, 91 insertions, 58 deletions
diff --git a/storage/innobase/row/row0ext.cc b/storage/innobase/row/row0ext.cc
index f7e28981939..32e9aad9896 100644
--- a/storage/innobase/row/row0ext.cc
+++ b/storage/innobase/row/row0ext.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2006, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -119,11 +120,6 @@ row_ext_create(
ret->buf = static_cast<byte*>(
mem_heap_alloc(heap, n_ext * ret->max_len));
-#ifdef UNIV_DEBUG
- memset(ret->buf, 0xaa, n_ext * ret->max_len);
- UNIV_MEM_ALLOC(ret->buf, n_ext * ret->max_len);
-#endif
-
/* Fetch the BLOB prefixes */
for (i = 0; i < n_ext; i++) {
const dfield_t* dfield;
diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc
index c7c86fb337b..4085ff17bd3 100644
--- a/storage/innobase/row/row0ftsort.cc
+++ b/storage/innobase/row/row0ftsort.cc
@@ -903,7 +903,7 @@ loop:
goto func_exit;
}
- UNIV_MEM_INVALID(block[t_ctx.buf_used], srv_sort_buf_size);
+ MEM_UNDEFINED(block[t_ctx.buf_used], srv_sort_buf_size);
buf[t_ctx.buf_used] = row_merge_buf_empty(buf[t_ctx.buf_used]);
mycount[t_ctx.buf_used] += t_ctx.rows_added[t_ctx.buf_used];
t_ctx.rows_added[t_ctx.buf_used] = 0;
@@ -997,12 +997,14 @@ exit:
goto func_exit;
}
- UNIV_MEM_INVALID(block[i], srv_sort_buf_size);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(block[i], srv_sort_buf_size);
if (crypt_block[i]) {
- UNIV_MEM_INVALID(crypt_block[i],
- srv_sort_buf_size);
+ MEM_UNDEFINED(crypt_block[i],
+ srv_sort_buf_size);
}
+#endif /* HAVE_valgrind_or_MSAN */
}
buf[i] = row_merge_buf_empty(buf[i]);
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 2ca54e90c4e..50394193a15 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -1272,8 +1272,10 @@ row_ins_foreign_check_on_constraint(
update->info_bits = 0;
update->n_fields = foreign->n_fields;
- UNIV_MEM_INVALID(update->fields,
- update->n_fields * sizeof *update->fields);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(update->fields,
+ update->n_fields * sizeof *update->fields);
+#endif /* HAVE_valgrind_or_MSAN */
bool affects_fulltext = false;
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index e46ee2c4f18..986cac54540 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -323,7 +323,9 @@ row_log_online_op(
goto err_exit;
}
- UNIV_MEM_INVALID(log->tail.buf, sizeof log->tail.buf);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(log->tail.buf, sizeof log->tail.buf);
+#endif /* HAVE_valgrind_or_MSAN */
ut_ad(log->tail.bytes < srv_sort_buf_size);
avail_size = srv_sort_buf_size - log->tail.bytes;
@@ -373,7 +375,7 @@ row_log_online_op(
log->tail.buf, avail_size);
}
- UNIV_MEM_ASSERT_RW(buf, srv_sort_buf_size);
+ MEM_CHECK_DEFINED(buf, srv_sort_buf_size);
if (row_log_tmpfile(log) < 0) {
log->error = DB_OUT_OF_MEMORY;
@@ -407,8 +409,10 @@ write_failed:
index->type |= DICT_CORRUPT;
}
- UNIV_MEM_INVALID(log->tail.block, srv_sort_buf_size);
- UNIV_MEM_INVALID(buf, srv_sort_buf_size);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(log->tail.block, srv_sort_buf_size);
+ MEM_UNDEFINED(buf, srv_sort_buf_size);
+#endif /* HAVE_valgrind_or_MSAN */
memcpy(log->tail.block, log->tail.buf + avail_size,
mrec_size - avail_size);
@@ -418,7 +422,9 @@ write_failed:
ut_ad(b == log->tail.block + log->tail.bytes);
}
- UNIV_MEM_INVALID(log->tail.buf, sizeof log->tail.buf);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(log->tail.buf, sizeof log->tail.buf);
+#endif /* HAVE_valgrind_or_MSAN */
err_exit:
mutex_exit(&log->mutex);
}
@@ -450,7 +456,9 @@ row_log_table_open(
{
mutex_enter(&log->mutex);
- UNIV_MEM_INVALID(log->tail.buf, sizeof log->tail.buf);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(log->tail.buf, sizeof log->tail.buf);
+#endif /* HAVE_valgrind_or_MSAN */
if (log->error != DB_SUCCESS) {
err_exit:
@@ -510,7 +518,7 @@ row_log_table_close_func(
memcpy(buf + log->tail.bytes, log->tail.buf, avail);
}
- UNIV_MEM_ASSERT_RW(buf, srv_sort_buf_size);
+ MEM_CHECK_DEFINED(buf, srv_sort_buf_size);
if (row_log_tmpfile(log) < 0) {
log->error = DB_OUT_OF_MEMORY;
@@ -541,8 +549,10 @@ row_log_table_close_func(
write_failed:
log->error = DB_ONLINE_LOG_TOO_BIG;
}
- UNIV_MEM_INVALID(log->tail.block, srv_sort_buf_size);
- UNIV_MEM_INVALID(buf, srv_sort_buf_size);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(log->tail.block, srv_sort_buf_size);
+ MEM_UNDEFINED(buf, srv_sort_buf_size);
+#endif /* HAVE_valgrind_or_MSAN */
memcpy(log->tail.block, log->tail.buf + avail, size - avail);
log->tail.bytes = size - avail;
} else {
@@ -551,7 +561,9 @@ write_failed:
}
log->tail.total += size;
- UNIV_MEM_INVALID(log->tail.buf, sizeof log->tail.buf);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(log->tail.buf, sizeof log->tail.buf);
+#endif /* HAVE_valgrind_or_MSAN */
err_exit:
mutex_exit(&log->mutex);
@@ -2557,7 +2569,9 @@ row_log_table_apply_ops(
ut_ad(new_trx_id_col > 0);
ut_ad(new_trx_id_col != ULINT_UNDEFINED);
- UNIV_MEM_INVALID(&mrec_end, sizeof mrec_end);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(&mrec_end, sizeof mrec_end);
+#endif /* HAVE_valgrind_or_MSAN */
offsets = static_cast<rec_offs*>(ut_malloc_nokey(i * sizeof *offsets));
rec_offs_set_n_alloc(offsets, i);
@@ -3434,7 +3448,9 @@ row_log_apply_ops(
ut_ad(!index->is_committed());
ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_X));
ut_ad(index->online_log);
- UNIV_MEM_INVALID(&mrec_end, sizeof mrec_end);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(&mrec_end, sizeof mrec_end);
+#endif /* HAVE_valgrind_or_MSAN */
offsets = static_cast<rec_offs*>(ut_malloc_nokey(i * sizeof *offsets));
rec_offs_set_n_alloc(offsets, i);
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 5cbfe0e3ddb..3a6d8cea4a8 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -1027,11 +1027,11 @@ row_merge_buf_write(
ut_a(b < &block[srv_sort_buf_size]);
ut_a(b == &block[0] + buf->total_size);
*b++ = 0;
-#ifdef UNIV_DEBUG_VALGRIND
+#ifdef HAVE_valgrind_or_MSAN
/* The rest of the block is uninitialized. Initialize it
to avoid bogus warnings. */
memset(b, 0xff, &block[srv_sort_buf_size] - b);
-#endif /* UNIV_DEBUG_VALGRIND */
+#endif /* HAVE_valgrind_or_MSAN */
DBUG_LOG("ib_merge_sort",
"write " << reinterpret_cast<const void*>(b) << ','
<< of->fd << ',' << of->offset << " EOF");
@@ -1425,7 +1425,9 @@ row_merge_write_rec(
return(NULL);
}
- UNIV_MEM_INVALID(&block[0], srv_sort_buf_size);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(&block[0], srv_sort_buf_size);
+#endif /* HAVE_valgrind_or_MSAN */
/* Copy the rest. */
b = &block[0];
@@ -1466,20 +1468,19 @@ row_merge_write_eof(
",fd=" << fd << ',' << *foffs);
*b++ = 0;
- UNIV_MEM_ASSERT_RW(&block[0], b - &block[0]);
- UNIV_MEM_ASSERT_W(&block[0], srv_sort_buf_size);
+ MEM_CHECK_DEFINED(&block[0], b - &block[0]);
+ MEM_CHECK_ADDRESSABLE(&block[0], srv_sort_buf_size);
-#ifdef UNIV_DEBUG_VALGRIND
- /* The rest of the block is uninitialized. Initialize it
- to avoid bogus warnings. */
- memset(b, 0xff, &block[srv_sort_buf_size] - b);
-#endif /* UNIV_DEBUG_VALGRIND */
+ /* The rest of the block is uninitialized. Silence warnings. */
+ MEM_MAKE_DEFINED(b, &block[srv_sort_buf_size] - b);
if (!row_merge_write(fd, (*foffs)++, block, crypt_block, space)) {
DBUG_RETURN(NULL);
}
- UNIV_MEM_INVALID(&block[0], srv_sort_buf_size);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(&block[0], srv_sort_buf_size);
+#endif
DBUG_RETURN(&block[0]);
}
@@ -2550,8 +2551,10 @@ write_buffers:
break;
}
- UNIV_MEM_INVALID(
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(
&block[0], srv_sort_buf_size);
+#endif /* HAVE_valgrind_or_MSAN */
}
}
merge_buf[i] = row_merge_buf_empty(buf);
@@ -3034,10 +3037,10 @@ row_merge(
ulint n_run = 0;
/*!< num of runs generated from this merge */
- UNIV_MEM_ASSERT_W(&block[0], 3 * srv_sort_buf_size);
+ MEM_CHECK_ADDRESSABLE(&block[0], 3 * srv_sort_buf_size);
if (crypt_block) {
- UNIV_MEM_ASSERT_W(&crypt_block[0], 3 * srv_sort_buf_size);
+ MEM_CHECK_ADDRESSABLE(&crypt_block[0], 3 * srv_sort_buf_size);
}
ut_ad(ihalf < file->offset);
@@ -3058,7 +3061,9 @@ row_merge(
foffs0 = 0;
foffs1 = ihalf;
- UNIV_MEM_INVALID(run_offset, *num_run * sizeof *run_offset);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(run_offset, *num_run * sizeof *run_offset);
+#endif /* HAVE_valgrind_or_MSAN */
for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) {
@@ -3139,7 +3144,9 @@ row_merge(
*tmpfd = file->fd;
*file = of;
- UNIV_MEM_INVALID(&block[0], 3 * srv_sort_buf_size);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(&block[0], 3 * srv_sort_buf_size);
+#endif /* HAVE_valgrind_or_MSAN */
return(DB_SUCCESS);
}
@@ -3252,7 +3259,7 @@ row_merge_sort(
break;
}
- UNIV_MEM_ASSERT_RW(run_offset, num_runs * sizeof *run_offset);
+ MEM_CHECK_DEFINED(run_offset, num_runs * sizeof *run_offset);
} while (num_runs > 1);
ut_free(run_offset);
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 3989095d6c6..b304c03f7ed 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -297,9 +297,7 @@ row_mysql_store_geometry(
{
/* MySQL might assume the field is set to zero except the length and
the pointer fields */
- UNIV_MEM_ASSERT_RW(src, src_len);
- UNIV_MEM_ASSERT_W(dest, dest_len);
- UNIV_MEM_INVALID(dest, dest_len);
+ MEM_CHECK_DEFINED(src, src_len);
memset(dest, '\0', dest_len);
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index 15486500b37..9340d5060d9 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -984,9 +984,11 @@ row_sel_get_clust_rec(
switch (err) {
case DB_SUCCESS:
case DB_SUCCESS_LOCKED_REC:
- /* Declare the variable uninitialized in Valgrind.
+#ifdef HAVE_valgrind_or_MSAN
+ /* Declare the variable uninitialized.
It should be set to DB_SUCCESS at func_exit. */
- UNIV_MEM_INVALID(&err, sizeof err);
+ MEM_UNDEFINED(&err, sizeof err);
+#endif /* HAVE_valgrind_or_MSAN */
break;
default:
goto err_exit;
@@ -2811,9 +2813,11 @@ row_sel_field_store_in_mysql_format_func(
#endif /* UNIV_DEBUG */
ut_ad(len != UNIV_SQL_NULL);
- UNIV_MEM_ASSERT_RW(data, len);
- UNIV_MEM_ASSERT_W(dest, templ->mysql_col_len);
- UNIV_MEM_INVALID(dest, templ->mysql_col_len);
+ MEM_CHECK_DEFINED(data, len);
+ MEM_CHECK_ADDRESSABLE(dest, templ->mysql_col_len);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(dest, templ->mysql_col_len);
+#endif /* HAVE_valgrind_or_MSAN */
switch (templ->type) {
const byte* field_end;
@@ -3075,9 +3079,9 @@ row_sel_store_mysql_field_func(
NULL value is set to the default value. */
ut_ad(templ->mysql_null_bit_mask);
- UNIV_MEM_ASSERT_RW(prebuilt->default_rec
- + templ->mysql_col_offset,
- templ->mysql_col_len);
+ MEM_CHECK_DEFINED(prebuilt->default_rec
+ + templ->mysql_col_offset,
+ templ->mysql_col_len);
mysql_rec[templ->mysql_null_byte_offset]
|= (byte) templ->mysql_null_bit_mask;
memcpy(mysql_rec + templ->mysql_col_offset,
@@ -3715,7 +3719,7 @@ row_sel_copy_cached_field_for_mysql(
buf += templ->mysql_col_offset;
cache += templ->mysql_col_offset;
- UNIV_MEM_ASSERT_W(buf, templ->mysql_col_len);
+ MEM_CHECK_ADDRESSABLE(buf, templ->mysql_col_len);
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR
&& (templ->type != DATA_INT)) {
@@ -3725,7 +3729,9 @@ row_sel_copy_cached_field_for_mysql(
row_mysql_read_true_varchar(
&len, cache, templ->mysql_length_bytes);
len += templ->mysql_length_bytes;
- UNIV_MEM_INVALID(buf, templ->mysql_col_len);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(buf, templ->mysql_col_len);
+#endif /* HAVE_valgrind_or_MSAN */
} else {
len = templ->mysql_col_len;
}
@@ -3784,7 +3790,7 @@ row_sel_dequeue_cached_row_for_mysql(
ut_ad(prebuilt->n_fetch_cached > 0);
ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
- UNIV_MEM_ASSERT_W(buf, prebuilt->mysql_row_len);
+ MEM_CHECK_ADDRESSABLE(buf, prebuilt->mysql_row_len);
cached_rec = prebuilt->fetch_cache[prebuilt->fetch_cache_first];
@@ -3794,7 +3800,9 @@ row_sel_dequeue_cached_row_for_mysql(
/* The record is long. Copy it field by field, in case
there are some long VARCHAR column of which only a
small length is being used. */
- UNIV_MEM_INVALID(buf, prebuilt->mysql_prefix_len);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(buf, prebuilt->mysql_prefix_len);
+#endif /* HAVE_valgrind_or_MSAN */
/* First copy the NULL bits. */
ut_memcpy(buf, cached_rec, prebuilt->null_bitmap_len);
@@ -3878,8 +3886,10 @@ row_sel_fetch_last_buf(
}
ut_ad(prebuilt->fetch_cache_first == 0);
- UNIV_MEM_INVALID(prebuilt->fetch_cache[prebuilt->n_fetch_cached],
- prebuilt->mysql_row_len);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(prebuilt->fetch_cache[prebuilt->n_fetch_cached],
+ prebuilt->mysql_row_len);
+#endif /* HAVE_valgrind_or_MSAN */
return(prebuilt->fetch_cache[prebuilt->n_fetch_cached]);
}
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index a7cd06d25fd..63c1ea8d662 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -1867,7 +1867,9 @@ row_upd_changes_ord_field_binary_func(
/* Silence a compiler warning without
silencing a Valgrind error. */
dfield_len = 0;
- UNIV_MEM_INVALID(&dfield_len, sizeof dfield_len);
+#ifdef HAVE_valgrind_or_MSAN
+ MEM_UNDEFINED(&dfield_len, sizeof dfield_len);
+#endif /* HAVE_valgrind_or_MSAN */
/* See if the column is stored externally. */
buf = row_ext_lookup(ext, col_no, &dfield_len);