Bug #56689 Valgrind warning in print_keyuse() with --debug
Submitted: 9 Sep 2010 12:22 Modified: 22 Nov 2010 1:34
Reporter: Guilhem Bichot Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S3 (Non-critical)
Version:next-mr-bugfixing OS:Linux
Assigned to: Tor Didriksen CPU Architecture:Any

[9 Sep 2010 12:22] Guilhem Bichot
Description:
Using next-mr-bugfixing jorgen.loland@oracle.com-20100909105840-i80sa0637fsimlrc ; I didn't try older versions. BUILD/compile-pentium64-valgrind-max.
Put the queries in "how-to-repeat" in a file named bug.test and run
./mtr --mem bug --debug --valgrind
I get:
==12447== Thread 13:
==12447== Use of uninitialised value of size 8
==12447==    at 0x5B6A85B: _itoa_word (_itoa.c:195)
==12447==    by 0x5B6BB6A: vfprintf (vfprintf.c:1613)
==12447==    by 0x5B75CB7: fprintf (fprintf.c:33)
==12447==    by 0x66CFF2: print_keyuse(keyuse_t*) (sql_test.cc:262)
==12447==    by 0x66D08F: print_keyuse_array(st_dynamic_array*) (sql_test.cc:275)
==12447==    by 0x60B960: update_ref_and_keys(THD*, st_dynamic_array*, st_join_table*, unsigned int, Item*, COND_EQUAL*, unsigned long long, st_select_lex*, st_sargable_param**) (sql_select.cc:6057)
==12447==    by 0x607449: make_join_statistics(JOIN*, TABLE_LIST*, Item*, st_dynamic_array*) (sql_select.cc:4498)
==12447==    by 0x5FF1C7: JOIN::optimize() (sql_select.cc:1813)
==12447==    by 0x7C77EA: subselect_single_select_engine::exec() (item_subselect.cc:2275)
==12447==    by 0x7C18FA: Item_subselect::exec() (item_subselect.cc:311)
==12447==    by 0x7C2A7F: Item_singlerow_subselect::val_int() (item_subselect.cc:670)
==12447==    by 0x75A4CC: Item::send(Protocol*, String*) (item.cc:5894)
==12447==    by 0x55F5EA: Protocol::send_result_set_row(List<Item>*) (protocol.cc:866)
==12447==    by 0x5A66A5: select_send::send_data(List<Item>&) (sql_class.cc:1779)
==12447==    by 0x626B41: end_send(JOIN*, st_join_table*, bool) (sql_select.cc:18121)
==12447==    by 0x623924: do_select(JOIN*, List<Item>*, TABLE*, Procedure*) (sql_select.cc:16569)
==12447== 

How to repeat:
CREATE TABLE C (c int);
INSERT INTO C VALUES (NULL);

CREATE TABLE D (d int , KEY (d));
INSERT INTO D VALUES (NULL),(NULL);

SELECT (SELECT 1 FROM D WHERE d = c) AS RESULT FROM C ;
drop table C,D;

Suggested fix:
I think it's keyuse->ref_table_rows which is not initialized.
Note this fishy code in add_key_part() (just an idea):
	if (field->eq(form->key_info[key].key_part[part].field))
	{
	  keyuse.table= field->table;
	  keyuse.val =  key_field->val;
	  keyuse.key =  key;
	  keyuse.keypart=part;
	  keyuse.keypart_map= (key_part_map) 1 << part;
	  keyuse.used_tables=key_field->val->used_tables();
	  keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL;
          keyuse.null_rejecting= key_field->null_rejecting;
          keyuse.cond_guard= key_field->cond_guard;
          keyuse.sj_pred_no= key_field->sj_pred_no;
	  if (insert_dynamic(keyuse_array,(uchar*) &keyuse))
            return TRUE;
          /* This will be set accordingly in optimize_keyuse */
          keyuse.ref_table_rows= ~(ha_rows) 0;
See: we set ref_table_rows after insert_dynamic(). But insert_dynamic does a memcpy() of keyuse into the dynamic array, so I think (not checked) that, as this copy is taken before ref_table_rows is set, it has its own ref_table_rows random. Maybe?
[9 Sep 2010 12:38] Tor Didriksen
cleanup like so:

        if (field->eq(form->key_info[key].key_part[part].field))
        {
          KEYUSE keyuse;
          keyuse.table=          field->table;
          keyuse.val=            key_field->val;
          keyuse.used_tables=    key_field->val->used_tables();
          keyuse.key=            key;
          keyuse.keypart=        part;
          keyuse.optimize=       key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL;
          keyuse.keypart_map=    (key_part_map) 1 << part;
          /* This will be set accordingly in optimize_keyuse */
          keyuse.ref_table_rows= ~(ha_rows) 0;
          keyuse.null_rejecting= key_field->null_rejecting;
          keyuse.cond_guard=     key_field->cond_guard;
          keyuse.sj_pred_no=     key_field->sj_pred_no;
          if (insert_dynamic(keyuse_array,(uchar*) &keyuse))
            return TRUE;
        }
[10 Sep 2010 7:25] Valeriy Kravchuk
I can not get exactly this warning with current next-mr tree on 32-bit Ubuntu. Maybe difference in environment is the reason.
[10 Sep 2010 14:36] Guilhem Bichot
Hello Miguel. I see in your output:
ERROR SUMMARY: 18 errors from 2 contexts (suppressed: 7 from 7)
so there must be some valgrind errors in /home/miguel/bzr/mr-bugfixing/mysql-test/var/log/mysqld.1.trace ? They always start with "==".
[10 Sep 2010 14:55] MySQL Verification Team
Guilhem..thanks for the warning. I actually got:

==32101== Thread 13:
==32101== Use of uninitialised value of size 8
==32101==    at 0x3342E43DAB: _itoa_word (in /lib64/libc-2.12.so)
==32101==    by 0x3342E44E74: vfprintf (in /lib64/libc-2.12.so)
==32101==    by 0x3342E4EEE7: fprintf (in /lib64/libc-2.12.so)
==32101==    by 0x65B7E8: print_keyuse(keyuse_t*) (sql_test.cc:262)
==32101==    by 0x65B86E: print_keyuse_array(st_dynamic_array*) (sql_test.cc:275)
==32101==    by 0x5FD2C3: update_ref_and_keys(THD*, st_dynamic_array*, st_join_table*, unsigned int, Item*, COND_EQUAL*, unsigned long long, st_select_lex*, st_sargable_param**) (sql_select.cc:6205)
==32101==    by 0x5F8CBA: make_join_statistics(JOIN*, TABLE_LIST*, Item*, st_dynamic_array*) (sql_select.cc:4649)
==32101==    by 0x5F0896: JOIN::optimize() (sql_select.cc:1960)
==32101==    by 0x79FC02: subselect_single_select_engine::exec() (item_subselect.cc:2262)
==32101==    by 0x79A4E6: Item_subselect::exec() (item_subselect.cc:311)
==32101==    by 0x79B419: Item_singlerow_subselect::val_int() (item_subselect.cc:670)
==32101==    by 0x73A9C4: Item::send(Protocol*, String*) (item.cc:5904)
==32101==    by 0x55C3BF: Protocol::send_result_set_row(List<Item>*) (protocol.cc:866)
==32101==    by 0x59DE24: select_send::send_data(List<Item>&) (sql_class.cc:1779)
==32101==    by 0x6185B2: end_send(JOIN*, st_join_table*, bool) (sql_select.cc:18251)
==32101==    by 0x615374: do_select(JOIN*, List<Item>*, TABLE*, Procedure*) (sql_select.cc:16690)
==32101== 
==32101== Conditional jump or move depends on uninitialised value(s)
==32101==    at 0x3342E43DB5: _itoa_word (in /lib64/libc-2.12.so)
==32101==    by 0x3342E44E74: vfprintf (in /lib64/libc-2.12.so)
==32101==    by 0x3342E4EEE7: fprintf (in /lib64/libc-2.12.so)
==32101==    by 0x65B7E8: print_keyuse(keyuse_t*) (sql_test.cc:262)
==32101==    by 0x65B86E: print_keyuse_array(st_dynamic_array*) (sql_test.cc:275)
==32101==    by 0x5FD2C3: update_ref_and_keys(THD*, st_dynamic_array*, st_join_table*, unsigned int, Item*, COND_EQUAL*, unsigned long long, st_select_lex*, st_sargable_param**) (sql_select.cc:6205)
==32101==    by 0x5F8CBA: make_join_statistics(JOIN*, TABLE_LIST*, Item*, st_dynamic_array*) (sql_select.cc:4649)
==32101==    by 0x5F0896: JOIN::optimize() (sql_select.cc:1960)
==32101==    by 0x79FC02: subselect_single_select_engine::exec() (item_subselect.cc:2262)
==32101==    by 0x79A4E6: Item_subselect::exec() (item_subselect.cc:311)
==32101==    by 0x79B419: Item_singlerow_subselect::val_int() (item_subselect.cc:670)
==32101==    by 0x73A9C4: Item::send(Protocol*, String*) (item.cc:5904)
==32101==    by 0x55C3BF: Protocol::send_result_set_row(List<Item>*) (protocol.cc:866)
==32101==    by 0x59DE24: select_send::send_data(List<Item>&) (sql_class.cc:1779)
==32101==    by 0x6185B2: end_send(JOIN*, st_join_table*, bool) (sql_select.cc:18251)
==32101==    by 0x615374: do_select(JOIN*, List<Item>*, TABLE*, Procedure*) (sql_select.cc:16690)
==32101==
[24 Sep 2010 8:24] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/119004

3252 Tor Didriksen	2010-09-24
      Bug #56689  Valgrind warning in print_keyuse() with --debug
      
      Initialize all fields in KEUSE struct before copying it into keyuse_array.
     @ sql/sql_select.cc
        Assigning a value to keyuse.ref_table_rows *after* we have copied the struct
        into the array had no effect, as insert_dynamic() copies by value.
        
        Also re-order lines, to match declaration order of member fields in KEYUSE
        (makes it easier to verify that all fields are indeed initialized)
[28 Sep 2010 12:37] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/119273

3252 Tor Didriksen	2010-09-28
      Bug #56689  Valgrind warning in print_keyuse() with --debug
      
      Initialize all fields in KEUSE struct before copying it into keyuse_array.
     @ sql/sql_select.cc
        Assigning a value to keyuse.ref_table_rows *after* we have copied the struct
        into the array had no effect, as insert_dynamic() copies by value.
        
        Also re-order lines, to match declaration order of member fields in KEYUSE
        (makes it easier to verify that all fields are indeed initialized)
[28 Sep 2010 12:37] Tor Didriksen
Pushed to next-mr-opt-backporting
[13 Nov 2010 16:25] Bugs System
Pushed into mysql-trunk 5.6.99-m5 (revid:alexander.nozdrin@oracle.com-20101113155825-czmva9kg4n31anmu) (version source revid:vasil.dimov@oracle.com-20100629074804-359l9m9gniauxr94) (merge vers: 5.6.99-m4) (pib:21)
[13 Nov 2010 16:36] Bugs System
Pushed into mysql-next-mr (revid:alexander.nozdrin@oracle.com-20101113160336-atmtmfb3mzm4pz4i) (version source revid:jimmy.yang@oracle.com-20100804103744-vbpeghipkz6pyc9z) (pib:21)
[22 Nov 2010 1:18] Paul DuBois
Bug is not in any released 5.6.x version. No changelog entry needed.