]> granicus.if.org Git - php/commitdiff
Fix #64705 errorInfo property of PDOException is null when PDO::__construct() fails
authorAhmed Abdou <email@ahmed.ro>
Sun, 17 Feb 2019 21:59:00 +0000 (22:59 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 11 Aug 2020 15:12:48 +0000 (17:12 +0200)
PDO driver constructors are throwing PdoException without setting
errorInfo, so create a new reusable function that throws exceptions
for PDO and will also set the errorInfo. Use this function in
pdo_mysql, pdo_sqlite, and pdo_pgsql.

NEWS
ext/pdo/pdo_dbh.c
ext/pdo/php_pdo_driver.h
ext/pdo_mysql/mysql_driver.c
ext/pdo_mysql/tests/bug_64705.phpt [new file with mode: 0644]
ext/pdo_pgsql/pgsql_driver.c
ext/pdo_pgsql/tests/bug_64705.phpt [new file with mode: 0644]
ext/pdo_sqlite/sqlite_driver.c
ext/pdo_sqlite/tests/bug_64705.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index d79a06a2bb3c6ea89ae5ccb5848bbcd082180822..178785e884be54935dd5849836d43070edafbd51 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -31,6 +31,10 @@ PHP                                                                        NEWS
   . Fixed bug #73060 (php failed with error after temp folder cleaned up).
     (cmb)
 
+- PDO:
+  . Fixed bug #64705 (errorInfo property of PDOException is null when
+    PDO::__construct() fails). (Ahmed Abdou)
+
 - Standard:
   . Fixed bug #79930 (array_merge_recursive() crashes when called with array
     with single reference). (Nikita)
index 36bb2a17aca1f7e115162b7c226063e40d5c893e..4df9db11de13e7a4fa7c7d6e9e2f7d9eb2f2c847 100644 (file)
 
 static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value);
 
+void pdo_throw_exception(unsigned int driver_errcode, char *driver_errmsg, pdo_error_type *pdo_error)
+{
+               zval error_info,pdo_exception;
+               char *pdo_exception_message;
+
+               object_init_ex(&pdo_exception, php_pdo_get_exception());
+               array_init(&error_info);
+
+               add_next_index_string(&error_info, *pdo_error);
+               add_next_index_long(&error_info, driver_errcode);
+               add_next_index_string(&error_info, driver_errmsg);
+
+               spprintf(&pdo_exception_message, 0,"SQLSTATE[%s] [%d] %s",*pdo_error, driver_errcode, driver_errmsg);
+               zend_update_property(php_pdo_get_exception(), &pdo_exception, "errorInfo", sizeof("errorInfo")-1, &error_info);
+               zend_update_property_long(php_pdo_get_exception(), &pdo_exception, "code", sizeof("code")-1, driver_errcode);
+               zend_update_property_string(
+                       php_pdo_get_exception(),
+                       &pdo_exception,
+                       "message",
+                       sizeof("message")-1,
+                       pdo_exception_message
+               );
+               efree(pdo_exception_message);
+               zval_ptr_dtor(&error_info);
+               zend_throw_exception_object(&pdo_exception);
+}
+
 void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *sqlstate, const char *supp) /* {{{ */
 {
        pdo_error_type *pdo_err = &dbh->error_code;
index 3350211a5e4d196016813df7064dc943fb7fe887..b002c3e5f306c16aa216ab9e852eea3f93edf442 100644 (file)
@@ -691,6 +691,7 @@ PDO_API void php_pdo_dbh_delref(pdo_dbh_t *dbh);
 PDO_API void php_pdo_free_statement(pdo_stmt_t *stmt);
 
 
+PDO_API void pdo_throw_exception(unsigned int driver_errcode, char *driver_errmsg, pdo_error_type *pdo_error);
 #endif /* PHP_PDO_DRIVER_H */
 /*
  * Local variables:
index 6431ccf4e14ba5782fd1bf575b2045875e553aa0..6efa0fc6204a48b57a40b27162be60ba5b170cd5 100644 (file)
@@ -103,8 +103,7 @@ int _pdo_mysql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int lin
 
        if (!dbh->methods) {
                PDO_DBG_INF("Throwing exception");
-               zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode, "SQLSTATE[%s] [%d] %s",
-                               *pdo_err, einfo->errcode, einfo->errmsg);
+               pdo_throw_exception(einfo->errcode, einfo->errmsg, pdo_err);
        }
 
        PDO_DBG_RETURN(einfo->errcode);
diff --git a/ext/pdo_mysql/tests/bug_64705.phpt b/ext/pdo_mysql/tests/bug_64705.phpt
new file mode 100644 (file)
index 0000000..53e7975
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Bug #64705 errorInfo property of PDOException is null when PDO::__construct() fails
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_mysql')) print 'skip not loaded';
+?>
+--FILE--
+<?php
+$dsn = 'mysql:host=DonotExistsHost;dbname=test;user=foo;password=wrongpass';
+try {
+  $pdo = new \PDO($dsn, null, null);
+} catch (\PDOException $e) {
+  var_dump(!empty($e->errorInfo) && is_array($e->errorInfo));
+}
+?>
+--EXPECTF--
+bool(true)
\ No newline at end of file
index 89dd55167ee19328cf2bc117616c6c292d13c588..794730a225442b414ea9bde68dad72be5800f067 100644 (file)
@@ -101,8 +101,7 @@ int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char *
        }
 
        if (!dbh->methods) {
-               zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode, "SQLSTATE[%s] [%d] %s",
-                               *pdo_err, einfo->errcode, einfo->errmsg);
+               pdo_throw_exception(einfo->errcode, einfo->errmsg, pdo_err);
        }
 
        return errcode;
diff --git a/ext/pdo_pgsql/tests/bug_64705.phpt b/ext/pdo_pgsql/tests/bug_64705.phpt
new file mode 100644 (file)
index 0000000..464b4d0
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Bug #64705 errorInfo property of PDOException is null when PDO::__construct() fails
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_pgsql')) print 'skip not loaded';
+?>
+--FILE--
+<?php
+$dsn = 'pgsql:host=DonotExistsHost;dbname=test;user=foo;password=wrongpass';
+try {
+  $pdo = new \PDO($dsn, null, null);
+} catch (\PDOException $e) {
+  var_dump(!empty($e->errorInfo) && is_array($e->errorInfo));
+}
+?>
+--EXPECTF--
+bool(true)
\ No newline at end of file
index 2cc7f72475317cacbdc60df19f1aa9f54427f8fd..3d85a6db106e3c17c1e35fa469a6080d134654ce 100644 (file)
@@ -76,8 +76,7 @@ int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int li
        }
 
        if (!dbh->methods) {
-               zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode, "SQLSTATE[%s] [%d] %s",
-                               *pdo_err, einfo->errcode, einfo->errmsg);
+               pdo_throw_exception(einfo->errcode, einfo->errmsg, pdo_err);
        }
 
        return einfo->errcode;
diff --git a/ext/pdo_sqlite/tests/bug_64705.phpt b/ext/pdo_sqlite/tests/bug_64705.phpt
new file mode 100644 (file)
index 0000000..861a99f
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Bug #64705 errorInfo property of PDOException is null when PDO::__construct() fails
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_sqlite')) print 'skip not loaded';
+?>
+--FILE--
+<?php
+$dsn = 'sqlite:./bug64705NonExistingDir/bug64705NonExistingDb';
+try {
+  $pdo = new \PDO($dsn, null, null);
+} catch (\PDOException $e) {
+  var_dump(!empty($e->errorInfo) && is_array($e->errorInfo));
+}
+?>
+--EXPECTF--
+bool(true)
\ No newline at end of file