MDEV-31083 ASAN use-after-poison in myrg_attach_children

The reason for ASAN report was that the MERGE and MYISAM file
had different key definitions, which is not allowed.

Fixed by ensuring that the MERGE code is not copying more key stats
than what is in the MyISAM file.

Other things:
- Give an error if different MyISAM files has different number of
  key parts.
This commit is contained in:
Monty 2023-04-20 14:12:48 +03:00
parent c7e04af8bc
commit cd37e49422
6 changed files with 37 additions and 7 deletions

View file

@ -71,6 +71,7 @@ typedef struct st_myrg_info
ulong cache_size;
uint merge_insert_method;
uint tables,options,reclength,keys;
uint key_parts;
my_bool cache_in_use;
/* If MERGE children attached to parent. See top comment in ha_myisammrg.cc */
my_bool children_attached;

View file

@ -3919,3 +3919,15 @@ ERROR HY000: Unable to open underlying table which is differently defined or of
DROP TRIGGER trg1;
DROP TABLE t1;
DROP TABLE m1;
#
# MDEV-31083 ASAN use-after-poison in myrg_attach_children
#
CREATE TABLE t1 (f TEXT, FULLTEXT (f)) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('foo'),('bar');
CREATE TABLE mrg (f TEXT) ENGINE=MERGE, UNION(t1);
SELECT * FROM mrg;
f
foo
bar
DROP TABLE mrg, t1;
End of 10.5 tests

View file

@ -2919,3 +2919,15 @@ set global default_storage_engine=@save_default_storage_engine;
# Check that all connections opened by test cases in this file are really
# gone so execution of other tests won't be affected by their presence.
--source include/wait_until_count_sessions.inc
--echo #
--echo # MDEV-31083 ASAN use-after-poison in myrg_attach_children
--echo #
CREATE TABLE t1 (f TEXT, FULLTEXT (f)) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('foo'),('bar');
CREATE TABLE mrg (f TEXT) ENGINE=MERGE, UNION(t1);
SELECT * FROM mrg;
DROP TABLE mrg, t1;
--echo End of 10.5 tests

View file

@ -518,6 +518,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
share->kfile=kfile;
share->this_process=(ulong) getpid();
share->last_process= share->state.process;
share->base.base_key_parts= base_key_parts;
share->base.key_parts=key_parts;
share->base.all_key_parts=key_parts+unique_key_parts;
if (!(share->last_version=share->state.version))

View file

@ -132,7 +132,7 @@ typedef struct st_mi_base_info
uint extra_alloc_bytes;
uint extra_alloc_procent;
/* The following are from the header */
uint key_parts, all_key_parts;
uint key_parts, all_key_parts, base_key_parts;
} MI_BASE_INFO;

View file

@ -432,17 +432,20 @@ int myrg_attach_children(MYRG_INFO *m_info, int handle_locking,
first_child= FALSE;
m_info->reclength= myisam->s->base.reclength;
min_keys= myisam->s->base.keys;
key_parts= myisam->s->base.key_parts;
key_parts= myisam->s->base.base_key_parts;
if (*need_compat_check && m_info->rec_per_key_part)
{
my_free(m_info->rec_per_key_part);
m_info->rec_per_key_part= NULL;
}
if (!m_info->rec_per_key_part)
if (!m_info->rec_per_key_part || m_info->key_parts != key_parts)
{
m_info->key_parts= key_parts;
/* The +1 is because by my_realloc() don't allow zero length */
if (!(m_info->rec_per_key_part= (ulong*)
my_malloc(rg_key_memory_MYRG_INFO,
key_parts * sizeof(long), MYF(MY_WME))))
my_realloc(rg_key_memory_MYRG_INFO, m_info->rec_per_key_part,
key_parts * sizeof(long) +1,
MYF(MY_WME | MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))))
goto err; /* purecov: inspected */
errpos= 1;
}
@ -457,7 +460,8 @@ int myrg_attach_children(MYRG_INFO *m_info, int handle_locking,
myisam->open_flag|= HA_OPEN_MERGE_TABLE;
/* Check table definition match. */
if (m_info->reclength != myisam->s->base.reclength)
if (m_info->reclength != myisam->s->base.reclength ||
key_parts != myisam->s->base.base_key_parts)
{
DBUG_PRINT("error", ("definition mismatch table: '%s' repair: %d",
myisam->filename,