]> granicus.if.org Git - php/commitdiff
Merge changes from 5.1 branch.
authorWez Furlong <wez@php.net>
Sun, 11 Sep 2005 05:04:00 +0000 (05:04 +0000)
committerWez Furlong <wez@php.net>
Sun, 11 Sep 2005 05:04:00 +0000 (05:04 +0000)
Add compat header that allows PDO head to compile against PHP 5.0 and PHP 5.1.

ext/pdo/package.xml
ext/pdo/pdo.c
ext/pdo/pdo_dbh.c
ext/pdo/pdo_sql_parser.re
ext/pdo/pdo_stmt.c
ext/pdo/php_pdo_int.h
ext/pdo/php_pdo_phpvers_compat.h [new file with mode: 0644]
ext/pdo/tests/pecl_bug_5217.phpt [new file with mode: 0644]

index 074275cac10f629b7c48cc53165f631ee58a2e92..ce7917fc20a888c142f5fd2501a0596971df8cc0 100755 (executable)
@@ -41,8 +41,8 @@
  <license>PHP</license>
  <release>
   <state>beta</state>
-  <version>0.9</version>
-  <date>2005-07-27</date>
+  <version>1.1dev</version>
+  <date>2005-09-11</date>
 
   <notes>
 You need to install a PDO database driver to make use of PDO,
@@ -100,6 +100,7 @@ numbers when you run your PHP scripts.
    <file role="src" name="pdo_sql_parser.re"/>
    <file role="src" name="pdo_sql_parser.c"/>
    <file role="src" name="pdo_sqlstate.c"/>
+   <file role="src" name="php_pdo_phpvers_compat.h"/>
    <file role="src" name="Makefile.frag"/>
 
    <file role="doc" name="README"/>
index faf2d5e150b7424701b59bf399141c3ade8838fa..fd800ad765c36f49a45fd254d28bdf7d25c3fa5a 100755 (executable)
@@ -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);
index 19407f97a8b621d056ae13f3c32687b654996f3e..fcb98a33940e83f275136b2c8a30876f3568d933 100755 (executable)
@@ -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);
 
index ce982096fb567547ad3a9e35dbce9b9b5cd50067..eeae984573c707ce0266f31eaa182714ec492463 100644 (file)
@@ -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),
index 1060cc3ddf2561bb6c5773da81282c4f60abb40d..4a4e298c5486ae7b5d3bfa6ebed76f18224fe24d 100755 (executable)
@@ -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(&param, 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", &param.paramno, &param.parameter, &param.param_type)) {
+       if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/|l", &param.name,
+               &param.namelen, &param.parameter, &param.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(&param, 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);
 
index 82ccf3826fe3747ad3242e32f5033f856ab4aaa0..f47d1cb7698c64376bfd2e443048c8cec598c54d 100755 (executable)
@@ -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 (file)
index 0000000..6622cf0
--- /dev/null
@@ -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 <wez@php.net>                                    |
+  +----------------------------------------------------------------------+
+*/
+
+/* $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 (file)
index 0000000..75df919
--- /dev/null
@@ -0,0 +1,28 @@
+--TEST--
+PDO Common: PECL Bug #5217: serialize/unserialze safety
+--SKIPIF--
+<?php # vim:ft=php
+if (!extension_loaded('pdo')) die('skip');
+$dir = getenv('REDIR_TEST_DIR');
+if (false == $dir) die('skip no driver');
+require_once $dir . 'pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
+$db = PDOTest::factory();
+try {
+       $ser = serialize($db);
+       debug_zval_dump($ser);
+       $db = unserialize($ser);
+       $db->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!