Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-19380

ASAN heap-use-after-free in Protocol::net_store_data

Details

    Description

      CREATE TABLE t1 (i int);
      INSERT INTO t1 VALUES (1),(2),(3);
       
      SELECT (SELECT MIN('foo') OVER () FROM t1 LIMIT 1);
      

      10.2 810f014ca7a705381e110cb2664

      ==14283==ERROR: AddressSanitizer: heap-use-after-free on address 0x6190000f8dea at pc 0x7f8196a54935 bp 0x7f817e383b30 sp 0x7f817e3832d8
      READ of size 3 at 0x6190000f8dea thread T27
          #0 0x7f8196a54934 in __asan_memcpy (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x8c934)
          #1 0x558870257c6e in Protocol::net_store_data(unsigned char const*, unsigned long) /10.2/sql/protocol.cc:61
          #2 0x55887025d849 in Protocol::store_string_aux(char const*, unsigned long, charset_info_st const*, charset_info_st const*) /10.2/sql/protocol.cc:1092
          #3 0x55887025e009 in Protocol_text::store(char const*, unsigned long, charset_info_st const*) /10.2/sql/protocol.cc:1129
          #4 0x558870a461be in Item::send(Protocol*, String*) /10.2/sql/item.cc:6893
          #5 0x55887025cf85 in Protocol::send_result_set_row(List<Item>*) /10.2/sql/protocol.cc:979
          #6 0x5588703771bf in select_send::send_data(List<Item>&) /10.2/sql/sql_class.cc:2722
          #7 0x5588704c8f06 in JOIN::exec_inner() /10.2/sql/sql_select.cc:3500
          #8 0x5588704c7d83 in JOIN::exec() /10.2/sql/sql_select.cc:3419
          #9 0x5588704cb0d0 in mysql_select(THD*, TABLE_LIST*, unsigned int, List<Item>&, Item*, unsigned int, st_order*, st_order*, Item*, st_order*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) /10.2/sql/sql_select.cc:3819
          #10 0x5588704aa80e in handle_select(THD*, LEX*, select_result*, unsigned long) /10.2/sql/sql_select.cc:376
          #11 0x558870432322 in execute_sqlcom_select /10.2/sql/sql_parse.cc:6479
          #12 0x55887041f7e8 in mysql_execute_command(THD*) /10.2/sql/sql_parse.cc:3537
          #13 0x55887043aa86 in mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool) /10.2/sql/sql_parse.cc:8013
          #14 0x55887041613b in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool) /10.2/sql/sql_parse.cc:1833
          #15 0x5588704132ba in do_command(THD*) /10.2/sql/sql_parse.cc:1387
          #16 0x55887073bce5 in do_handle_one_connection(CONNECT*) /10.2/sql/sql_connect.cc:1335
          #17 0x55887073b6ed in handle_one_connection /10.2/sql/sql_connect.cc:1241
          #18 0x5588718efa71 in pfs_spawn_thread /10.2/storage/perfschema/pfs.cc:1862
          #19 0x7f819592a6b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9)
          #20 0x7f8194dbf41c in clone (/lib/x86_64-linux-gnu/libc.so.6+0x10741c)
      

      Attachments

        Activity

          varun Varun Gupta (Inactive) added a comment - Patch http://lists.askmonty.org/pipermail/commits/2019-December/014096.html

          Take-aways from yesterday discussion:

          The bug happens because of the following: Item_cache_str::cache_value() calls this:

            value= example->str_result(&value_buff);
          

          The window function makes the passed string object (value_buff) to point to an area in a temporary table's record buffer.
          Then, the temporary table is freed, together with its record buffer.
          Then, Item_cache_str attempts to read the value.

          The cause of the problem is that Item_cache_str::cache_value returns control while Item_cache_str::value_buff is left having its pointer pointing to a string somewhere.

          The fix is to call value_buff.copy(). This will make the value_buff to store its string in a buffer that it owns, which will not disappear unexpectedly.

          psergei Sergei Petrunia added a comment - Take-aways from yesterday discussion: The bug happens because of the following: Item_cache_str::cache_value() calls this: value= example->str_result(&value_buff); The window function makes the passed string object (value_buff) to point to an area in a temporary table's record buffer. Then, the temporary table is freed, together with its record buffer. Then, Item_cache_str attempts to read the value. The cause of the problem is that Item_cache_str::cache_value returns control while Item_cache_str::value_buff is left having its pointer pointing to a string somewhere. The fix is to call value_buff.copy(). This will make the value_buff to store its string in a buffer that it owns, which will not disappear unexpectedly.

          like so:

          diff --git a/sql/item.cc b/sql/item.cc
          index 333d71ddf70..10087ef1974 100644
          --- a/sql/item.cc
          +++ b/sql/item.cc
          @@ -10044,6 +10044,8 @@ bool Item_cache_str::cache_value()
               value_buff.copy(*value);
               value= &value_buff;
             }
          +  else
          +    value_buff.copy();
             return TRUE;
           }
           
          

          psergei Sergei Petrunia added a comment - like so: diff --git a/sql/item.cc b/sql/item.cc index 333d71ddf70..10087ef1974 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -10044,6 +10044,8 @@ bool Item_cache_str::cache_value() value_buff.copy(*value); value= &value_buff; } + else + value_buff.copy(); return TRUE; }

          People

            varun Varun Gupta (Inactive)
            alice Alice Sherepa
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Git Integration

                Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.