Bug #18823979: PS: UCS2 + CASE WHEN THEN ELSE CRASH IN

               ITEM_PARAM::SAFE_CHARSET_CONVERTER

ISSUE:
------
Charset conversion on a null parameter is not handled
correctly.

SOLUTION:
---------
Item_param's charset converter does not handle the case
where it might have to deal with a null value. This is
fine for other charset converters since the value is not
supplied to them at runtime.

The fix is to check if the parameter is now set to null and
return an Item_null object. Also, there is no need to
initialize Item_param's cnvitem in the constructor to a
string. This can be done in
ITEM_PARAM::SAFE_CHARSET_CONVERTER itself.

Members of Item_param, cnvbuf and cnvstr, have been removed
and cnvitem has been made a local variable in
ITEM_PARAM::SAFE_CHARSET_CONVERTER.
parent 01d41f68
...@@ -926,14 +926,31 @@ Item *Item_param::safe_charset_converter(CHARSET_INFO *tocs) ...@@ -926,14 +926,31 @@ Item *Item_param::safe_charset_converter(CHARSET_INFO *tocs)
{ {
if (const_item()) if (const_item())
{ {
uint cnv_errors; Item *cnvitem;
String *ostr= val_str(&cnvstr); String tmp, cstr, *ostr= val_str(&tmp);
cnvitem->str_value.copy(ostr->ptr(), ostr->length(),
ostr->charset(), tocs, &cnv_errors); if (null_value)
if (cnv_errors) {
return NULL; cnvitem= new Item_null();
cnvitem->str_value.mark_as_const(); if (cnvitem == NULL)
cnvitem->max_length= cnvitem->str_value.numchars() * tocs->mbmaxlen; return NULL;
cnvitem->collation.set(tocs);
}
else
{
uint conv_errors;
cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs,
&conv_errors);
if (conv_errors || !(cnvitem= new Item_string(cstr.ptr(), cstr.length(),
cstr.charset(),
collation.derivation)))
return NULL;
cnvitem->str_value.copy();
cnvitem->str_value.mark_as_const();
}
return cnvitem; return cnvitem;
} }
return Item::safe_charset_converter(tocs); return Item::safe_charset_converter(tocs);
...@@ -2795,8 +2812,6 @@ Item_param::Item_param(uint pos_in_query_arg) : ...@@ -2795,8 +2812,6 @@ Item_param::Item_param(uint pos_in_query_arg) :
value is set. value is set.
*/ */
maybe_null= 1; maybe_null= 1;
cnvitem= new Item_string("", 0, &my_charset_bin, DERIVATION_COERCIBLE);
cnvstr.set(cnvbuf, sizeof(cnvbuf), &my_charset_bin);
} }
......
#ifndef ITEM_INCLUDED #ifndef ITEM_INCLUDED
#define ITEM_INCLUDED #define ITEM_INCLUDED
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -1861,10 +1861,6 @@ public: ...@@ -1861,10 +1861,6 @@ public:
class Item_param :public Item, class Item_param :public Item,
private Settable_routine_parameter private Settable_routine_parameter
{ {
char cnvbuf[MAX_FIELD_WIDTH];
String cnvstr;
Item *cnvitem;
public: public:
enum enum_item_param_state enum enum_item_param_state
{ {
......
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