php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80099 php_memnstr segfaults
Submitted: 2020-09-13 17:03 UTC Modified: 2020-09-17 16:12 UTC
From: alex dot mashin at gmail dot com Assigned:
Status: Closed Package: Program Execution
PHP Version: 7.4.10 OS: Ubuntu 20.04
Private report: No CVE-ID: None
 [2020-09-13 17:03 UTC] alex dot mashin at gmail dot com
Description:
------------
I am trying to improve a third-party PHP extension. I was trying to split a comma-separated string with php_explode() but it caused a segmentation fault.

I managed to find out that the segfault was caused by php_memnstr.

If its third parameter (delimiter length) is a plain number, or strlen( ZSTR_VAL(needle) ), or even needle->len, there is no segfault.

However, if it is ZSTR_LEN(delimiter), as in php_memnstr, a segfault happens. The delimiter is a properly initiated zend_string *, and its ZSTR_LEN can be output with php_printf and looks correct.

It is interesting, that the segfaults seems to happen immediately: the numerous php_prints calls above php_memnstr are not executed (as if the compiler optimises something incorrectly).

Unfortunately, I was unable to make gdb work.

PHP 7.4.10 (cli) (built: Sep  9 2020 06:36:30) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.10, Copyright (c), by Zend Technologies
    with Xdebug v2.9.6, Copyright (c) 2002-2020, by Derick Rethans


Test script:
---------------
zend_string * haystack;
haystack = zend_string_init( "1,2,3", 5, 0 );

zend_string * needle;
needle = zend_string_init( ",", 1, 0 );

// Works:
const char *p = php_memnstr(ZSTR_VAL(haystack), ZSTR_VAL(needle), 1, ZSTR_VAL(haustack) + ZSTR_LEN(haystack) );

// Also works:
const char *p = php_memnstr(ZSTR_VAL(haystack), ZSTR_VAL(needle), strlen( ZSTR_VAL(needle) ), ZSTR_VAL(haustack) + ZSTR_LEN(haystack) );

// Even this works:
const char *p = php_memnstr(ZSTR_VAL(haystack), ZSTR_VAL(needle), needle->len, ZSTR_VAL(haustack) + ZSTR_LEN(haystack) );

// Segfaults:
const char *p = php_memnstr(ZSTR_VAL(haystack), ZSTR_VAL(needle), ZSTR_LEN(needle), ZSTR_VAL(haustack) + ZSTR_LEN(haystack) );


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-09-13 21:37 UTC] cmb@php.net
`ZSTR_LEN(needle)` should evaluate to `(needle)->len`, so
something else may be wrong with that code.  I'm also confused
about the `haustack`; is that just a typo in this bug report?

Anyhow, I don't think this bug tracker is the right place to make
progress on this issue; the PHP internals mailing list might
better be suited.  And also, you really want to work with a
debugger when developing PHP extensions, and facing such issues.
 [2020-09-17 16:12 UTC] alex dot mashin at gmail dot com
-Status: Open +Status: Closed
 [2020-09-17 16:12 UTC] alex dot mashin at gmail dot com
Closing, as I reworked the code to avoid the error.
 
PHP Copyright © 2001-2023 The PHP Group
All rights reserved.
Last updated: Sun Dec 10 02:01:27 2023 UTC