Valgrind error on main.group_min_max

Bug #1515591 reported by Laurynas Biveinis
14
This bug affects 2 people
Affects Status Importance Assigned to Milestone
MySQL Server
Unknown
Unknown
Percona Server moved to https://jira.percona.com/projects/PS
Status tracked in 5.7
5.5
Fix Released
Medium
Laurynas Biveinis
5.6
Fix Released
Medium
Unassigned
5.7
Fix Released
Medium
Unassigned

Bug Description

Valgrind reports an error on main.group_min_max:

main.group_min_max [ fail ] Found warnings/errors in server log file!
        Test ended at 2015-11-12 14:04:32
line
==17805== Thread 20:
==17805== Conditional jump or move depends on uninitialised value(s)
==17805== at 0x4C31D52: __memcmp_sse4_1 (vg_replace_strmem.c:1094)
==17805== by 0x9D351E: QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG*) (opt_range.cc:12888)
==17805== by 0x9D2B2C: TRP_GROUP_MIN_MAX::make_quick(PARAM*, bool, st_mem_root*) (opt_range.cc:12647)
==17805== by 0x9BB882: SQL_SELECT::test_quick_select(THD*, Bitmap<64u>, unsigned long long, unsigned long long, bool, st_order::enum_order) (opt_range.cc:2971)
==17805== by 0xA216F5: get_quick_record_count(THD*, SQL_SELECT*, TABLE*, Bitmap<64u> const*, unsigned long long) (sql_optimizer.cc:4002)
==17805== by 0xA2098B: make_join_statistics(JOIN*, TABLE_LIST*, Item*, Mem_root_array<Key_use, true>*, bool) (sql_optimizer.cc:3713)
==17805== by 0xA17737: JOIN::optimize() (sql_optimizer.cc:382)
==17805== by 0x84A104: mysql_execute_select(THD*, st_select_lex*, bool) (sql_select.cc:1086)
==17805== by 0x84A490: mysql_select(THD*, TABLE_LIST*, unsigned int, List<Item>&, Item*, SQL_I_List<st_order>*, SQL_I_List<st_order>*, Item*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) (sql_select.cc:1221)
==17805== by 0x9AA1E2: mysql_explain_unit(THD*, st_select_lex_unit*, select_result*) (opt_explain.cc:2132)
==17805== by 0x9A9DAB: explain_query_expression(THD*, select_result*) (opt_explain.cc:2034)
==17805== by 0x81BD15: execute_sqlcom_select(THD*, TABLE_LIST*) (sql_parse.cc:5672)
==17805== by 0x813EAC: mysql_execute_command(THD*) (sql_parse.cc:3010)
==17805== by 0x81EDBD: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:6972)
==17805== by 0x810298: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1442)
==17805== by 0x80F053: do_command(THD*) (sql_parse.cc:1054)
==17805== Uninitialised value was created by a client request
==17805== at 0x9C611A: get_mm_leaf(RANGE_OPT_PARAM*, Item*, Field*, st_key_part*, Item_func::Functype, Item*) (opt_range.cc:7088)
==17805== by 0x9C4C8B: get_mm_parts(RANGE_OPT_PARAM*, Item_func*, Field*, Item_func::Functype, Item*, Item_result) (opt_range.cc:6555)
==17805== by 0x9C3791: get_func_mm_tree(RANGE_OPT_PARAM*, Item_func*, Field*, Item*, Item_result, bool) (opt_range.cc:6119)
==17805== by 0x9C399C: get_full_func_mm_tree(RANGE_OPT_PARAM*, Item_func*, Item_field*, Item*, bool) (opt_range.cc:6219)
==17805== by 0x9C4842: get_mm_tree(RANGE_OPT_PARAM*, Item*) (opt_range.cc:6456)
==17805== by 0x9BB272: SQL_SELECT::test_quick_select(THD*, Bitmap<64u>, unsigned long long, unsigned long long, bool, st_order::enum_order) (opt_range.cc:2830)
==17805== by 0xA216F5: get_quick_record_count(THD*, SQL_SELECT*, TABLE*, Bitmap<64u> const*, unsigned long long) (sql_optimizer.cc:4002)
==17805== by 0xA2098B: make_join_statistics(JOIN*, TABLE_LIST*, Item*, Mem_root_array<Key_use, true>*, bool) (sql_optimizer.cc:3713)
==17805== by 0xA17737: JOIN::optimize() (sql_optimizer.cc:382)
==17805== by 0x84A104: mysql_execute_select(THD*, st_select_lex*, bool) (sql_select.cc:1086)
==17805== by 0x84A490: mysql_select(THD*, TABLE_LIST*, unsigned int, List<Item>&, Item*, SQL_I_List<st_order>*, SQL_I_List<st_order>*, Item*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) (sql_select.cc:1221)
==17805== by 0x9AA1E2: mysql_explain_unit(THD*, st_select_lex_unit*, select_result*) (opt_explain.cc:2132)
==17805== by 0x9A9DAB: explain_query_expression(THD*, select_result*) (opt_explain.cc:2034)
==17805== by 0x81BD15: execute_sqlcom_select(THD*, TABLE_LIST*) (sql_parse.cc:5672)
==17805== by 0x813EAC: mysql_execute_command(THD*) (sql_parse.cc:3010)
==17805== by 0x81EDBD: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:6972)

tags: added: ci valgrind
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

On 5.6, this is an upstream bug.
In 5.7 port-in-progress, this is a Percona Server-only bug.

tags: added: upstream
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

May or may not be related to bug 1067099

Revision history for this message
Yura Sorokin (yura-sorokin) wrote :

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

    TRASH(null_string, key_part->store_length + 1);
    memcpy(null_string, is_null_string, sizeof(is_null_string));

    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.

Revision history for this message
Yura Sorokin (yura-sorokin) wrote :

Another suspicious "memcmp()" is in the "get_constant_key_infix()" function
*****************************************************************
    if (cur_range->maybe_null &&
         cur_range->min_value[0] && cur_range->max_value[0])
    {
      /*
        cur_range specifies 'IS NULL'. In this case the argument points
        to a "null value" (a copy of is_null_string) that we do not
        memcmp(), or memcpy to a field.
      */
      DBUG_ASSERT (field_length > 0);
      *key_ptr= 1;
      key_ptr+= field_length;
      *key_infix_len+= field_length;
    }
    else if (memcmp(cur_range->min_value, cur_range->max_value, field_length) == 0)
    { /* cur_range specifies an equality condition. */
      memcpy(key_ptr, cur_range->min_value, field_length);
      key_ptr+= field_length;
      *key_infix_len+= field_length;
    }
    else
      return false;
*****************************************************************

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

5.5 is now affected too, probably as a result of bug 1588169 fix.

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :
Revision history for this message
Shahriyar Rzayev (rzayev-sehriyar) wrote :

Percona now uses JIRA for bug reports so this bug report is migrated to: https://jira.percona.com/browse/PS-1668

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Duplicates of this bug

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.