Skip to content

Commit e87acb8

Browse files
committed
sqlite: fix error checks for column retrieval
These can return NULL on OOM. And for blobs, it can return NULL for empty blobs (so *no* failure, just an edge case). Passing NULL to memcpy is UB, so we have to check for a NULL pointer there to avoid UB.
1 parent 37bb1c3 commit e87acb8

1 file changed

Lines changed: 35 additions & 9 deletions

File tree

ext/sqlite3/sqlite3.c

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ PHP_METHOD(SQLite3, query)
627627
}
628628
/* }}} */
629629

630-
static void sqlite_value_to_zval(sqlite3_stmt *stmt, int column, zval *data) /* {{{ */
630+
static void sqlite_value_to_zval(php_sqlite3_db_object *db_obj, sqlite3_stmt *stmt, int column, zval *data) /* {{{ */
631631
{
632632
sqlite3_int64 val;
633633

@@ -636,7 +636,13 @@ static void sqlite_value_to_zval(sqlite3_stmt *stmt, int column, zval *data) /*
636636
val = sqlite3_column_int64(stmt, column);
637637
#if LONG_MAX <= 2147483647
638638
if (val > ZEND_LONG_MAX || val < ZEND_LONG_MIN) {
639-
ZVAL_STRINGL(data, (char *)sqlite3_column_text(stmt, column), sqlite3_column_bytes(stmt, column));
639+
const char *text = (const char *) sqlite3_column_text(stmt, column);
640+
if (UNEXPECTED(text == NULL)) {
641+
php_sqlite3_error(db_obj, SQLITE_NOMEM, "Failed to retrieve column value due to out of memory");
642+
ZVAL_NULL(data);
643+
} else {
644+
ZVAL_STRINGL(data, text, sqlite3_column_bytes(stmt, column));
645+
}
640646
} else {
641647
#endif
642648
ZVAL_LONG(data, (zend_long) val);
@@ -653,13 +659,33 @@ static void sqlite_value_to_zval(sqlite3_stmt *stmt, int column, zval *data) /*
653659
ZVAL_NULL(data);
654660
break;
655661

656-
case SQLITE3_TEXT:
657-
ZVAL_STRING(data, (char*)sqlite3_column_text(stmt, column));
662+
case SQLITE3_TEXT: {
663+
const char *text = (const char *) sqlite3_column_text(stmt, column);
664+
if (UNEXPECTED(text == NULL)) {
665+
php_sqlite3_error(db_obj, SQLITE_NOMEM, "Failed to retrieve column value due to out of memory");
666+
ZVAL_NULL(data);
667+
} else {
668+
ZVAL_STRING(data, text);
669+
}
658670
break;
671+
}
659672

660673
case SQLITE_BLOB:
661-
default:
662-
ZVAL_STRINGL(data, (char*)sqlite3_column_blob(stmt, column), sqlite3_column_bytes(stmt, column));
674+
default: {
675+
const char *blob = (const char *) sqlite3_column_blob(stmt, column);
676+
if (UNEXPECTED(blob == NULL)) {
677+
if (sqlite3_errcode(sqlite3_db_handle(stmt)) == SQLITE_NOMEM) {
678+
php_sqlite3_error(db_obj, SQLITE_NOMEM, "Failed to retrieve column value due to out of memory");
679+
ZVAL_NULL(data);
680+
} else {
681+
/* Zero-length BLOB */
682+
ZVAL_EMPTY_STRING(data);
683+
}
684+
} else {
685+
ZVAL_STRINGL(data, blob, sqlite3_column_bytes(stmt, column));
686+
}
687+
break;
688+
}
663689
}
664690
}
665691
/* }}} */
@@ -709,13 +735,13 @@ PHP_METHOD(SQLite3, querySingle)
709735
case SQLITE_ROW: /* Valid Row */
710736
{
711737
if (!entire_row) {
712-
sqlite_value_to_zval(stmt, 0, return_value);
738+
sqlite_value_to_zval(db_obj, stmt, 0, return_value);
713739
} else {
714740
int i = 0;
715741
array_init(return_value);
716742
for (i = 0; i < sqlite3_data_count(stmt); i++) {
717743
zval data;
718-
sqlite_value_to_zval(stmt, i, &data);
744+
sqlite_value_to_zval(db_obj, stmt, i, &data);
719745
add_assoc_zval(return_value, (char*)sqlite3_column_name(stmt, i), &data);
720746
}
721747
}
@@ -1973,7 +1999,7 @@ PHP_METHOD(SQLite3Result, fetchArray)
19731999
for (i = 0; i < n_cols; i++) {
19742000
zval data;
19752001

1976-
sqlite_value_to_zval(result_obj->stmt_obj->stmt, i, &data);
2002+
sqlite_value_to_zval(result_obj->db_obj, result_obj->stmt_obj->stmt, i, &data);
19772003

19782004
if (mode & PHP_SQLITE3_NUM) {
19792005
add_index_zval(return_value, i, &data);

0 commit comments

Comments
 (0)