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
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: alex dot mashin at gmail dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 14:01:32 2024 UTC