← Back to team overview

maria-developers team mailing list archive

Re: 91259f9: MDEV-7505 - Too large scale in DECIMAL dynamic column getter crashes mysqld

 

Hi, svoj!

On Jun 04, svoj@xxxxxxxxxxx wrote:
> revision-id: 91259f903c2ffac7c7c8fc72385a572eace4fa89
> parent(s): 9bb9bde42dbf6f936faadeaa34cde838bf6b63dd
> committer: Sergey Vojtovich
> branch nick: mariadb
> timestamp: 2015-06-04 16:04:05 +0400
> message:
> 
> MDEV-7505 - Too large scale in DECIMAL dynamic column getter crashes mysqld
> 
> Server may crash if sanity checks of COLUMN_GET() fail.
> 
> COLUMN_GET() description generator expects parent CAST item, which may not have
> been created due to failure of sanity checks. Then further attempt to report
> an error may crash the server.
> 
> Fixed COLUMN_GET() description generator to handle such case.
> 
> ---
>  mysql-test/r/dyncol.result | 6 ++++++
>  mysql-test/t/AAA.test      | 1 +

Mistakenly committed file ^^^^

>  mysql-test/t/dyncol.test   | 6 ++++++
>  sql/item_strfunc.cc        | 7 +++++++
>  4 files changed, 20 insertions(+)
> 
> diff --git a/mysql-test/t/AAA.test b/mysql-test/t/AAA.test
> new file mode 100644
> index 0000000..371db62
> --- /dev/null
> +++ b/mysql-test/t/AAA.test
> @@ -0,0 +1 @@
> +SELECT COLUMN_GET(`x`, 'y' AS DECIMAL(5,34));
> diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
> index eedf149..7ad4c06 100644
> --- a/sql/item_strfunc.cc
> +++ b/sql/item_strfunc.cc
> @@ -4467,6 +4467,13 @@ bool Item_dyncol_get::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
>  
>  void Item_dyncol_get::print(String *str, enum_query_type query_type)

How do you get to Item_dyncol_get::print if cast couldn't be created?
The comment below says "see create_func_dyncol_get". This function looks
like

  if (!(res= new (thd->mem_root) Item_dyncol_get(str, num)))
    return res;                                 // Return NULL
  return create_func_cast(thd, res, cast_type, c_len, c_dec, cs);

and to get Item_dyncol_get without a parent, one needs create_func_cast
to return 'res' without wrapping it in a CAST(...). But it never does
that.

>  {
> +  /* Parent cast doesn't exist yet. Only print dynamic column name. */
> +  if (!str->length())

Not safe, if you wrap your COLUMN_GET() in, say, CONCAT():

   CONCAT(COLUMN_GET(`x`, 'y' AS DECIMAL(5,34)))

then str->length() won't be 0, despite the error in CAST.

> +  {
> +    args[1]->print(str, query_type);
> +    return;
> +  }
> +
>    /* see create_func_dyncol_get */
>    DBUG_ASSERT(str->length() >= 5);
>    DBUG_ASSERT(strncmp(str->ptr() + str->length() - 5, "cast(", 5) == 0);

Regards,
Sergei


Follow ups