Hello, I discovered a security issue in the SQLite3 DBD driver of apr-util (version 1.6.3, and it also exists in the current trunk).
The function dbd_sqlite3_bind() in apr_dbd_sqlite3.c reads a blob size via atoi() from a user-supplied string and passes it directly to sqlite3_bind_blob() without any validation against the actual length of the data buffer. An attacker can supply a size larger than the real data length, causing an out‑of‑bounds read when SQLite copies the blob. This may lead to information disclosure or a crash (DoS). The issue affects the text‑based BLOB binding path (pquery/pselect family). Binary BLOB binding (pbquery/pbselect) is not affected by this specific code path, but it also lacks validation (a separate issue). The proposed patch adds a safety check: if the announced size exceeds strlen(data), the parameter is bound as NULL instead of a blob. This prevents the OOB read and falls back to a safe behavior. This change assumes that text‑based BLOB bindings are only used for textual data (the common case). For genuine binary data, callers should migrate to the binary bind functions (pbquery/pbselect), which already expect a binary size argument. The patch follows the Apache C Language Style Guide (4‑space indent, no tabs, brace placement, spacing around operators). Please review and consider applying. Thank you, Max Lane <[email protected]> --- Index: dbd/apr_dbd_sqlite3.c =================================================================== --- dbd/apr_dbd_sqlite3.c (working copy) +++ dbd/apr_dbd_sqlite3.c (working copy) @@ -458,7 +458,22 @@ char *data = (char *)values[j]; int size = atoi((char*)values[++j]); /* skip table and column */ j += 2; - sqlite3_bind_blob(stmt, i + 1, data, size, SQLITE_STATIC); + /* + * Validate that the announced size does not exceed the actual + * length of the data. Otherwise an attacker could cause an + * out-of-bounds read in sqlite3_bind_blob(). + * + * For binary BLOB data the binary bind functions + * (pbquery/pbselect) should be used instead. + */ + if (size > (int)strlen(data)) { + sqlite3_bind_null(stmt, i + 1); + } + else { + sqlite3_bind_blob(stmt, i + 1, data, size, SQLITE_STATIC); + } } break;
