HexBrain

MariaDB · Report #3766217

libmariadb ( mariadb-connector-c ): stack overflow via server-controlled field->length in prepared-statement codec

Validstatus
mediumseverity
23upvotes
4 Oct 2026disclosed

How it was found

MariaDB Connector/C (libmariadb) calls alloca() with a length value read directly from the server's column-definition packet without any upper bound. A malicious MariaDB/MySQL server, or a MITM attacker on a non-TLS connection, can set field->length to a value exceeding the process stack size, causing an immediate stack overflow and process crash ( SIGSEGV ).

Vulnerable Code

File: libmariadb/ma_stmt_codec.c, function convert_from_long, line 677

static void convert_from_long(MYSQL_BIND *r_param, const MYSQL_FIELD *field,
                               long long val)
{
  // ...
  default:
    {
      char *buffer;
      buffer = alloca(MAX(field->length, 22));  // <-- no upper bound
      // ...
    }
}

Source of field->length: libmariadb/mariadb_lib.c, line 1171

field->length = (uint) uint4korr(p);  // 4-byte read from server packet, no clamp

The server's column-definition packet contains a 4-byte field->length value that is read verbatim with uint4korr() and stored without any validation. When this value reaches convert_from_long() via the prepared-statement fetch path, alloca() attempts to reserve that many bytes on the stack. Any value exceeding the thread's stack limit (~8MB default) causes SIGSEGV.

Call Chain

mysql_stmt_fetch()
  --> stmt_buffered_fetch() or ma_stmt_execute_packet_read()
    --> madb_update_stmt_fields()
      --> field->length = uint4korr(p)  // server-controlled, no clamp
  --> ma_stmt_fetch_column_as_bind()
    --> field->fetch_func() --> ps_fetch_long()
      --> convert_from_long()
        --> alloca(MAX(field->length, 22))  // BOOM if > stack size

Steps to Reproduce

Prerequisites

  • GCC, libmariadb-dev (any version with prepared-statement support)
  • Python 3 (for the malicious server)

Step 1 - Build the C client

unzip mariadb-c.zip
cd poc
gcc -o client client.c $(mariadb_config --cflags --libs)

Step 2 - Start the malicious server (field_length = 16MB)

python3 malicious_server.py 33995 &

The server implements the minimum MariaDB wire protocol: handshake, auth OK, COM_STMT_PREPARE response with field->length = 0x1000000 (16MB), and COM_STMT_EXECUTE response with a single integer row.

Step 3 - Run the client

./client 33995

Step 4 - Observe the crash

Segmentation fault (core dumped)
Exit code: 139

Step 5 - Control run (field_length = 100)

# Edit malicious_server.py: FIELD_LENGTH = 100
python3 malicious_server.py 33996 &
./client 33996
[client] connecting to 127.0.0.1:33996
[client] connected, server: 5.7.30-malicious
[client] prepared
[client] executed, fetching...
[client] fetch returned 0, value='7' len=1
Exit code: 0

Clean execution - confirms the threshold matches the stack size.

Exploitation conditions:

  • The attacker controls or can impersonate the database server (malicious server, DNS poisoning, ARP spoofing, or MITM on non-TLS connections)
  • No authentication or credentials are required - the malicious field metadata is sent after the handshake in response to COM_STMT_PREPARE
  • No user interaction is required

Affected versions:

  • libmariadb 11.8.6 (Debian/Kali system package) - confirmed
  • MariaDB Connector/C HEAD of 3.4 branch (6ffb335, version 3.4.10-dev) - same vulnerable code
  • MariaDB Connector/C v3.4.9 (64e9fe0) - same vulnerable code
  • All prior versions with prepared-statement support

Suggested Fix

Clamp field->length before it reaches alloca():

// Option 1: clamp at parse time (mariadb_lib.c:1171)
field->length = MIN((uint)uint4korr(p), MAX_FIELD_LENGTH);

// Option 2: clamp at alloca site (ma_stmt_codec.c:677)
size_t buf_len = MAX(field->length, 22);
if (buf_len > MAX_ALLOCA_SIZE)
    buffer = malloc(buf_len);
else
    buffer = alloca(buf_len);

Environment

  • libmariadb 11.8.6 (Debian 1:11.8.6-2)
  • GCC 14.2.0, Linux x86_64
  • Stack limit: 8192 KB (default)
  • Reproduction: 2/2 successful

Impact

A malicious MariaDB/MySQL server, or a network attacker performing MITM on a non-TLS database connection, can crash any application linked against libmariadb that uses prepared statements (mysql_stmt_* API). The crash occurs when the client fetches query results - after the connection is established and the query is executed.

Confirmed impact:

  • Denial of Service: The client process crashes with SIGSEGV (exit 139). Any application using libmariadb prepared statements is terminated immediately.

Reach - affected downstream consumers:

  • PHP mysqli in prepared-statement mode
  • Perl DBD::MariaDB
  • Ruby mysql2 gem
  • Direct C/C++ applications using mysql_stmt_fetch()
  • MariaDB Connector/Python is NOT affected ( uses STMT_ATTR_FIELD_FETCH_CALLBACK override that bypasses this code path )

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original