diff options
author | Sergei Petrunia <psergey@askmonty.org> | 2020-01-12 22:15:55 +0300 |
---|---|---|
committer | Sergei Petrunia <psergey@askmonty.org> | 2020-01-12 22:15:55 +0300 |
commit | d531b4ee3a9bcd89a2fa6b49a2207eaf966f53e3 (patch) | |
tree | fbdc8bb230c6d123f8b2484878acf234caf46810 /sql/sp_head.cc | |
parent | 9c3eca85141836548214e3c68f256b3868502509 (diff) | |
download | mariadb-git-d531b4ee3a9bcd89a2fa6b49a2207eaf966f53e3.tar.gz |
MDEV-21341: Fix UBSAN failures: Issue Sixbb-10.3-mdev21341-issueSix
(Variant #2 of the patch, which keeps the sp_head object inside the
MEM_ROOT that sp_head object owns)
(10.3 version of the fix, with handling for class sp_package)
sp_head::operator new() and operator delete() were dereferencing sp_head*
pointers to memory that didn't hold a valid sp_head object (it was
not created/already destroyed).
This caused UBSan to crash when looking up type information.
Fixed by providing static sp_head::create() and sp_head::destroy() methods.
Diffstat (limited to 'sql/sp_head.cc')
-rw-r--r-- | sql/sp_head.cc | 77 |
1 files changed, 43 insertions, 34 deletions
diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 360713fc452..af4316085b7 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -474,47 +474,39 @@ check_routine_name(const LEX_CSTRING *ident) * */ -void * -sp_head::operator new(size_t size) throw() +sp_head *sp_head::create(sp_package *parent, const Sp_handler *handler) { - DBUG_ENTER("sp_head::operator new"); MEM_ROOT own_root; + init_sql_alloc(&own_root, "sp_head", MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC, + MYF(0)); sp_head *sp; + if (!(sp= new (&own_root) sp_head(&own_root, parent, handler))) + free_root(&own_root, MYF(0)); - init_sql_alloc(&own_root, "sp_head", - MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC, MYF(0)); - sp= (sp_head *) alloc_root(&own_root, size); - if (sp == NULL) - DBUG_RETURN(NULL); - sp->main_mem_root= own_root; - DBUG_PRINT("info", ("mem_root %p", &sp->mem_root)); - DBUG_RETURN(sp); + return sp; } -void -sp_head::operator delete(void *ptr, size_t size) throw() -{ - DBUG_ENTER("sp_head::operator delete"); - MEM_ROOT own_root; - - if (ptr == NULL) - DBUG_VOID_RETURN; - - sp_head *sp= (sp_head *) ptr; - /* Make a copy of main_mem_root as free_root will free the sp */ - own_root= sp->main_mem_root; - DBUG_PRINT("info", ("mem_root %p moved to %p", - &sp->mem_root, &own_root)); - free_root(&own_root, MYF(0)); - - DBUG_VOID_RETURN; +void sp_head::destroy(sp_head *sp) +{ + if (sp) + { + /* Make a copy of main_mem_root as free_root will free the sp */ + MEM_ROOT own_root= sp->main_mem_root; + delete sp; + + DBUG_PRINT("info", ("mem_root 0x%lx moved to 0x%lx", + (ulong) &sp->mem_root, (ulong) &own_root)); + free_root(&own_root, MYF(0)); + } } -sp_head::sp_head(sp_package *parent, const Sp_handler *sph) - :Query_arena(&main_mem_root, STMT_INITIALIZED_FOR_SP), +sp_head::sp_head(MEM_ROOT *mem_root_arg, sp_package *parent, + const Sp_handler *sph) + :Query_arena(NULL, STMT_INITIALIZED_FOR_SP), Database_qualified_name(&null_clex_str, &null_clex_str), + main_mem_root(*mem_root_arg), m_parent(parent), m_handler(sph), m_flags(0), @@ -545,6 +537,8 @@ sp_head::sp_head(sp_package *parent, const Sp_handler *sph) m_pcont(new (&main_mem_root) sp_pcontext()), m_cont_level(0) { + mem_root= &main_mem_root; + m_first_instance= this; m_first_free_instance= this; m_last_cached_sp= this; @@ -567,10 +561,25 @@ sp_head::sp_head(sp_package *parent, const Sp_handler *sph) } -sp_package::sp_package(LEX *top_level_lex, +sp_package *sp_package::create(LEX *top_level_lex, const sp_name *name, + const Sp_handler *sph) +{ + MEM_ROOT own_root; + init_sql_alloc(&own_root, "sp_package", MEM_ROOT_BLOCK_SIZE, + MEM_ROOT_PREALLOC, MYF(0)); + sp_package *sp; + if (!(sp= new (&own_root) sp_package(&own_root, top_level_lex, name, sph))) + free_root(&own_root, MYF(0)); + + return sp; +} + + +sp_package::sp_package(MEM_ROOT *mem_root_arg, + LEX *top_level_lex, const sp_name *name, const Sp_handler *sph) - :sp_head(NULL, sph), + :sp_head(mem_root_arg, NULL, sph), m_current_routine(NULL), m_top_level_lex(top_level_lex), m_rcontext(NULL), @@ -588,7 +597,7 @@ sp_package::~sp_package() m_routine_declarations.cleanup(); m_body= null_clex_str; if (m_current_routine) - delete m_current_routine->sphead; + sp_head::destroy(m_current_routine->sphead); delete m_rcontext; } @@ -845,7 +854,7 @@ sp_head::~sp_head() my_hash_free(&m_sptabs); my_hash_free(&m_sroutines); - delete m_next_cached_sp; + sp_head::destroy(m_next_cached_sp); DBUG_VOID_RETURN; } |