From 1f9cf93cacce03f13adf26465c9ba523cd34578f Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Wed, 6 Oct 2010 11:11:02 +0000 Subject: [PATCH] Fix for Bug #52686 mysql_stmt_attr_[gs]et arg. points to incorrect type --- ext/mysqli/mysqli_api.c | 36 ++++++++++++++++------ ext/mysqli/tests/mysqli_stmt_attr_set.phpt | 6 ++++ ext/mysqlnd/mysqlnd_ps.c | 23 ++++++++------ 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 6ce166713e..8557a1ba89 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -380,11 +380,11 @@ mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval ***args, unsigned int argc, case MYSQL_TYPE_NEWDECIMAL: #endif { -#if MYSQL_VERSION_ID > 50099 +#if MYSQL_VERSION_ID >= 50107 /* Changed to my_bool in MySQL 5.1. See MySQL Bug #16144 */ my_bool tmp; #else - ulong tmp = 0; + uint tmp = 0; #endif stmt->result.buf[ofs].type = IS_STRING; /* @@ -2231,8 +2231,10 @@ PHP_FUNCTION(mysqli_stmt_attr_set) MY_STMT *stmt; zval *mysql_stmt; long mode_in; + my_bool mode_b; ulong mode; ulong attr; + void *mode_p; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode_in) == FAILURE) { return; @@ -2244,11 +2246,22 @@ PHP_FUNCTION(mysqli_stmt_attr_set) RETURN_FALSE; } - mode = mode_in; + switch (attr) { +#if MYSQL_VERSION_ID >= 50107 + case STMT_ATTR_UPDATE_MAX_LENGTH: + mode_b = (my_bool) mode_in; + mode_p = &mode_b; + break; +#endif + default: + mode = mode_in; + mode_p = &mode; + break; + } #if !defined(MYSQLI_USE_MYSQLND) - if (mysql_stmt_attr_set(stmt->stmt, attr, (void *)&mode)) { + if (mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) { #else - if (FAIL == mysql_stmt_attr_set(stmt->stmt, attr, (void *)&mode)) { + if (FAIL == mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) { #endif RETURN_FALSE; } @@ -2262,11 +2275,7 @@ PHP_FUNCTION(mysqli_stmt_attr_get) { MY_STMT *stmt; zval *mysql_stmt; -#if !defined(MYSQLI_USE_MYSQLND) && MYSQL_VERSION_ID > 50099 - my_bool value; -#else ulong value = 0; -#endif ulong attr; int rc; @@ -2278,6 +2287,11 @@ PHP_FUNCTION(mysqli_stmt_attr_get) if ((rc = mysql_stmt_attr_get(stmt->stmt, attr, &value))) { RETURN_FALSE; } + +#if MYSQL_VERSION_ID >= 50107 + if (attr == STMT_ATTR_UPDATE_MAX_LENGTH) + value = *((my_bool *)&value); +#endif RETURN_LONG((long)value); } /* }}} */ @@ -2423,7 +2437,11 @@ PHP_FUNCTION(mysqli_stmt_store_result) stmt->stmt->fields[i].type == MYSQL_TYPE_LONG_BLOB || stmt->stmt->fields[i].type == MYSQL_TYPE_GEOMETRY)) { +#if MYSQL_VERSION_ID >= 50107 my_bool tmp=1; +#else + uint tmp=1; +#endif mysql_stmt_attr_set(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp); break; } diff --git a/ext/mysqli/tests/mysqli_stmt_attr_set.phpt b/ext/mysqli/tests/mysqli_stmt_attr_set.phpt index 82e0121a3c..c2ddd21198 100644 --- a/ext/mysqli/tests/mysqli_stmt_attr_set.phpt +++ b/ext/mysqli/tests/mysqli_stmt_attr_set.phpt @@ -92,6 +92,9 @@ require_once('skipifconnectfailure.inc'); $stmt = mysqli_stmt_init($link); $stmt->prepare("SELECT label FROM test"); $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, 1); + $res = $stmt->attr_get(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH); + if ($res !== 1) + printf("[007.1] max_length should be 1, got %s\n", $res); $stmt->execute(); $stmt->store_result(); $res = $stmt->result_metadata(); @@ -109,6 +112,9 @@ require_once('skipifconnectfailure.inc'); $stmt = mysqli_stmt_init($link); $stmt->prepare("SELECT label FROM test"); $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, 0); + $res = $stmt->attr_get(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH); + if ($res !== 0) + printf("[008.1] max_length should be 0, got %s\n", $res); $stmt->execute(); $stmt->store_result(); $res = $stmt->result_metadata(); diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index 70bcef9e38..cecce5ec43 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -1827,39 +1827,42 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_set)(MYSQLND_STMT * const s, const void * const value TSRMLS_DC) { MYSQLND_STMT_DATA * stmt = s? s->data:NULL; - unsigned long val = *(unsigned long *) value; DBG_ENTER("mysqlnd_stmt::attr_set"); if (!stmt) { DBG_RETURN(FAIL); } - DBG_INF_FMT("stmt=%lu attr_type=%u value=%lu", stmt->stmt_id, attr_type, val); + DBG_INF_FMT("stmt=%lu attr_type=%u", stmt->stmt_id, attr_type); switch (attr_type) { - case STMT_ATTR_UPDATE_MAX_LENGTH: + case STMT_ATTR_UPDATE_MAX_LENGTH:{ + zend_uchar bval = *(zend_uchar *) value; /* XXX : libmysql uses my_bool, but mysqli uses ulong as storage on the stack and mysqlnd won't be used out of the scope of PHP -> use ulong. */ - stmt->update_max_length = val? TRUE:FALSE; + stmt->update_max_length = bval? TRUE:FALSE; break; + } case STMT_ATTR_CURSOR_TYPE: { - if (val > (unsigned long) CURSOR_TYPE_READ_ONLY) { + unsigned int ival = *(unsigned int *) value; + if (ival > (unsigned long) CURSOR_TYPE_READ_ONLY) { SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented"); DBG_INF("FAIL"); DBG_RETURN(FAIL); } - stmt->flags = val; + stmt->flags = ival; break; } case STMT_ATTR_PREFETCH_ROWS: { - if (val == 0) { - val = MYSQLND_DEFAULT_PREFETCH_ROWS; - } else if (val > 1) { + unsigned int ival = *(unsigned int *) value; + if (ival == 0) { + ival = MYSQLND_DEFAULT_PREFETCH_ROWS; + } else if (ival > 1) { SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented"); DBG_INF("FAIL"); DBG_RETURN(FAIL); } - stmt->prefetch_rows = val; + stmt->prefetch_rows = ival; break; } default: -- 2.40.0