Commit 81453474 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-20917 InnoDB is passing NULL to nonnull function parameters

mem_heap_dup(): Avoid mem_heap_alloc() and memcpy() of data=NULL, len=0.

trx_undo_report_insert_virtual(), trx_undo_page_report_insert(),
trx_undo_page_report_modify(): Avoid memcpy(ptr, NULL, 0).

dfield_data_is_binary_equal(): Correctly handle data=NULL, len=0.

This clean-up was motivated by WITH_UBSAN, and no bug related to this
was observed in the wild. It should be noted that undefined behaviour
such as memcpy(ptr, NULL, 0) could allow compilers to perform unsafe
optimizations, like it was the case in
commit fc168c3a (MDEV-15587).
parent 2d82ae5b
......@@ -168,7 +168,7 @@ dfield_data_is_binary_equal(
const dfield_t* field, /*!< in: field */
ulint len, /*!< in: data length or UNIV_SQL_NULL */
const byte* data) /*!< in: data */
MY_ATTRIBUTE((nonnull, warn_unused_result));
MY_ATTRIBUTE((nonnull(1), warn_unused_result));
/*********************************************************************//**
Gets info bits in a data tuple.
......
......@@ -223,7 +223,7 @@ dfield_data_is_binary_equal(
const byte* data) /*!< in: data */
{
return(len == dfield_get_len(field)
&& (len == UNIV_SQL_NULL
&& (!len || len == UNIV_SQL_NULL
|| !memcmp(dfield_get_data(field), data, len)));
}
......
......@@ -228,7 +228,22 @@ mem_strdupl(
const char* str, /*!< in: string to be copied */
ulint len); /*!< in: length of str, in bytes */
/** Duplicates a NUL-terminated string, allocated from a memory heap.
/** Duplicate a block of data, allocated from a memory heap.
@param[in] heap memory heap where string is allocated
@param[in] data block of data to be copied
@param[in] len length of data, in bytes
@return own: a copy of data */
inline
void*
mem_heap_dup(mem_heap_t* heap, const void* data, size_t len)
{
ut_ad(data || !len);
return UNIV_LIKELY(data != NULL)
? memcpy(mem_heap_alloc(heap, len), data, len)
: NULL;
}
/** Duplicate a NUL-terminated string, allocated from a memory heap.
@param[in] heap memory heap where string is allocated
@param[in] str string to be copied
@return own: a copy of the string */
......@@ -259,16 +274,6 @@ mem_heap_strcat(
const char* s1, /*!< in: string 1 */
const char* s2); /*!< in: string 2 */
/**********************************************************************//**
Duplicate a block of data, allocated from a memory heap.
@return own: a copy of the data */
void*
mem_heap_dup(
/*=========*/
mem_heap_t* heap, /*!< in: memory heap where copy is allocated */
const void* data, /*!< in: data to be copied */
ulint len); /*!< in: length of data, in bytes */
/****************************************************************//**
A simple sprintf replacement that dynamically allocates the space for the
formatted string from the given heap. This supports a very limited set of
......
/*****************************************************************************
Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation.
Copyright (c) 2017, 2019, 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
......@@ -41,19 +41,6 @@ mem_heap_strdup(
return(static_cast<char*>(mem_heap_dup(heap, str, strlen(str) + 1)));
}
/**********************************************************************//**
Duplicate a block of data, allocated from a memory heap.
@return own: a copy of the data */
void*
mem_heap_dup(
/*=========*/
mem_heap_t* heap, /*!< in: memory heap where copy is allocated */
const void* data, /*!< in: data to be copied */
ulint len) /*!< in: length of data, in bytes */
{
return(memcpy(mem_heap_alloc(heap, len), data, len));
}
/**********************************************************************//**
Concatenate two strings and return the result, using a memory heap.
@return own: the result */
......
......@@ -412,9 +412,15 @@ trx_undo_report_insert_virtual(
const dfield_t* vfield = dtuple_get_nth_v_field(
row, col->v_pos);
ulint flen = vfield->len;
switch (ulint flen = vfield->len) {
case 0: case UNIV_SQL_NULL:
if (trx_undo_left(undo_page, *ptr) < 5) {
return(false);
}
if (flen != UNIV_SQL_NULL) {
*ptr += mach_write_compressed(*ptr, flen);
break;
default:
ulint max_len
= dict_max_v_field_len_store_undo(
table, col_no);
......@@ -429,15 +435,8 @@ trx_undo_report_insert_virtual(
}
*ptr += mach_write_compressed(*ptr, flen);
ut_memcpy(*ptr, vfield->data, flen);
memcpy(*ptr, vfield->data, flen);
*ptr += flen;
} else {
if (trx_undo_left(undo_page, *ptr) < 5) {
return(false);
}
*ptr += mach_write_compressed(*ptr, flen);
}
}
}
......@@ -506,13 +505,16 @@ trx_undo_page_report_insert(
ptr += mach_write_compressed(ptr, flen);
if (flen != UNIV_SQL_NULL) {
switch (flen) {
case 0: case UNIV_SQL_NULL:
break;
default:
if (trx_undo_left(undo_page, ptr) < flen) {
return(0);
}
ut_memcpy(ptr, dfield_get_data(field), flen);
memcpy(ptr, dfield_get_data(field), flen);
ptr += flen;
}
}
......@@ -981,7 +983,7 @@ trx_undo_page_report_modify(
return(0);
}
ut_memcpy(ptr, field, flen);
memcpy(ptr, field, flen);
ptr += flen;
}
}
......@@ -1123,7 +1125,7 @@ trx_undo_page_report_modify(
return(0);
}
ut_memcpy(ptr, field, flen);
memcpy(ptr, field, flen);
ptr += flen;
}
......@@ -1149,7 +1151,7 @@ trx_undo_page_report_modify(
return(0);
}
ut_memcpy(ptr, field, flen);
memcpy(ptr, field, flen);
ptr += flen;
}
}
......@@ -1305,7 +1307,7 @@ trx_undo_page_report_modify(
return(0);
}
ut_memcpy(ptr, field, flen);
memcpy(ptr, field, flen);
ptr += flen;
}
......@@ -1391,14 +1393,17 @@ trx_undo_page_report_modify(
ptr += mach_write_compressed(ptr, flen);
if (flen != UNIV_SQL_NULL) {
switch (flen) {
case 0: case UNIV_SQL_NULL:
break;
default:
if (trx_undo_left(undo_page, ptr)
< flen) {
return(0);
}
ut_memcpy(ptr, field, flen);
memcpy(ptr, field, flen);
ptr += flen;
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment