Uploaded image for project: 'MariaDB Connector/C'
  1. MariaDB Connector/C
  2. CONC-825

Windows crash in prepared statement execution from unaligned int2store packet writes

    XMLWordPrintable

Details

    • Bug
    • Status: Open (View Workflow)
    • Minor
    • Resolution: Unresolved
    • None
    • None
    • None
    • None

    Description

      [use of codex (AI) was relied on to diagnose the issue via github actions with windows builds and to try and identify relevant source code; apologies if this report ends up not being helpful, but I tried my best to be the human in the loop and reviewing all diagnoses and suggestions]

      Summary

      MariaDB Connector/C 3.4.9 can crash on Windows during prepared statement execution in ma_stmt_execute_generate_simple_request when built with MinGW GCC optimizations. The crash appears to be caused by the Windows/x86 fast-path int2store macro storing through a typed uint16* into a protocol packet byte buffer whose current offset is not guaranteed to satisfy that store's alignment assumptions. GCC's vectorizer can then combine the repeated type writes into aligned SSE stores, producing a faulting movaps instruction on Windows.

      This looks less like a confirmed GCC miscompilation and more like Connector/C relying on undefined behavior / unsafe alignment assumptions that a particular optimized build exposes.

      Affected version

      • MariaDB Connector/C 3.4.9 source
      • Windows builds produced by JuliaPackaging/Yggdrasil's MinGW toolchain
      • The official MariaDB Connector/C 3.4.9 Windows DLL did not reproduce the crash in our diagnostics, likely because that build does not emit the same vectorized aligned-store sequence.

      Symptoms

      Using JuliaDatabases/MySQL.jl with MariaDB_Connector_C_jll 3.4.9+0 on Windows, prepared statement execution crashes with:

      EXCEPTION_ACCESS_VIOLATION
      ma_stmt_execute_generate_simple_request
      

      The failing Yggdrasil-built DLL contains a faulting aligned SSE store in ma_stmt_execute_generate_simple_request:

      movaps xmmword ptr [r11 - 0x10], xmm0
      

      Relevant source locations

      In include/ma_global.h, the Windows/x86 branch uses typed stores for little-endian integer writes:

      #if defined(__i386__) || defined(_WIN32)
      ...
      #define int2store(T,A) *((uint16*) (T))= (uint16) (A)
      

      Current 3.4 branch reference:
      https://github.com/mariadb-corporation/mariadb-connector-c/blob/3.4/include/ma_global.h#L744-L783

      In libmariadb/mariadb_stmt.c, ma_stmt_execute_generate_simple_request allocates a byte buffer and writes the prepared-statement packet. The parameter type loop writes 2 bytes per parameter:

      if (!(start= p= (uchar *)malloc(length)))
        goto mem_error;
       
      int4store(p, stmt->stmt_id);
      p += STMT_ID_LENGTH;
       
      int1store(p, (unsigned char) stmt->flags);
      p++;
       
      int4store(p, 1);
      p+= 4;
       
      ...
       
      size_t null_count= (stmt->param_count + 7) / 8;
      ...
      p += null_count;
       
      int1store(p, stmt->send_types_to_server);
      p++;
       
      ...
       
      for (i = 0; i < stmt->param_count; i++)
      {
        uint buffer_type= stmt->params[i].buffer_type | (stmt->params[i].is_unsigned ? 32768 : 0);
        int2store(p, buffer_type);
        p+= 2;
      }
      

      Current 3.4 branch reference:
      https://github.com/mariadb-corporation/mariadb-connector-c/blob/3.4/libmariadb/mariadb_stmt.c#L772-L828

      For example, with 33 parameters, null_count = (33 + 7) / 8 = 5. The type-info pointer starts at malloc_base + 4 + 1 + 4 + 5 + 1 = malloc_base + 15, so the int2store loop starts from an odd byte offset. The macro casts that uchar* to uint16* and stores through it.

      Diagnostics performed

      In JuliaDatabases/MySQL.jl diagnostics:

      • Released MariaDB_Connector_C_jll 3.4.9+0 crashed on both windows-2022 and windows-2025 GitHub Actions images.
      • Official MariaDB Connector/C 3.4.9 Windows DLL passed on both Windows images.
      • Older MariaDB_Connector_C_jll 3.3.9 passed.
      • A Yggdrasil rebuild of Connector/C 3.4.9 with -fno-tree-vectorize passed on both Windows images.
      • Disassembly of the failing JLL showed the faulting movaps inside ma_stmt_execute_generate_simple_request; the -fno-tree-vectorize rebuild did not contain the vectorized movaps store sequence in that function.

      Diagnostic run:
      https://github.com/JuliaDatabases/MySQL.jl/actions/runs/27571414885

      Original downstream issue:
      https://github.com/JuliaDatabases/MySQL.jl/issues/236

      Yggdrasil workaround PR:
      https://github.com/JuliaPackaging/Yggdrasil/pull/13971

      Suggested upstream fix

      Avoid typed stores through potentially unaligned packet-buffer pointers in this path. Possible fixes include:

      • Make the Windows/x86 int2store implementation byte-wise, like the non-x86 fallback.
      • Use memcpy for the 2-byte store.
      • Use a byte-wise helper specifically for protocol packet construction.

      Julia's binary build is using -fno-tree-vectorize as a downstream workaround, but the root issue appears to be that Connector/C's packet buffer writes do not satisfy the alignment assumptions introduced by the typed uint16* store.

      Attachments

        Issue Links

          Activity

            People

              georg Georg Richter
              jacobquinn_jl Jacob Quinn
              Votes:
              0 Vote for this issue
              Watchers:
              2 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.