Fixing a leak in mysqlnd when passing invalid fetch modes to mysqlnd.

This commit is contained in:
Ulf Wendel 2009-09-30 14:39:33 +00:00
parent 59dc338ac2
commit d79cba2afd
3 changed files with 13 additions and 17 deletions

View file

@ -2012,7 +2012,7 @@ static void php_mysql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type,
} }
} }
if ((result_type & MYSQL_BOTH) == 0) { if (result_type & ~MYSQL_BOTH) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The result type should be either MYSQL_NUM, MYSQL_ASSOC or MYSQL_BOTH"); php_error_docref(NULL TSRMLS_CC, E_WARNING, "The result type should be either MYSQL_NUM, MYSQL_ASSOC or MYSQL_BOTH");
result_type = MYSQL_BOTH; result_type = MYSQL_BOTH;
} }
@ -2200,6 +2200,11 @@ PHP_FUNCTION(mysql_fetch_array)
} }
ZEND_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, -1, "MySQL result", le_result); ZEND_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, -1, "MySQL result", le_result);
if (mode & ~MYSQL_BOTH) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The result type should be either MYSQL_NUM, MYSQL_ASSOC or MYSQL_BOTH");
mode = MYSQL_BOTH;
}
mysqlnd_fetch_into(result, mode, return_value, MYSQLND_MYSQL); mysqlnd_fetch_into(result, mode, return_value, MYSQLND_MYSQL);
#endif #endif
} }

View file

@ -56,7 +56,7 @@ exit(1);
do { do {
$illegal_mode = mt_rand(0, 10000); $illegal_mode = mt_rand(0, 10000);
} while (in_array($illegal_mode, array(MYSQL_ASSOC, MYSQL_NUM, MYSQL_BOTH))); } while (in_array($illegal_mode, array(MYSQL_ASSOC, MYSQL_NUM, MYSQL_BOTH)));
$tmp = @mysql_fetch_array($res, $illegal_mode); $tmp = mysql_fetch_array($res, $illegal_mode);
if (!is_array($tmp)) if (!is_array($tmp))
printf("[013] Expecting array, got %s/%s. [%d] %s\n", printf("[013] Expecting array, got %s/%s. [%d] %s\n",
gettype($tmp), $tmp, mysql_errno($link), mysql_error($link)); gettype($tmp), $tmp, mysql_errno($link), mysql_error($link));
@ -355,5 +355,7 @@ array(11) {
%unicode|string%(1) "1" %unicode|string%(1) "1"
} }
Warning: mysql_fetch_array(): The result type should be either MYSQL_NUM, MYSQL_ASSOC or MYSQL_BOTH in %s on line %d
Warning: mysql_fetch_array(): %d is not a valid MySQL result resource in %s on line %d Warning: mysql_fetch_array(): %d is not a valid MySQL result resource in %s on line %d
done! done!

View file

@ -901,13 +901,8 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag
lengths[i] = len; lengths[i] = len;
} }
/* Forbid ZE to free it, we will clean it */
Z_ADDREF_P(data);
if ((flags & MYSQLND_FETCH_BOTH) == MYSQLND_FETCH_BOTH) {
Z_ADDREF_P(data);
}
if (flags & MYSQLND_FETCH_NUM) { if (flags & MYSQLND_FETCH_NUM) {
Z_ADDREF_P(data);
zend_hash_next_index_insert(row_ht, &data, sizeof(zval *), NULL); zend_hash_next_index_insert(row_ht, &data, sizeof(zval *), NULL);
} }
if (flags & MYSQLND_FETCH_ASSOC) { if (flags & MYSQLND_FETCH_ASSOC) {
@ -918,6 +913,7 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag
the index is a numeric and convert it to it. This however means constant the index is a numeric and convert it to it. This however means constant
hashing of the column name, which is not needed as it can be precomputed. hashing of the column name, which is not needed as it can be precomputed.
*/ */
Z_ADDREF_P(data);
if (zend_hash_key->is_numeric == FALSE) { if (zend_hash_key->is_numeric == FALSE) {
#if PHP_MAJOR_VERSION >= 6 #if PHP_MAJOR_VERSION >= 6
zend_u_hash_quick_update(Z_ARRVAL_P(row), IS_UNICODE, zend_u_hash_quick_update(Z_ARRVAL_P(row), IS_UNICODE,
@ -1128,16 +1124,8 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES *result, void *param, unsigned int flags,
for (i = 0; i < result->field_count; i++, field++, zend_hash_key++) { for (i = 0; i < result->field_count; i++, field++, zend_hash_key++) {
zval *data = current_row[i]; zval *data = current_row[i];
/*
Let us later know what to do with this zval. If ref_count > 1, we will just
decrease it, otherwise free it. zval_ptr_dtor() make this very easy job.
*/
Z_ADDREF_P(data);
if ((flags & MYSQLND_FETCH_BOTH) == MYSQLND_FETCH_BOTH) {
Z_ADDREF_P(data);
}
if (flags & MYSQLND_FETCH_NUM) { if (flags & MYSQLND_FETCH_NUM) {
Z_ADDREF_P(data);
zend_hash_next_index_insert(Z_ARRVAL_P(row), &data, sizeof(zval *), NULL); zend_hash_next_index_insert(Z_ARRVAL_P(row), &data, sizeof(zval *), NULL);
} }
if (flags & MYSQLND_FETCH_ASSOC) { if (flags & MYSQLND_FETCH_ASSOC) {
@ -1148,6 +1136,7 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES *result, void *param, unsigned int flags,
the index is a numeric and convert it to it. This however means constant the index is a numeric and convert it to it. This however means constant
hashing of the column name, which is not needed as it can be precomputed. hashing of the column name, which is not needed as it can be precomputed.
*/ */
Z_ADDREF_P(data);
if (zend_hash_key->is_numeric == FALSE) { if (zend_hash_key->is_numeric == FALSE) {
#if PHP_MAJOR_VERSION >= 6 #if PHP_MAJOR_VERSION >= 6
zend_u_hash_quick_update(Z_ARRVAL_P(row), IS_UNICODE, zend_u_hash_quick_update(Z_ARRVAL_P(row), IS_UNICODE,