php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72526 segfault in curl_setopt()
Submitted: 2016-06-30 13:48 UTC Modified: 2016-07-27 12:27 UTC
Votes:3
Avg. Score:3.7 ± 0.9
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:2 (100.0%)
From: lazy at iq dot pl Assigned: pierrick (profile)
Status: Closed Package: cURL related
PHP Version: 7.0.8 OS: Debian Wheezy
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: lazy at iq dot pl
New email:
PHP Version: OS:

 

 [2016-06-30 13:48 UTC] lazy at iq dot pl
Description:
------------
gcc version 4.7.2 (Debian 4.7.2-5) 

compiling with O0 "fixes" the problem,

also works fine on centos 7, so it might be some optimization issue

Breakpoint 1, _php_curl_setopt (ch=0x3d61925b780, option=10023, zvalue=0x3d619213160) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/ext/curl/interface.c:2133
2133	{
(gdb) p zvalue
$1 = (zval *) 0x3d619213160
(gdb) list
2128		dupch->res = Z_RES_P(return_value);
2129	}
2130	/* }}} */
2131	
2132	static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ */
2133	{
2134		CURLcode error = CURLE_OK;
2135		zend_long lval;
2136	
2137		ZVAL_DEREF(zvalue);
(gdb) next
2137		ZVAL_DEREF(zvalue);
(gdb) 
2133	{
(gdb) 
2137		ZVAL_DEREF(zvalue);
(gdb) 
2138		switch (option) {
(gdb) 
3626	}
(gdb) 
2603				ph = HASH_OF(zvalue);
(gdb) next
2604				if (!ph) {
(gdb) 
2650				ZEND_HASH_FOREACH_VAL(ph, current) {
(gdb) 
2661				if ((*ch->clone) == 1) {
(gdb) 
2662					zend_hash_index_update_ptr(ch->to_free->slist, option, slist);
(gdb) 
2661				if ((*ch->clone) == 1) {
(gdb) 
2662					zend_hash_index_update_ptr(ch->to_free->slist, option, slist);
(gdb) 
2822					zval_ptr_dtor(&ch->handlers->progress->func_name);
(gdb) 

Program received signal SIGSEGV, Segmentation fault.
_zval_ptr_dtor (zval_ptr=0x4) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/Zend/zend_execute_API.c:533
533		i_zval_ptr_dtor(zval_ptr ZEND_FILE_LINE_RELAY_CC);


gdb) bt
#0  _zval_ptr_dtor (zval_ptr=0x4) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/Zend/zend_execute_API.c:533
#1  0x00000000005807e5 in _php_curl_setopt (ch=ch@entry=0x2c7a8fe3700, option=<optimized out>, zvalue=zvalue@entry=0x2c7a8fe3520) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/ext/curl/interface.c:2822
#2  0x00000000005814b5 in zif_curl_setopt_array (execute_data=<optimized out>, return_value=0x2c7a9c16660) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/ext/curl/interface.c:3015
#3  0x00000000008f8fed in ZEND_DO_FCALL_SPEC_HANDLER (execute_data=0x2c7a9c16430) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/Zend/zend_vm_execute.h:842
#4  0x00000000008b66a0 in execute_ex (ex=<optimized out>) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/Zend/zend_vm_execute.h:417
#5  0x0000000000907097 in zend_execute (op_array=op_array@entry=0x2c7a9c78000, return_value=return_value@entry=0x0) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/Zend/zend_vm_execute.h:458
#6  0x0000000000878a24 in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/Zend/zend.c:1427
#7  0x000000000081aaa0 in php_execute_script (primary_file=primary_file@entry=0x3dcd7e2eaa0) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/main/main.c:2494
#8  0x00000000004566ca in main (argc=1, argv=0x3dcd7e2ee58) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/sapi/cgi/cgi_main.c:2453

Please look at
https://github.com/php/php-src/blob/master/ext/curl/interface.c#L2663-L2672

May it be running ZEND_HASH_FOREACH_VAL() loop on an empty hash corrupting the stack ?



Test script:
---------------
$ch=curl_init();

curl_setopt($ch, CURLOPT_HTTPHEADER, array());

Expected result:
----------------
Normal execution

Actual result:
--------------
Segfault:
gdb) bt
#0  _zval_ptr_dtor (zval_ptr=0x4) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/Zend/zend_execute_API.c:533
#1  0x00000000005807e5 in _php_curl_setopt (ch=ch@entry=0x2c7a8fe3700, option=<optimized out>, zvalue=zvalue@entry=0x2c7a8fe3520) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/ext/curl/interface.c:2822
#2  0x00000000005814b5 in zif_curl_setopt_array (execute_data=<optimized out>, return_value=0x2c7a9c16660) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/ext/curl/interface.c:3015
#3  0x00000000008f8fed in ZEND_DO_FCALL_SPEC_HANDLER (execute_data=0x2c7a9c16430) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/Zend/zend_vm_execute.h:842
#4  0x00000000008b66a0 in execute_ex (ex=<optimized out>) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/Zend/zend_vm_execute.h:417
#5  0x0000000000907097 in zend_execute (op_array=op_array@entry=0x2c7a9c78000, return_value=return_value@entry=0x0) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/Zend/zend_vm_execute.h:458
#6  0x0000000000878a24 in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/Zend/zend.c:1427
#7  0x000000000081aaa0 in php_execute_script (primary_file=primary_file@entry=0x3dcd7e2eaa0) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/main/main.c:2494
#8  0x00000000004566ca in main (argc=1, argv=0x3dcd7e2ee58) at /usr/src/new/apache2-suexec/work/pri/php-7.0.8/sapi/cgi/cgi_main.c:2453

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-06-30 15:55 UTC] laruence@php.net
I can not reproduce this on ubuntu
 [2016-07-01 11:03 UTC] lazy at iq dot pl
with some experiments I have narrowed it to calling

zend_hash_index_update_ptr(ch->to_free->slist, option, slist); with NULL slist,


Breakpoint 2, _zend_hash_index_update (ht=0x3b3e8257268, h=h@entry=10023, pData=pData@entry=0x3eb430303e0) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend_hash.c:838
838		return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
(gdb) bt
#0  _zend_hash_index_update (ht=0x3b3e8257268, h=h@entry=10023, pData=pData@entry=0x3eb430303e0) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend_hash.c:838
#1  0x000000000054848e in zend_hash_index_update_ptr (pData=0x0, h=10023, ht=<optimized out>) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend_hash.h:642
#2  _php_curl_setopt (ch=0x3b3e825e780, option=10023, zvalue=0x3b3e8214130) at /usr/src/new/apache2-suexec/work/pri/php-src/ext/curl/interface.c:2680
#3  0x0000000000549224 in zif_curl_setopt (execute_data=<optimized out>, return_value=0x3eb43030470) at /usr/src/new/apache2-suexec/work/pri/php-src/ext/curl/interface.c:3001
#4  0x00000000007472c7 in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER (execute_data=0x3b3e8214030) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend_vm_execute.h:632
#5  0x0000000000736a18 in execute_ex (ex=<optimized out>) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend_vm_execute.h:432
#6  0x000000000078ee30 in zend_execute (op_array=op_array@entry=0x3b3e827f000, return_value=return_value@entry=0x0) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend_vm_execute.h:474
#7  0x00000000006ef314 in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend.c:1441
#8  0x000000000068f0a0 in php_execute_script (primary_file=primary_file@entry=0x3eb43032980) at /usr/src/new/apache2-suexec/work/pri/php-src/main/main.c:2532
#9  0x0000000000791000 in do_cli (argc=2, argv=0x408b690) at /usr/src/new/apache2-suexec/work/pri/php-src/sapi/cli/php_cli.c:990
#10 0x000000000043290c in main (argc=2, argv=0x408b690) at /usr/src/new/apache2-suexec/work/pri/php-src/sapi/cli/php_cli.c:1378
(gdb) cont
Breakpoint 2, _zend_hash_index_update (ht=0x4, h=h@entry=10023, pData=pData@entry=0x3eb430303e0) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend_hash.c:838
838		return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
(gdb) bt
#0  _zend_hash_index_update (ht=0x4, h=h@entry=10023, pData=pData@entry=0x3eb430303e0) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend_hash.c:838
#1  0x000000000054848e in zend_hash_index_update_ptr (pData=0x0, h=10023, ht=<optimized out>) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend_hash.h:642
#2  _php_curl_setopt (ch=0x3b3e825e780, option=10023, zvalue=0x3b3e8214130) at /usr/src/new/apache2-suexec/work/pri/php-src/ext/curl/interface.c:2680
#3  0x0000000000549224 in zif_curl_setopt (execute_data=<optimized out>, return_value=0x3eb43030470) at /usr/src/new/apache2-suexec/work/pri/php-src/ext/curl/interface.c:3001
#4  0x00000000007472c7 in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER (execute_data=0x3b3e8214030) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend_vm_execute.h:632
#5  0x0000000000736a18 in execute_ex (ex=<optimized out>) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend_vm_execute.h:432
#6  0x000000000078ee30 in zend_execute (op_array=op_array@entry=0x3b3e827f000, return_value=return_value@entry=0x0) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend_vm_execute.h:474
#7  0x00000000006ef314 in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at /usr/src/new/apache2-suexec/work/pri/php-src/Zend/zend.c:1441
#8  0x000000000068f0a0 in php_execute_script (primary_file=primary_file@entry=0x3eb43032980) at /usr/src/new/apache2-suexec/work/pri/php-src/main/main.c:2532
#9  0x0000000000791000 in do_cli (argc=2, argv=0x408b690) at /usr/src/new/apache2-suexec/work/pri/php-src/sapi/cli/php_cli.c:990
#10 0x000000000043290c in main (argc=2, argv=0x408b690) at /usr/src/new/apache2-suexec/work/pri/php-src/sapi/cli/php_cli.c:1378


zend_hash_index_update_ptr() is called twice maybe because of some curruption in

Zend/zend_hash.h:644			ZEND_ASSUME(Z_PTR_P(zv));

removing Zend/zend_hash.h:644			ZEND_ASSUME(Z_PTR_P(zv));
"fixes" the problem


ZEND_ASSUME is defined as

#elif ((defined(__GNUC__) && ZEND_GCC_VERSION >= 4005) || __has_builtin(__builtin_unreachable)) && PHP_HAVE_BUILTIN_EXPECT
# define ZEND_ASSUME(c) do { \
                if (__builtin_expect(!(c), 0)) __builtin_unreachable(); \
        } while (0)

https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
— Built-in Function: long __builtin_expect (long exp, long c)
You may use __builtin_expect to provide the compiler with branch prediction information. In general, you should prefer to use actual profile feedback for this (-fprofile-arcs), as programmers are notoriously bad at predicting how their programs actually perform. However, there are applications in which this data is hard to collect.


c is NULL so !(c) is 1 and __builtin_unreachable is called which leads to segfault maybe becaouse of some gcc problems with __builtin_unreachable() on debian's gcc (-O0 works fine)

can we fix this by adding

if(zend_hash_num_elements(ph) == 0) {
    php_error_docref(NULL, E_WARNING, "You must pass an non empty argument");
    return 1;
}
before calling zend_hash_index_update_ptr() ?


on debian's gcc
int main() {
int *c=0;

do { \
        if (__builtin_expect(!(c), 0)) __builtin_unreachable(); \
    } while (0);
}

with -O2 is also segfaulting, -O0 is ok


what's the semantic of ZEND_ASSUME should it bail on an NULL argument ?
 [2016-07-01 11:16 UTC] lazy at iq dot pl
ZEND_ASSUME(0) also segfaults on
gcc version 4.9.2 (Debian 4.9.2-10) - debian 8
gcc version 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC) - centos 7


any chance You ware using gcc older then 4.0.5 ?
 [2016-07-01 11:37 UTC] lazy at iq dot pl
this should be 4.5.0 not 4.0.5
 [2016-07-27 12:25 UTC] arie dot mail at gmail dot com
I've also have this issue, could reproduce from the same little test script.

Curl version: 7.50.0
PHP Version 7.0.9
gcc (Debian 4.7.2-5) 4.7.2
Debian: 7.11

bt:
(gdb) bt
#0  i_zval_ptr_dtor (zval_ptr=0x4) at /usr/local/directadmin/custombuild/php-7.0.9/Zend/zend_variables.h:56
#1  _zval_ptr_dtor (zval_ptr=0x4) at /usr/local/directadmin/custombuild/php-7.0.9/Zend/zend_execute_API.c:533
#2  0x0000000000533de5 in _php_curl_setopt (ch=0x7f5583264780, option=<optimized out>, zvalue=0x7f5583214150) at /usr/local/directadmin/custombuild/php-7.0.9/ext/curl/interface.c:2822
#3  0x0000000000534dc4 in zif_curl_setopt (execute_data=<optimized out>, return_value=0x7f55832140c0) at /usr/local/directadmin/custombuild/php-7.0.9/ext/curl/interface.c:2984
#4  0x0000000000855372 in ZEND_DO_ICALL_SPEC_HANDLER (execute_data=0x7f5583214030) at /usr/local/directadmin/custombuild/php-7.0.9/Zend/zend_vm_execute.h:586
#5  0x0000000000845e60 in execute_ex (ex=<optimized out>) at /usr/local/directadmin/custombuild/php-7.0.9/Zend/zend_vm_execute.h:417
#6  0x0000000000896807 in zend_execute (op_array=op_array@entry=0x7f5583275000, return_value=return_value@entry=0x0) at /usr/local/directadmin/custombuild/php-7.0.9/Zend/zend_vm_execute.h:458
#7  0x00000000008080a4 in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at /usr/local/directadmin/custombuild/php-7.0.9/Zend/zend.c:1427
#8  0x00000000007a9a30 in php_execute_script (primary_file=primary_file@entry=0x7ffca1293e40) at /usr/local/directadmin/custombuild/php-7.0.9/main/main.c:2494
#9  0x000000000045378e in main (argc=<optimized out>, argv=<optimized out>) at /usr/local/directadmin/custombuild/php-7.0.9/sapi/fpm/fpm/fpm_main.c:1968
 [2016-07-27 12:27 UTC] pierrick@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: pierrick
 [2016-07-27 12:27 UTC] pierrick@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.

This bug was fixed with #71709
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Fri May 09 14:01:27 2025 UTC