mirror of
https://github.com/MariaDB/server.git
synced 2025-01-30 18:41:56 +01:00
2255be0395
ha_storage_put_memlim(): Initialize node->next in order to avoid a
crash on a subsequent invocation, due to dereferencing an uninitialized
pointer.
This fixes a regression that had been introduced in
commit ccb6cd8053
(MDEV-35189).
Reviewed by: Debarun Banerjee
114 lines
3.6 KiB
C++
114 lines
3.6 KiB
C++
/*****************************************************************************
|
|
|
|
Copyright (c) 2007, 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
|
|
Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/**************************************************//**
|
|
@file ha/ha0storage.cc
|
|
Hash storage.
|
|
Provides a data structure that stores chunks of data in
|
|
its own storage, avoiding duplicates.
|
|
|
|
Created September 22, 2007 Vasil Dimov
|
|
*******************************************************/
|
|
|
|
#include "ha0storage.h"
|
|
#include "hash0hash.h"
|
|
#include "mem0mem.h"
|
|
|
|
/*******************************************************************//**
|
|
Copies data into the storage and returns a pointer to the copy. If the
|
|
same data chunk is already present, then pointer to it is returned.
|
|
Data chunks are considered to be equal if len1 == len2 and
|
|
memcmp(data1, data2, len1) == 0. If "data" is not present (and thus
|
|
data_len bytes need to be allocated) and the size of storage is going to
|
|
become more than "memlim" then "data" is not added and NULL is returned.
|
|
To disable this behavior "memlim" can be set to 0, which stands for
|
|
"no limit". */
|
|
const void*
|
|
ha_storage_put_memlim(
|
|
/*==================*/
|
|
ha_storage_t* storage, /*!< in/out: hash storage */
|
|
const void* data, /*!< in: data to store */
|
|
ulint data_len, /*!< in: data length */
|
|
ulint memlim) /*!< in: memory limit to obey */
|
|
{
|
|
const uint32_t fold= my_crc32c(0, data, data_len);
|
|
ha_storage_node_t** after = reinterpret_cast<ha_storage_node_t**>
|
|
(&storage->hash.cell_get(fold)->node);
|
|
for (; *after; after= &(*after)->next)
|
|
if ((*after)->data_len == data_len &&
|
|
!memcmp((*after)->data, data, data_len))
|
|
return (*after)->data;
|
|
|
|
/* not present */
|
|
|
|
/* check if we are allowed to allocate data_len bytes */
|
|
if (memlim > 0 && ha_storage_get_size(storage) + data_len > memlim)
|
|
return nullptr;
|
|
|
|
/* we put the auxiliary node struct and the data itself in one
|
|
continuous block */
|
|
ha_storage_node_t *node= static_cast<ha_storage_node_t*>
|
|
(mem_heap_alloc(storage->heap, sizeof *node + data_len));
|
|
node->data_len= data_len;
|
|
node->data= &node[1];
|
|
node->next= nullptr;
|
|
memcpy(const_cast<void*>(node->data), data, data_len);
|
|
*after= node;
|
|
return node->data;
|
|
}
|
|
|
|
#ifdef UNIV_COMPILE_TEST_FUNCS
|
|
|
|
void
|
|
test_ha_storage()
|
|
{
|
|
ha_storage_t* storage;
|
|
char buf[1024];
|
|
int i;
|
|
const void* stored[256];
|
|
const void* p;
|
|
|
|
storage = ha_storage_create(0, 0);
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
|
|
memset(buf, i, sizeof(buf));
|
|
stored[i] = ha_storage_put(storage, buf, sizeof(buf));
|
|
}
|
|
|
|
//ha_storage_empty(&storage);
|
|
|
|
for (i = 255; i >= 0; i--) {
|
|
|
|
memset(buf, i, sizeof(buf));
|
|
p = ha_storage_put(storage, buf, sizeof(buf));
|
|
|
|
if (p != stored[i]) {
|
|
ib::warn() << "ha_storage_put() returned " << p
|
|
<< " instead of " << stored[i] << ", i=" << i;
|
|
return;
|
|
}
|
|
}
|
|
|
|
ib::info() << "all ok";
|
|
|
|
ha_storage_free(storage);
|
|
}
|
|
|
|
#endif /* UNIV_COMPILE_TEST_FUNCS */
|