MariaDB · Report #3910393
Stack Buffer Overflow in MariaDB CONNECT storage engine when reading DOUBLE columns from TABLE_TYPE=DOS tables
How it was found
This problem is located in storage/connect/value.cpp, function TYPVAL<double>::SetValue_char(). The function copies at most 31 bytes into a 64-byte stack buffer, but subsequently places the terminating "\0" byte using the original field length (n) instead of the bounded length.
bool TYPVAL<double>::SetValue_char(const char *p, int n){
if (p && n > 0) {
char buf[64];
for (; n > 0 && *p == ' '; p++)
n--;
memcpy(buf, p, MY_MIN(n, 31));
buf[n] = '\0';
When a DOUBLE(M,D) column is read back from a TABLE_TYPE='DOS' file, TYPVAL<double>::SetValue_char() copies the textual field into a 64-byte stack buffer, and then writes the terminating NUL byte at index n , where n is the SQL-declared field width, not the bounded copy length. The memcpy() that fills the buffer is correctly clamped with MY_MIN(n, 31), but the terminator buf[n] = '\0' is not clamped at all.
Because the SQL layer accepts widths up to 255, the C layer ends up executing buf[255] = '\0' on a 64-byte buffer, a single-byte (0x00) write up to 191 bytes past its end (for example).
Call chain:
- DOUBLE(255,30) is accepted by the SQL layer and field_length becomes 255 (sql/field.cc)
- CONNECT copies the declared width unchanged (ha_connect.cc)
- That length becomes the column's Long field, again unchanged (reldef.cpp, colblk.cpp, tabdos.cpp)
- DOSCOL::ReadColumn() assigns field = Long and passes it straight into the value parser (tabdos.cpp)
case TYPE_DOUBLE:
if (!(err = Value->SetValue_char(p, field))) {
PoC:
- Build with ASAN
- Run PoC.sh script (trigger + config inline in its launch flags)
Dockerfile: https://gist.github.com/dldLambda/58ad85abfb9bc65d661a69faba7523e0 PoC.sh script: https://gist.github.com/dldLambda/f4bc2a9c343bb28404989dba2628d2bf
Under ASAN, the server reports a stack-buffer-overflow write of 1 byte at the buf[n] = '\0' line in TYPVAL<double>::SetValue_char Without ASAN, the server crashes
Impact
Attacker can trigger a Denial of Service by crashing the MariaDB server.