The problem is with "QUICK_GROUP_MIN_MAX_SELECT::add_range()" ("opt_range.cc") which when doing "memcmp()" assumes that both "sel_range->min_value" and "sel_range->max_value" have exactly "min_max_arg_len" significant bytes.
*****************************************************************
if (!(sel_range->min_flag & NO_MIN_RANGE) &&
!(sel_range->max_flag & NO_MAX_RANGE))
{
if (sel_range->maybe_null && sel_range->min_value[0] && sel_range->max_value[0])
range_flag|= NULL_RANGE; /* IS NULL condition */
else if (memcmp(sel_range->min_value, sel_range->max_value, min_max_arg_len) == 0)
range_flag|= EQ_RANGE; /* equality condition */
}
*****************************************************************
However this is not always true.
There are 2 places in "get_mm_leaf()" where "min_value" and "max_value" are not fully initialized (although properly allocated).
1)
*****************************************************************
uchar *null_string=
static_cast<uchar*>(alloc_root(alloc, key_part->store_length + 1));
if (!null_string)
goto end; // out of memory
if (!(tree= new (alloc) SEL_ARG(field, null_string, null_string)))
goto end; // out of memory
*****************************************************************
2)
*****************************************************************
case Item_func::LE_FUNC:
if (!maybe_null)
tree->min_flag=NO_MIN_RANGE; /* From start */
else
{ // > NULL
if (!(tree->min_value= static_cast<uchar*>(alloc_root(alloc, key_part->store_length+1))))
goto end;
TRASH(tree->min_value, key_part->store_length + 1);
memcpy(tree->min_value, is_null_string, sizeof(is_null_string));
tree->min_flag=NEAR_MIN;
}
break;
*****************************************************************
The fix would be in rewriting "memcmp" logic in "QUICK_GROUP_MIN_MAX_SELECT::add_range()" so that it would perform "memcmp" only when values are not nullable or are nullable and are not currently set to null.
However, it feels safer to zero-set allocated memory (instead of "TRASH()") to make sure that all other similar "memcmp()" calls will produce predictable results.
The problem is with "QUICK_ GROUP_MIN_ MAX_SELECT: :add_range( )" ("opt_range.cc") which when doing "memcmp()" assumes that both "sel_range- >min_value" and "sel_range- >max_value" have exactly "min_max_arg_len" significant bytes. ******* ******* ******* ******* ******* ******* ******* ******* ** range-> min_flag & NO_MIN_RANGE) && (sel_range- >max_flag & NO_MAX_RANGE)) >maybe_ null &&
sel_range- >min_value[ 0] && sel_range- >max_value[ 0]) sel_range- >min_value, sel_range- >max_value,
min_ max_arg_ len) == 0) ******* ******* ******* ******* ******* ******* ******* ******* **
*******
if (!(sel_
!
{
if (sel_range-
range_flag|= NULL_RANGE; /* IS NULL condition */
else if (memcmp(
range_flag|= EQ_RANGE; /* equality condition */
}
*******
However this is not always true. ******* ******* ******* ******* ******* ******* ******* ******* ** cast<uchar* >(alloc_ root(alloc, key_part- >store_ length + 1));
There are 2 places in "get_mm_leaf()" where "min_value" and "max_value" are not fully initialized (although properly allocated).
1)
*******
uchar *null_string=
static_
if (!null_string)
goto end; // out of memory
TRASH( null_string, key_part- >store_ length + 1); null_string, is_null_string, sizeof( is_null_ string) );
memcpy(
if (!(tree= new (alloc) SEL_ARG(field, null_string, null_string))) ******* ******* ******* ******* ******* ******* ******* ******* ** ******* ******* ******* ******* ******* ******* ******* ******* ** >min_flag= NO_MIN_ RANGE; /* From start */
static_ cast<uchar* >(alloc_ root(alloc, key_part- >store_ length+ 1)))) tree->min_ value, key_part- >store_ length + 1); tree->min_ value, is_null_string, sizeof( is_null_ string) ); >min_flag= NEAR_MIN; ******* ******* ******* ******* ******* ******* ******* ******* **
goto end; // out of memory
*******
2)
*******
case Item_func::LE_FUNC:
if (!maybe_null)
tree-
else
{ // > NULL
if (!(tree->min_value=
goto end;
TRASH(
memcpy(
tree-
}
break;
*******
The fix would be in rewriting "memcmp" logic in "QUICK_ GROUP_MIN_ MAX_SELECT: :add_range( )" so that it would perform "memcmp" only when values are not nullable or are nullable and are not currently set to null.
However, it feels safer to zero-set allocated memory (instead of "TRASH()") to make sure that all other similar "memcmp()" calls will produce predictable results.