From: Wez Furlong Date: Sun, 11 Sep 2005 05:04:00 +0000 (+0000) Subject: Merge changes from 5.1 branch. X-Git-Tag: RELEASE_0_9_0~243 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=434fa24dfa68c16087f6e2b613f35d30807b6fe9;p=php Merge changes from 5.1 branch. Add compat header that allows PDO head to compile against PHP 5.0 and PHP 5.1. --- diff --git a/ext/pdo/package.xml b/ext/pdo/package.xml index 074275cac1..ce7917fc20 100755 --- a/ext/pdo/package.xml +++ b/ext/pdo/package.xml @@ -41,8 +41,8 @@ PHP beta - 0.9 - 2005-07-27 + 1.1dev + 2005-09-11 You need to install a PDO database driver to make use of PDO, @@ -100,6 +100,7 @@ numbers when you run your PHP scripts. + diff --git a/ext/pdo/pdo.c b/ext/pdo/pdo.c index faf2d5e150..fd800ad765 100755 --- a/ext/pdo/pdo.c +++ b/ext/pdo/pdo.c @@ -60,6 +60,13 @@ PDO_API zend_class_entry *php_pdo_get_exception(TSRMLS_D) return U_CLASS_ENTRY(pdo_exception_ce); } +PDO_API char *php_pdo_str_tolower_dup(const char *src, int len) +{ + char *dest = emalloc(len + 1); + zend_str_tolower_copy(dest, src, len); + return dest; +} + zend_class_entry *pdo_dbh_ce, *pdo_dbstmt_ce, *pdo_row_ce; /* proto array pdo_drivers() @@ -112,7 +119,7 @@ zend_module_entry pdo_module_entry = { PHP_RINIT(pdo), PHP_RSHUTDOWN(pdo), PHP_MINFO(pdo), - "0.9", + "1.1dev", STANDARD_MODULE_PROPERTIES }; /* }}} */ @@ -295,6 +302,7 @@ PHP_MINIT_FUNCTION(pdo) le_ppdo = zend_register_list_destructors_ex(NULL, php_pdo_pdbh_dtor, "PDO persistent database", module_number); + REGISTER_LONG_CONSTANT("PDO_PARAM_BOOL", (long)PDO_PARAM_BOOL, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PDO_PARAM_NULL", (long)PDO_PARAM_NULL, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PDO_PARAM_INT", (long)PDO_PARAM_INT, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PDO_PARAM_STR", (long)PDO_PARAM_STR, CONST_CS|CONST_PERSISTENT); diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 19407f97a8..fcb98a3394 100755 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -432,9 +432,11 @@ static void pdo_stmt_construct(pdo_stmt_t *stmt, zval *object, zend_class_entry ZVAL_ASCII_STRINGL(&z_key, "queryString", sizeof("queryString")-1, 0); std_object_handlers.write_property(object, &z_key, query_string TSRMLS_CC); zval_ptr_dtor(&query_string); +#ifdef UG if (UG(unicode)) { zval_dtor(&z_key); } +#endif if (dbstmt_ce->constructor) { zend_fcall_info fci; @@ -504,7 +506,7 @@ static PHP_METHOD(PDO, prepare) if (ZEND_NUM_ARGS() > 1 && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(options), PDO_ATTR_STATEMENT_CLASS, (void**)&opt)) { if (zend_hash_index_find(Z_ARRVAL_PP(opt), 0, (void**)&item) == FAILURE - || (Z_TYPE_PP(item) != IS_STRING && Z_TYPE_PP(item) != IS_UNICODE) + || !PDO_ZVAL_PP_IS_TEXT(item) || zend_u_lookup_class(Z_TYPE_PP(item), Z_UNIVAL_PP(item), Z_UNILEN_PP(item), &pce TSRMLS_CC) == FAILURE ) { pdo_raise_impl_error(dbh, NULL, "HY000", @@ -963,6 +965,21 @@ static PHP_METHOD(PDO, quote) } /* }}} */ +/* {{{ proto int PDO::__wakeup() + Prevents use of a PDO instance that has been unserialized */ +static PHP_METHOD(PDO, __wakeup) +{ + zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "You cannot serialize or unserialize PDO instances"); +} +/* }}} */ + +/* {{{ proto int PDO::__sleep() + Prevents serialization of a PDO instance */ +static PHP_METHOD(PDO, __sleep) +{ + zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "You cannot serialize or unserialize PDO instances"); +} +/* }}} */ function_entry pdo_dbh_functions[] = { PHP_ME_MAPPING(__construct, dbh_constructor, NULL) @@ -977,6 +994,8 @@ function_entry pdo_dbh_functions[] = { PHP_ME(PDO, errorCode, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDO, errorInfo, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDO, getAttribute, NULL, ZEND_ACC_PUBLIC) + PHP_ME(PDO, __wakeup, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) + PHP_ME(PDO, __sleep, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) PHP_ME(PDO, quote, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; @@ -1057,7 +1076,9 @@ static union _zend_function *dbh_method_get( zval *object = *object_pp; #endif pdo_dbh_t *dbh = zend_object_store_get_object(object TSRMLS_CC); - zend_uchar ztype = UG(unicode)?IS_UNICODE:IS_STRING; +#ifdef IS_UNICODE + zend_uchar ztype = UG(unicode) ? IS_UNICODE : IS_STRING; +#endif lc_method_name = zend_u_str_tolower_dup(ztype, method_name, method_len); diff --git a/ext/pdo/pdo_sql_parser.re b/ext/pdo/pdo_sql_parser.re index ce982096fb..eeae984573 100644 --- a/ext/pdo/pdo_sql_parser.re +++ b/ext/pdo/pdo_sql_parser.re @@ -210,8 +210,6 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, plc->freeq = 0; break; - case IS_BOOL: - convert_to_long(param->parameter); case IS_LONG: case IS_DOUBLE: convert_to_string(param->parameter); @@ -220,6 +218,8 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, plc->freeq = 0; break; + case IS_BOOL: + convert_to_long(param->parameter); default: convert_to_string(param->parameter); if (!stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter), diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 1060cc3ddf..4a4e298c54 100755 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -492,6 +492,7 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno TSRMLS_DC case PDO_PARAM_STR: if (value && !(value_len == 0 && stmt->dbh->oracle_nulls == PDO_NULL_EMPTY_STRING)) { +#ifdef IS_UNICODE if (UG(unicode)) { UErrorCode status = U_ZERO_ERROR; UChar *u_str; @@ -502,7 +503,9 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno TSRMLS_DC if (caller_frees) { efree(value); } - } else { + } else +#endif + { ZVAL_STRINGL(dest, value, value_len, !caller_frees); } if (caller_frees) { @@ -643,7 +646,7 @@ static int make_callable_ex(pdo_stmt_t *stmt, zval *callable, zend_fcall_info * object = (zval**)Z_ARRVAL_P(callable)->pListHead->pData; method = (zval**)Z_ARRVAL_P(callable)->pListHead->pListNext->pData; - if (Z_TYPE_PP(object) == IS_STRING || Z_TYPE_PP(object) == IS_UNICODE) { /* static call */ + if (PDO_ZVAL_PP_IS_TEXT(object)) { /* static call */ if (zend_u_lookup_class(Z_TYPE_PP(object), Z_UNIVAL_PP(object), Z_UNILEN_PP(object), &pce TSRMLS_CC) == FAILURE) { pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied class does not exist" TSRMLS_CC); return 0; @@ -658,11 +661,11 @@ static int make_callable_ex(pdo_stmt_t *stmt, zval *callable, zend_fcall_info * return 0; } - if (Z_TYPE_PP(method) != IS_STRING && Z_TYPE_PP(method) != IS_UNICODE) { + if (!PDO_ZVAL_PP_IS_TEXT(method)) { pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied function must be a valid callback; bogus method name" TSRMLS_CC); return 0; } - } else if (Z_TYPE_P(callable) == IS_STRING || Z_TYPE_P(callable) == IS_UNICODE) { + } else if (PDO_ZVAL_P_IS_TEXT(callable)) { method = &callable; } @@ -1258,7 +1261,7 @@ static PHP_METHOD(PDOStatement, fetchAll) /* no break */ case 2: stmt->fetch.cls.ctor_args = ctor_args; /* we're not going to free these */ - if (Z_TYPE_P(arg2) != IS_STRING && Z_TYPE_P(arg2) != IS_UNICODE) { + if (!PDO_ZVAL_P_IS_TEXT(arg2)) { pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Invalid class name (should be a string)" TSRMLS_CC); error = 1; break; @@ -1386,6 +1389,36 @@ static int register_bound_param(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, return really_register_bound_param(¶m, stmt, is_param TSRMLS_CC); } /* }}} */ +/* {{{ proto bool PDOStatement::bindValue(mixed $paramno, mixed $param [, int $type ]) + bind an input parameter to the value of a PHP variable. $paramno is the 1-based position of the placeholder in the SQL statement (but can be the parameter name for drivers that support named placeholders). It should be called prior to execute(). */ +static PHP_METHOD(PDOStatement, bindValue) +{ + pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC); + struct pdo_bound_param_data param = {0}; + + param.paramno = -1; + param.param_type = PDO_PARAM_STR; + + if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, + "lz/|l", ¶m.paramno, ¶m.parameter, ¶m.param_type)) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/|l", ¶m.name, + ¶m.namelen, ¶m.parameter, ¶m.param_type)) { + RETURN_FALSE; + } + } + + if (param.paramno > 0) { + --param.paramno; /* make it zero-based internally */ + } else if (!param.name) { + pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "Columns/Parameters are 1-based" TSRMLS_CC); + RETURN_FALSE; + } + + RETURN_BOOL(really_register_bound_param(¶m, stmt, TRUE TSRMLS_CC)); +} +/* }}} */ + + /* {{{ proto bool PDOStatement::bindParam(mixed $paramno, mixed &$param [, int $type [, int $maxlen [, mixed $driverdata]]]) bind a parameter to a PHP variable. $paramno is the 1-based position of the placeholder in the SQL statement (but can be the parameter name for drivers that support named placeholders). This isn't supported by all drivers. It should be called prior to execute(). */ static PHP_METHOD(PDOStatement, bindParam) @@ -1610,6 +1643,7 @@ fail_out: case PDO_FETCH_BOTH: case PDO_FETCH_OBJ: case PDO_FETCH_BOUND: + case PDO_FETCH_NAMED: break; case PDO_FETCH_COLUMN: @@ -1677,7 +1711,11 @@ fail_out: break; default: - pdo_raise_impl_error(stmt->dbh, stmt, "22003", "mode is out of range" TSRMLS_CC); + if ((mode & ~PDO_FETCH_FLAGS) < PDO_FETCH__MAX && (mode & ~PDO_FETCH_FLAGS) >= 0) { + pdo_raise_impl_error(stmt->dbh, stmt, "22003", "unhandled mode; this is a PDO bug, please report it" TSRMLS_CC); + } else { + pdo_raise_impl_error(stmt->dbh, stmt, "22003", "mode is out of range" TSRMLS_CC); + } return FAILURE; } @@ -1823,12 +1861,28 @@ static PHP_METHOD(PDOStatement, debugDumpParams) } /* }}} */ +/* {{{ proto int PDOStatement::__wakeup() + Prevents use of a PDOStatement instance that has been unserialized */ +static PHP_METHOD(PDOStatement, __wakeup) +{ + zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "You cannot serialize or unserialize PDOStatement instances"); +} +/* }}} */ + +/* {{{ proto int PDOStatement::__sleep() + Prevents serialization of a PDOStatement instance */ +static PHP_METHOD(PDOStatement, __sleep) +{ + zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "You cannot serialize or unserialize PDOStatement instances"); +} +/* }}} */ function_entry pdo_dbstmt_functions[] = { PHP_ME(PDOStatement, execute, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDOStatement, fetch, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDOStatement, bindParam, second_arg_force_ref, ZEND_ACC_PUBLIC) PHP_ME(PDOStatement, bindColumn, second_arg_force_ref, ZEND_ACC_PUBLIC) + PHP_ME(PDOStatement, bindValue, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDOStatement, rowCount, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDOStatement, fetchColumn, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDOStatement, fetchAll, NULL, ZEND_ACC_PUBLIC) @@ -1843,6 +1897,8 @@ function_entry pdo_dbstmt_functions[] = { PHP_ME(PDOStatement, nextRowset, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDOStatement, closeCursor, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDOStatement, debugDumpParams, NULL, ZEND_ACC_PUBLIC) + PHP_ME(PDOStatement, __wakeup, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) + PHP_ME(PDOStatement, __sleep, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) {NULL, NULL, NULL} }; @@ -1853,7 +1909,7 @@ static void dbstmt_prop_write(zval *object, zval *member, zval *value TSRMLS_DC) convert_to_text(member); - if ((Z_UNILEN_P(member) == sizeof("queryString")-1) && (ZEND_U_EQUAL(Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member), "queryString", sizeof("queryString")-1))) { + if (PDO_MEMBER_IS(member, "queryString")) { pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only" TSRMLS_CC); } else { std_object_handlers.write_property(object, member, value TSRMLS_CC); @@ -1866,7 +1922,7 @@ static void dbstmt_prop_delete(zval *object, zval *member TSRMLS_DC) convert_to_text(member); - if ((Z_UNILEN_P(member) == sizeof("queryString")-1) && (ZEND_U_EQUAL(Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member), "queryString", sizeof("queryString")-1))) { + if (PDO_MEMBER_IS(member, "queryString")) { pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only" TSRMLS_CC); } else { std_object_handlers.unset_property(object, member TSRMLS_CC); @@ -1886,7 +1942,9 @@ static union _zend_function *dbstmt_method_get( #if PHP_API_VERSION >= 20041225 zval *object = *object_pp; #endif - zend_uchar ztype = UG(unicode)?IS_UNICODE:IS_STRING; +#ifdef IS_UNICODE + zend_uchar ztype = UG(unicode) ? IS_UNICODE : IS_STRING; +#endif lc_method_name = zend_u_str_tolower_dup(ztype, method_name, method_len); diff --git a/ext/pdo/php_pdo_int.h b/ext/pdo/php_pdo_int.h index 82ccf3826f..f47d1cb769 100755 --- a/ext/pdo/php_pdo_int.h +++ b/ext/pdo/php_pdo_int.h @@ -20,6 +20,8 @@ /* $Id$ */ +#include "php_pdo_phpvers_compat.h" + /* Stuff private to the PDO extension and not for consumption by PDO drivers * */ extern zend_class_entry *pdo_exception_ce; diff --git a/ext/pdo/php_pdo_phpvers_compat.h b/ext/pdo/php_pdo_phpvers_compat.h new file mode 100644 index 0000000000..6622cf0811 --- /dev/null +++ b/ext/pdo/php_pdo_phpvers_compat.h @@ -0,0 +1,56 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2005 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Wez Furlong | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +/* macros for backwards compatibility with PHP 5, so that HEAD of PDO and its + * drivers may still build against PHP 5 */ + +#ifndef PHP_PDO_PHPVERS_COMPAT_H +# define PHP_PDO_PHPVERS_COMPAT_H +# if PHP_MAJOR_VERSION < 6 + +# define ZVAL_RT_STRINGL(a, b, c, d) ZVAL_STRINGL(a, b, c, d) +# define ZVAL_ASCII_STRINGL(a, b, c, d) ZVAL_STRINGL(a, b, c, d) +# define U_CLASS_ENTRY(ce) ce +# define PDO_ZVAL_PP_IS_TEXT(pp) (Z_TYPE_PP(pp) == IS_STRING) +# define PDO_ZVAL_P_IS_TEXT(pp) (Z_TYPE_P(pp) == IS_STRING) +# define Z_UNIVAL_PP(x) Z_STRVAL_PP(x) +# define Z_UNIVAL_P(x) Z_STRVAL_P(x) +# define Z_UNIVAL(x) Z_STRVAL(x) +# define Z_UNILEN_PP(x) Z_STRLEN_PP(x) +# define Z_UNILEN_P(x) Z_STRLEN_P(x) +# define Z_UNILEN(x) Z_STRLEN(x) +# define zend_u_hash_find(a, b, c, d, e) zend_hash_find(a, c, d, e) +# define zend_u_lookup_class(a, b, c, d) zend_lookup_class(b, c, d) +PDO_API char *php_pdo_str_tolower_dup(const char *src, int len); +# define zend_u_str_tolower_dup(a, b, c) php_pdo_str_tolower_dup(b, c) +# define convert_to_text(x) convert_to_string(x) +# define zend_u_fetch_class(a, b, c, d) zend_fetch_class(b, c, d) +# define PDO_MEMBER_IS(z, strlit) ((Z_STRLEN_P(z) == sizeof(strlit)-1) && 0 == strcmp(Z_STRVAL_P(z), strlit)) + +# else + +# define PDO_ZVAL_PP_IS_TEXT(pp) ((Z_TYPE_PP(pp) == IS_STRING) || (Z_TYPE_PP(pp) == IS_UNICODE)) +# define PDO_ZVAL_P_IS_TEXT(pp) ((Z_TYPE_P(pp) == IS_STRING) || (Z_TYPE_P(pp) == IS_UNICODE)) + +# define PDO_MEMBER_IS(z, strlit) ((Z_UNILEN_P(z) == sizeof(strlit)-1) && (ZEND_U_EQUAL(Z_TYPE_P(z), Z_UNIVAL_P(z), Z_UNILEN_P(z), strlit, sizeof(strlit)-1))) + +# endif +#endif + diff --git a/ext/pdo/tests/pecl_bug_5217.phpt b/ext/pdo/tests/pecl_bug_5217.phpt new file mode 100644 index 0000000000..75df91956f --- /dev/null +++ b/ext/pdo/tests/pecl_bug_5217.phpt @@ -0,0 +1,28 @@ +--TEST-- +PDO Common: PECL Bug #5217: serialize/unserialze safety +--SKIPIF-- + +--FILE-- +exec('CREATE TABLE test (id int NOT NULL PRIMARY KEY, val VARCHAR(10))'); +} catch (Exception $e) { + echo "Safely caught " . $e->getMessage() . "\n"; +} + +echo "PHP Didn't crash!\n"; +?> +--EXPECT-- +Safely caught You cannot serialize or unserialize PDO instances +PHP Didn't crash!