php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #44352 mysqli_connect_error() false negative for host errors
Submitted: 2008-03-06 17:35 UTC Modified: 2008-03-18 17:01 UTC
From: stein at visibone dot com Assigned: andrey (profile)
Status: Closed Package: MySQLi related
PHP Version: 5.2.5 OS: Windows 2000
Private report: No CVE-ID: None
 [2008-03-06 17:35 UTC] stein at visibone dot com
Description:
------------
If you don't like this cramming of 4 bugs in 1, please consider this solely a report of bug #1 which is the most serious.  Fix the first two assert()'s in the reproduce code and call it a solved.

I think the mysqli connect-time error handling has a lot of bugs.  I hope you'll bear with this report of 4 separate bugs.  They all contribute to a very difficult time for PHP code to detect connection failure (as opposed humans detecting it from warning messages in the output).  I hope someone will find this a useful analysis of what goes wrong when connections go wrong. 

Bug #1: a bad host (misspelled domain, server down) can't be detected by mysqli_connect_error() or mysqli_connect_errno() -- they return empty string and zero.  I have a hunch that in bug #30051 he actually detected this problem at first, but then he brought up his server on localhost and it went away so he closed his submission.  I think bug #31163 reported this problem and then died of neglect.  Bug #31745 may have suffered from it, but it seems to be more about exceptions versus error messages. 

Again, bug 1 is the most serious.  It breaks Example#1 on http://www.php.net/manual/en/function.mysqli-connect.php when there's no MySQL server running on localhost.  Bugs 2,3,4 make workarounds hard.

Bug #2: the object oriented constructor "new mysqli" never returns FALSE.  This was reported in bug #32818 but waived off as a non-bug without explanation.  The documentation for this constructor is smooshed in with that of mysqli_connect(), where it states "Returns ... FALSE if the connection failed".  So I believe bug #32818 was not bogus, or the documentation is.

Bug #3 $mysqli->error member never passes the isset() nor property_exists() tests.  Not when the connection fails, nor when it works, nor after a good query, nor a bad.  Maybe all mysqli properties suffer from this.  The reproduce code demonstrates the same lapse for mysqli::error, mysqli::errno, and mysqli_result::num_rows.  So this may be a defect of mysqli or some faux pas of the PHP5 object model itself.  I could find no existing bug that described it.

Bug #4 mysqli object limbo.  Connection failure is undetectable without generating a warning.  "new mysql" returns what is by every diagnostic a mysqli object. (get_class(), instanceof, and is_a() all say it is.)  But if the connection failed, doing anything with the instance will give you the ubiquitous and inscrutible "Couldn't fetch mysqli" warning.

Drastic workaround for object oriented (works around all four bugs):

     $mysqli = @new mysqli(...);
     if (NULL === @$mysqli->error) {
          die('connect fail: ' . mysqli_connect_error());
     }

This may break someday.  It's undocumented what the error member should do if the connection succeeds, but it acually does become the empty string.

Gentle workaround for procedural, same as Example #2 in mysqli_connect() manual page:

     $link = @mysqli_connect(...);
     if (FALSE === $link) {
          die('connect fail: ' . mysqli_connect_error());
     }

Although in either case the message will be blank for host errors.

I believe bug 1 is the serious one.  Classic mysql_connect() doesn't make this mistake.  Bugs 2,3,4 are relatively minor quirks of the object model.  All four bugs together make connection errors difficult to detect in the code.

Reproduce code:
---------------
http://www.visibone.com/php/mysqli_connect_bugs.php.txt

If you find this too verbose, please concentrate on the first two assert()'s.  Fix them and I'd call this issue closed.

Expected result:
----------------
Many of the assert()'s should fail, especially the ones commented "// BUG"

Actual result:
--------------
Testing... 2 tables ...Done.

(or a different number of tables)

I.e. no warnings, all assert()'s pass.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-03-08 22:26 UTC] johannes@php.net
Assigned to primary maintainer
 [2008-03-10 19:15 UTC] andrey@php.net
I can't reproduce the problem with mysqli/libmysql - neither 5.2 nor 5.3-dev. However, I saw it with mysqli/mysqlnd, which is due to a bug in PHP's streams. I will fix the bug. Can you give more information?
I am using mysql 5.1.24-rc server and client library (+headers). Libmysql reports a problem in the resolution of `bogushost.com`
I haven't still checked the problem with isset($mysqli->error)

andrey@whirlpool:~/dev/php5_3> ./php -r 'var_dump(mysqli_get_client_info());$c=new mysqli("bogushost.com");var_dump(mysqli_connect_error());'
string(9) "5.1.24-rc"

Warning: mysqli::mysqli(): (HY000/2005): Unknown MySQL server host 'bogushost.com' (1) in Command line code on line 1
string(45) "Unknown MySQL server host 'bogushost.com' (1)"

--------------------------------------------------------------

andrey@whirlpool:~/dev/vanilla/php5_2> ./php -r 'var_dump(mysqli_get_client_info());$c=new mysqli("bogushost.com");var_dump(mysqli_connect_error());'
string(9) "5.1.24-rc"

Warning: mysqli::mysqli(): (HY000/2005): Unknown MySQL server host 'bogushost.com' (1) in Command line code on line 1
string(45) "Unknown MySQL server host 'bogushost.com' (1)"

--------------------------------------------------------------

 [2008-03-11 09:40 UTC] stein at visibone dot com
Good test case.  For windows command line I swapped the quote marks.  With warnings suppressed I get:

C:\>php -r "var_dump(mysqli_get_client_info());$c=@new mysqli('bogushost.com');var_dump(mysqli_connect_error());"

string(46) "mysqlnd 5.0.1-beta - 070402 - $Revision: 321 $"
string(0) ""
 [2008-03-11 09:49 UTC] stein at visibone dot com
...and with warnings (no @ sign) I get:

string(46) "mysqlnd 5.0.1-beta - 070402 - $Revision: 321 $"
PHP Warning:  mysqli::mysqli(): php_network_getaddresses: getaddrinfo failed: No such host is known.  in Command line code on line 1

Warning: mysqli::mysqli(): php_network_getaddresses: getaddrinfo failed: No such host is known.  in Command line code on line 1
PHP Warning:  mysqli::mysqli(): (00000/0):  in Command line code on line 1

Warning: mysqli::mysqli(): (00000/0):  in Command line code on line 1
string(0) ""
 [2008-03-18 17:01 UTC] andrey@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

Fixed in 5.3 & HEAD
 
PHP Copyright © 2001-2022 The PHP Group
All rights reserved.
Last updated: Tue Jan 18 14:03:13 2022 UTC