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

Server crash in write_full_pages (Aria temp table) via binary-protocol prepared statement string parameter

    XMLWordPrintable

Details

    • Bug
    • Status: Confirmed (View Workflow)
    • Major
    • Resolution: Unresolved
    • 10.11, 11.4, 11.8, 12.3, 13.1, 13.2
    • 10.11, 11.4, 11.8, 12.3, 13.1
    • Can result in hang or crash
    • Crash when a large binary-protocol PS string parameter is materialized into an Aria temporary table (UNION ALL + ORDER BY)

    Description

      Summary

      When a prepared-statement parameter is declared at the protocol level as
      MYSQL_TYPE_STRING (0xfe) and carries a large value (value_bytes * connection
      mbmaxlen > 65535), and that parameter is placed directly into an output column
      of a UNION ALL with a global ORDER BY, the union result is materialized into an
      Aria block-record temporary table. The blob slot of the record written by
      select_unit::write_record() then holds a (length, pointer) pair that does not
      describe a real buffer, and write_full_pages() memcpys from the wild address.
      AddressSanitizer aborts the server; in a non-ASan build this is a read from an
      arbitrary address (server crash, potentially copying arbitrary memory into the
      temporary table).

      Steps to reproduce

      1. Build the server with -DWITH_ASAN=ON (RelWithDebInfo) and start mariadbd.
      2. Run the attached reproduce_report.py (requires python3 and
        mysql-connector-python):

        python3 reproduce_report.py -H 127.0.0.1 -P 3306 -u root
        

      The script creates two tiny InnoDB tables, then sends COM_STMT_PREPARE for:

      select cast(? as signed) as a1, ? as a2, 1 as a3, 1 as a4, 1 as a5,
             cast(? as double) as a6 from t4
      union all (select count(t.c3) - cast(? as signed) as a1, ? as a2,
             t.c9 as a3, t.c3 as a4, count(t.c4) as a5, t.c4 as a6 from t3 t)
      order by a5, a6
      

      and a COM_STMT_EXECUTE whose parameter for output column a2 has protocol type
      byte 0xfe (MYSQL_TYPE_STRING) with a 65536-byte value.

      Note on temp table engine: on current main (since MDEV-38975, HEAP blob
      support) the internal temp table stays in HEAP with default settings, so the
      script forces conversion to Aria with:

      SET SESSION tmp_memory_table_size=1024;
      SET SESSION max_heap_table_size=1024;
      

      Actual result

      mariadbd aborts (AddressSanitizer CHECK failed, "Address is not in memory and
      not in shadow"):

      #8  __interceptor_memcpy
      #9  write_full_pages                 storage/maria/ma_blockrec.c:2170
      #10 write_block_record               storage/maria/ma_blockrec.c:3475
      #11 allocate_and_write_block_record  storage/maria/ma_blockrec.c:3580
      #12 _ma_write_init_block_record      storage/maria/ma_blockrec.c:3620
      #13 maria_write                      storage/maria/ma_write.c:158
      #14 handler::ha_write_tmp_row        sql/sql_class.h:8238
      #15 select_unit::write_record        sql/sql_union.cc:417
      #16 select_unit::send_data           sql/sql_union.cc:161
      #17 select_result_sink::send_data_with_check  sql/sql_class.cc:3381
      ...
      #33 mysqld_stmt_execute              sql/sql_prepare.cc:3407
      

      The full ASan trace is attached (mariadb_error_delta.log).

      Expected result

      The statement executes (or returns an error) without crashing the server.

      Analysis / notes

      • The bug requires the binary protocol: the parameter must arrive with protocol
        type MYSQL_TYPE_STRING (0xfe). SQL-level PREPARE / EXECUTE ... USING,
        CAST/CONVERT and text inlining cannot produce this type handler for a value
        of this size and do NOT reproduce the crash.
      • Size threshold: value_bytes * connection mbmaxlen > 65535 (with utf8mb4,
        16384 bytes suffice).
      • Both UNION branches must scan real tables, and the second branch's aggregate
        plus its column sources are needed to keep the record layout on the
        full-pages path. (With a single shared table, the same root cause surfaces as
        the sibling manifestation in write_tail at ma_blockrec.c:2001.)
      • Root cause: the blob slot of the temp-table record carries a (length,
        pointer) pair that does not describe a real buffer; write_full_pages()
        memcpys from the wild address.
      • Reproduced on 13.2.0-MariaDB-asan @ f6d172c03bf3 (main, 2026-10-21).

      Attachments

        1. mariadb_error_delta.log
          5 kB
          Hongbo Feng
        2. mdev-41741.py
          5 kB
          Shipra Jain
        3. reproduce_report.py
          8 kB
          Hongbo Feng

        Issue Links

          Activity

            People

              Khaled.amr Khaled Amr
              ycybfhb Hongbo Feng
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:

                Time Tracking

                  Estimated:
                  Original Estimate - 0d
                  0d
                  Remaining:
                  Remaining Estimate - 1d
                  1d
                  Logged:
                  Time Spent - Not Specified
                  Not Specified

                  Git Integration

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