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

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

    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 DISTINCT dedup)

    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 DISTINCT over a two-table join, the union dedup temporary table
      (Aria, dynamic record format) materializes a row whose blob slot holds a
      (length, pointer) pair that does not describe a real buffer. _ma_rec_pack()
      then 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 (1 row each), then sends
      COM_STMT_PREPARE for:

      select ref_1.c7, ?, 1, ref_1.c2, ref_0.c1, ref_1.c7
      from t1 ref_0 inner join t2 ref_1 on (ref_0.c1 >= ref_1.c1)
      union (select 1,2,3,4,5,6)
      

      and a COM_STMT_EXECUTE whose single parameter has protocol type byte 0xfe
      (MYSQL_TYPE_STRING) with a 32869-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  _ma_rec_pack            storage/maria/ma_dynrec.c:1023
      #10 _ma_write_blob_record   storage/maria/ma_dynrec.c:266
      #11 maria_write             storage/maria/ma_write.c:285
      #12 handler::ha_write_tmp_row  sql/sql_class.h:8238
      #13 select_unit::write_record  sql/sql_union.cc:417
      #14 select_unit::send_data     sql/sql_union.cc:161
      #15 select_result_sink::send_data_with_check  sql/sql_class.cc:3381
      #16 end_send                  sql/sql_select.cc:26975
      #17 JOIN_CACHE::generate_full_extensions  sql/sql_join_cache.cc:2538
      ...
      #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. COM_STMT_EXECUTE flags are
        irrelevant.
      • Size threshold: value_bytes * connection mbmaxlen > 65535 (with utf8mb4,
        16384 bytes suffice).
      • Trigger requirements (verified by ablation): UNION DISTINCT (UNION ALL does
        not crash), >= 6 projection columns (5 do not crash), a two-table join
        (join-cache path), real tables (1 row each suffices), and the parameter value
        carried straight into a UNION output column.
      • Root cause: the blob slot of the temp-table record carries a (length,
        pointer) pair that does not describe a real buffer; _ma_rec_pack() 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-41742.py
          6 kB
          Shipra Jain
        3. reproduce_report.py
          7 kB
          Hongbo Feng

        Activity

          People

            psergei Sergei Petrunia
            ycybfhb Hongbo Feng
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:

              Git Integration

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