php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79741 curl_setopt CURLOPT_POSTFIELDS asserts on object with declared properties
Submitted: 2020-06-26 08:45 UTC Modified: 2020-06-26 10:39 UTC
From: sjon@php.net Assigned: nikic (profile)
Status: Closed Package: cURL related
PHP Version: 7.3 OS: archLinux
Private report: No CVE-ID: None
 [2020-06-26 08:45 UTC] sjon@php.net
Description:
------------
#0  0x00007f9e8c4ba355 raise (libc.so.6 + 0x3c355)
#1  0x00007f9e8c4a3853 abort (libc.so.6 + 0x25853)
#2  0x00007f9e8c4a3727 __assert_fail_base.cold (libc.so.6 + 0x25727)
#3  0x00007f9e8c4b2936 __assert_fail (libc.so.6 + 0x34936)
#4  0x000055e572bcd0d2 __zval_get_string_func (php + 0x64f0d2)
#5  0x000055e572bcd106 zval_get_string_func (php + 0x64f106)
#6  0x00007f9e8a479635 zval_get_tmp_string (curl.so + 0x4635)
#7  0x00007f9e8a482503 build_mime_structure_from_hash (curl.so + 0xd503)
#8  0x00007f9e8a483dfa _php_curl_setopt (curl.so + 0xedfa)
#9  0x00007f9e8a484c4b zif_curl_setopt (curl.so + 0xfc4b)
#10 0x000055e572c4fd71 ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER (php + 0x6d1d71)
#11 0x000055e572cb64bc execute_ex (php + 0x7384bc)
#12 0x000055e572cba613 zend_execute (php + 0x73c613)
#13 0x000055e572bdc0e9 zend_execute_scripts (php + 0x65e0e9)
#14 0x000055e572b39fc0 php_execute_script (php + 0x5bbfc0)
#15 0x000055e572cbd1c1 do_cli (php + 0x73f1c1)
#16 0x000055e572cbe3c1 main (php + 0x7403c1)
#17 0x00007f9e8c4a5002 __libc_start_main (libc.so.6 + 0x27002)
#18 0x000055e57277e6ae _start (php + 0x2006ae)

Test script:
---------------
<?php

class x
{
	private $_body;

	public function __construct(SimpleXMLElement $body)
	{
		$this->_body = $body;
	}

	public function __toString()
	{
		return $this->_body->asXML();
	}
}

$body = new x(simplexml_load_string('<?xml version="1.0" encoding="UTF-8"?>
<Test>
    <Id>123</Id>
</Test>'));

$ch = curl_init();

curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

Expected result:
----------------
no segfault - which can be achieved by manually casting to string first eg. curl_setopt($ch, CURLOPT_POSTFIELDS, (string)$body);

Actual result:
--------------
segfault

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-06-26 10:15 UTC] nikic@php.net
-Status: Open +Status: Verified
 [2020-06-26 10:15 UTC] nikic@php.net
Reduced a bit:

<?php
  
class Test {
    private $prop;

    public function __toString() {
        return "Foobar";
    }
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_POSTFIELDS, new Test);

For some reason the property declaration is important.
 [2020-06-26 10:21 UTC] nikic@php.net
-Summary: segfault: curl_setopt/CURLOPT_POSTFIELDS using toStringable +Summary: curl_setopt CURLOPT_POSTFIELDS asserts on object with declared properties -Status: Verified +Status: Assigned -PHP Version: 7.4.7 +PHP Version: 7.3 -Assigned To: +Assigned To: nikic
 [2020-06-26 10:21 UTC] nikic@php.net
Actually, the __toString() here is a red herring, just this works as well:

class Test {
    public $prop;
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_POSTFIELDS, new Test);

It also reproduces on PHP 7.3.

The problem is that CURLOPT_POSTFIELDS accepts a string or an array ... or an object, in which case it will be interpreted as an array. The loop does not handle INDIRECT values properly.

I'm going to fix this in the straightforward way for PHP 7.3, but I believe we should drop support for objects here in PHP 8.0. This is very confusing, and interpreting Stringable objects as strings would make a great deal more sense here.
 [2020-06-26 10:30 UTC] nikic@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=43cd3f68143eb6b35e19605855dac45db4007fc1
Log: Fixed bug #79741
 [2020-06-26 10:30 UTC] nikic@php.net
-Status: Assigned +Status: Closed
 [2020-06-26 10:39 UTC] nikic@php.net
PR for master: https://github.com/php/php-src/pull/5773
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 09:01:32 2024 UTC