php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71863 Segfault when EXPLAIN with "Unknown column" error
Submitted: 2016-03-20 19:31 UTC Modified: 2016-07-22 21:33 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:1 (50.0%)
From: Azq2 at ya dot ru Assigned: andrey (profile)
Status: Closed Package: MySQLi related
PHP Version: master-Git-2016-03-20 (Git) OS: Ubuntu 14.04
Private report: No CVE-ID: None
 [2016-03-20 19:31 UTC] Azq2 at ya dot ru
Description:
------------
If execute "explain ..." query with non-existent keys - occure segfault.

(my english very ugly, i from Ukraine)

Test script:
---------------
<?php
	$req = mysqli_connect('127.0.0.1', 'root', 'qwerty'); // <-- must be valid mysql server and user/password
	
	// create db and table for test
	mysqli_query($req, "CREATE DATABASE IF NOT EXISTS test42") or die(mysqli_error($req));
	mysqli_select_db($req, 'test42') or die(mysqli_error($req));
	mysqli_query($req, "DROP TABLE IF EXISTS users") or die(mysqli_error($req));
	mysqli_query($req, "CREATE TABLE users (id INT UNSIGNED NOT NULL DEFAULT 0)") or die(mysqli_error($req));
	
	// segfault if EXPLAIN + "Unknown column" error
	mysqli_query($req, "EXPLAIN SELECT `id` FROM `users` WHERE `owner_id` = '2' AND `object_id` = '1' AND type = '0'") or die(mysqli_error($req));


Expected result:
----------------
$ php -v
PHP 5.5.17 (cli) (built: Sep 21 2014 19:56:50) 
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2014, by Zend Technologies

$ php 1111.php
PHP Warning:  mysqli_query(): (42S22/1054): Unknown column 'owner_id' in 'where clause' in /root/1111.php on line 11

Warning: mysqli_query(): (42S22/1054): Unknown column 'owner_id' in 'where clause' in /root/1111.php on line 11
Unknown column 'owner_id' in 'where clause'

Actual result:
--------------
(gdb) bt
#0  0x0000000000791fc4 in mysqlnd_mysqlnd_res_store_result_fetch_data_pub (
    conn=0x7fffee66b008, result=<optimized out>, meta=<optimized out>, 
    row_buffers=0x7fffee67c008, binary_protocol=<optimized out>)
    at /home/azq2/build/php-src/ext/mysqlnd/mysqlnd_result.c:1394
#1  0x0000000000794dde in mysqlnd_mysqlnd_res_store_result_pub (
    result=0x7fffee65c8c8, conn=0x7fffee66b008, flags=<optimized out>)
    at /home/azq2/build/php-src/ext/mysqlnd/mysqlnd_result.c:1445
#2  0x0000000000782238 in mysqlnd_mysqlnd_conn_data_store_result_pub (
    conn=0x7fffee66b008, flags=<optimized out>)
    at /home/azq2/build/php-src/ext/mysqlnd/mysqlnd_connection.c:1967
#3  0x000000000066688a in zif_mysqli_query (execute_data=<optimized out>, 
    return_value=0x7fffee614180)
    at /home/azq2/build/php-src/ext/mysqli/mysqli_nonapi.c:613
#4  0x0000000000852fcd in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER ()
    at /home/azq2/build/php-src/Zend/zend_vm_execute.h:641
#5  0x000000000083b6eb in execute_ex (ex=<optimized out>)
    at /home/azq2/build/php-src/Zend/zend_vm_execute.h:424
#6  0x0000000000891f37 in zend_execute (op_array=0x7fffee683000, 
    op_array@entry=0x7fffee684620, 
    return_value=return_value@entry=0x7fffee614030)
    at /home/azq2/build/php-src/Zend/zend_vm_execute.h:468
#7  0x00000000007fe2d4 in zend_execute_scripts (type=type@entry=8, 
    retval=0x7fffee614030, retval@entry=0x0, file_count=file_count@entry=3)
---Type <return> to continue, or q <return> to quit---
    at /home/azq2/build/php-src/Zend/zend.c:1427
#8  0x00000000007a18c8 in php_execute_script (
    primary_file=primary_file@entry=0x7fffffffc890)
    at /home/azq2/build/php-src/main/main.c:2487
#9  0x00000000008941d8 in do_cli (argc=2, argv=0x1189950)
    at /home/azq2/build/php-src/sapi/cli/php_cli.c:974
#10 0x0000000000444e20 in main (argc=2, argv=0x1189950)
    at /home/azq2/build/php-src/sapi/cli/php_cli.c:1344


Patches

fix-mysqlnd-result-set-segfaul (last revision 2016-04-11 14:31 UTC by reyad dot attiyat at gmail dot com)

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-03-21 08:33 UTC] laruence@php.net
-Assigned To: +Assigned To: mysql
 [2016-04-11 14:36 UTC] reyad dot attiyat at gmail dot com
I also encountered this crash when dealing with errors in MySQL SELECT queries. I'm running PHP 7.1 (master) on Debian linux. The error seems to caused by a null function table pointer. The result set error_info struct is not initialized with callbacks and segfaults when the COPY_CLIENT_ERROR macro is called.

The patch potentially fixes this issue by copying the error_info struct of the row packet into the the result set error_info struct.
 [2016-04-11 14:42 UTC] reyad dot attiyat at gmail dot com
This problem is not isolated to MySQLi but any extension, such as PDO, that uses the mysqlnd backend.
 [2016-07-13 20:11 UTC] nikic@php.net
-Assigned To: mysql +Assigned To: andrey
 [2016-07-13 20:11 UTC] nikic@php.net
@andrey: The PR (https://github.com/php/php-src/pull/1858) points out that this is likely caused by https://github.com/php/php-src/commit/4bb784cd0d80c330364cdfebc824a434cc27f05a. Could you please take a look at the PR and check if it is correct?
 [2016-07-19 08:08 UTC] andrey@php.net
-Status: Assigned +Status: Feedback
 [2016-07-19 08:08 UTC] andrey@php.net
I can't reproduce with 7.1 and MySQL 5.7.13

andrey@poohie:/work/dev/php/php-src$ ./php -v
PHP 7.1.0-dev (cli) (built: Jul 19 2016 11:03:23) ( NTS DEBUG )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.1.0-dev, Copyright (c) 1998-2016 Zend Technologies

andrey@poohie:/work/dev/php/php-src$ ./php ext/mysqli/tests/bug71863.php
Unknown column 'owner_id' in 'where clause'
 [2016-07-19 08:10 UTC] andrey@php.net
I can't reproduce also with the test script from this bug report (in the previous comment I tested with the test script from the Pull Request)
 [2016-07-19 14:01 UTC] reyad dot attiyat at gmail dot com
@andrey

I still get this bug on PHP 7.1. However I'm using Windows 10, previously on Windows 7, and am using PHP 7.1.0alpha3 Thread Safe. I downloaded the build from here: http://windows.php.net/qa/. I also just test the non thread safe build and encounter the same problem.

I will test on linux to eliminate that as a possible cause.

Also I'm using MariaDB and not Oracle's MySQL could this be the reason for segmentation fault?
 [2016-07-19 14:05 UTC] andrey@php.net
MariaDB might be an issue. I don't know. Keep in mind that mysqlnd supports officially only MySQL and not any forks.

I will try to get MariaDB up and running to test with it.

Best,
Andrey
 [2016-07-19 19:10 UTC] andrey@php.net
-Status: Feedback +Status: Assigned
 [2016-07-19 19:10 UTC] andrey@php.net
I confirm a segfault with MariaDB 10.1.16 . Will have to check how it is incompatible with the MySQL client server protocol.
 [2016-07-22 20:03 UTC] andrey@php.net
MySQL sends an error directly after the query is executed, as it should happen. MariaDB does send OK, meaning that there are fields and sends meta for 10 fields, then EOF (marking end of metadata) and only then it sends an error message. Such sending of errors is not common. It exists when we talk calling stored procedures because they can fail in the middle after some meta is sent.
 [2016-07-22 20:26 UTC] reyad dot attiyat at gmail dot com
This segfault only happens in PHP 7.1 and not in previous versions of PHP. I understand that mysqlnd only supports the official MySQL implementation, but don't believe we should have a separate driver for MariaDB or other forks (like AWS Aurora). Do you think we should add a quirk/flag to the mysqlnd driver for MariaDB that would handle these errors correctly?
 [2016-07-22 20:42 UTC] andrey@php.net
MariaDB bends the protocol and this is why this happened. I am preparing a fix for this. The crash happens because of a bug of mine of not initializing correctly callbacks for the error structure. Reporting an error after reporting that there is no error is very rare case, which I saw last time in 2007 (see http://bugs.mysql.com/bug.php?id=27876 :)
mysqlnd should not crash, that is for sure.
 [2016-07-22 20:55 UTC] andrey@php.net
Here is an example of MariaDB. A test from the suite fails. Why? Because they changed a text message, which is not that weird, but they changed the ID of the error.
001+ int(2)
002+ int(1146)
003+ string(39) "Table 'mysql.table_stats' doesn't exist"
001- int(1)
002- int(1051)
003- %unicode|string%(%d) "Unknown table %snot_exists%s"
 [2016-07-22 21:33 UTC] andrey@php.net
-Status: Assigned +Status: Closed
 [2016-07-22 21:33 UTC] andrey@php.net
The fix for this bug has been committed.

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/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.

Just pushed the fix to 7.1 and master
 [2016-07-23 13:10 UTC] reyad dot attiyat at gmail dot com
Thank you.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 11:01:28 2024 UTC