php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #55748 multiple NULL Pointer Dereference with zend_strndup()
Submitted: 2011-09-21 03:54 UTC Modified: 2011-11-18 09:31 UTC
From: max at cxib dot net Assigned: stas (profile)
Status: Closed Package: *General Issues
PHP Version: 5.3SVN-2011-09-21 (SVN) OS: *
Private report: No CVE-ID: 2011-4153
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: max at cxib dot net
New email:
PHP Version: OS:

 

 [2011-09-21 03:54 UTC] max at cxib dot net
Description:
------------
multiple NULL Pointer Dereference with zend_strndup()


see zend_strndup()

-zend_alloca.c---
ZEND_API char *zend_strndup(const char *s, uint length)
{
	char *p;

	p = (char *) malloc(length+1);
	if (UNEXPECTED(p == NULL)) {
		return p;
	}
	if (length) {
		memcpy(p, s, length);
	}
	p[length] = 0;
	return p;
}
-zend_alloca.c---

in php code, many calls to zend_strndup() dosen't check returned values. In result, places like:

-zend_builtin_functions.c---
ZEND_FUNCTION(define)
{
	char *name;
	int name_len;
	zval *val;
	zval *val_free = NULL;
	zend_bool non_cs = 0;
	int case_sensitive = CONST_CS;
	zend_constant c;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|b", &name, &name_len, &val, &non_cs) == FAILURE) {
		return;
	}
...
	c.flags = case_sensitive; /* non persistent */
	c.name = zend_strndup(name, name_len); <======== MAY RETURN NULL
	c.name_len = name_len+1;
	c.module_number = PHP_USER_CONSTANT;
	if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
		RETURN_TRUE;
	} else {
		RETURN_FALSE;
	}
}
-zend_builtin_functions.c---


[cx@82 /www]$ ulimit -a
socket buffer size       (bytes, -b) unlimited
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) 524288
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) 40000
open files                      (-n) 11095
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 65536
cpu time               (seconds, -t) unlimited
max user processes              (-u) 5547
virtual memory          (kbytes, -v) 40000
swap size               (kbytes, -w) unlimited
[cx@82 /www]$ cat define.php
<?php
define(str_repeat("A",$argv[1]),"a");
?>


to see difference

[cx@82 /www]$ php define.php 8999999
Out of memory
[cx@82 /www]$ php define.php 9999999
Segmentation fault: 11

(gdb) bt
#0  0x28745eb0 in strrchr () from /lib/libc.so.7
#1  0x0822d538 in zend_register_constant (c=0xbfbfcfb0)
    at /usr/ports/lang/php5/work/php/Zend/zend_constants.c:429
#2  0x08251e0e in zif_define (ht=2, return_value=0x28825a98, 
    return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)
    at /usr/ports/lang/php5/work/php/Zend/zend_builtin_functions.c:688
#3  0x0826dba6 in zend_do_fcall_common_helper_SPEC (execute_data=0x29401040)
    at zend_vm_execute.h:316


please see also
ext/soap/php_sdl.c
			if (sdl->is_persistent) {
				new_enc->details.ns = zend_strndup(ns, ns_len);
				new_enc->details.type_str = strdup(new_enc->details.type_str);
			} else {
				new_enc->details.ns = estrndup(ns, ns_len);
				new_enc->details.type_str = estrdup(new_enc->details.type_str);
			}

ext/standard/syslog.c
	BG(syslog_device) = zend_strndup(ident, ident_len);
	openlog(BG(syslog_device), option, facility);
	RETURN_TRUE;


ext/standard/browscap.c
				} else { /* Other than true/false setting */
					Z_STRVAL_P(new_property) = zend_strndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2));
					Z_STRLEN_P(new_property) = Z_STRLEN_P(arg2);
				}
				new_key = zend_strndup(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1));
				zend_str_tolower(new_key, Z_STRLEN_P(arg1));
				zend_hash_update(Z_ARRVAL_P(current_section), new_key, Z_STRLEN_P(arg1) + 1, &new_property, sizeof(zval *), NULL);
				free(new_key);



ext/oci8/oci8.c
		if (alloc_non_persistent) {
			connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
			connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
			connection->is_persistent = 0;
		} else {
			connection = (php_oci_connection *) calloc(1, sizeof(php_oci_connection));
			connection->hash_key = zend_strndup(hashed_details.c, hashed_details.len);
			connection->is_persistent = 1;
		}





ext/com_dotnet/com_typeinfo.c
				const_name = php_com_olestring_to_string(bstr_ids, &c.name_len, codepage TSRMLS_CC);
				c.name = zend_strndup(const_name, c.name_len);
				efree(const_name);
				c.name_len++; /* include NUL */
				SysFreeString(bstr_ids);

				/* sanity check for the case where the constant is already defined */
				if (zend_get_constant(c.name, c.name_len - 1, &exists TSRMLS_CC)) {
					if (COMG(autoreg_verbose) && !compare_function(&results, &c.value, &exists TSRMLS_CC)) {
						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type library constant %s is already defined", c.name);
					}
					free(c.name);
					ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
					continue;
				}




main/php_open_temporary_file.c
	/* On Unix use the (usual) TMPDIR environment variable. */
	{
		char* s = getenv("TMPDIR");
		if (s && *s) {
			int len = strlen(s);

			if (s[len - 1] == DEFAULT_SLASH) {
				temporary_directory = zend_strndup(s, len - 1);
			} else {
				temporary_directory = zend_strndup(s, len);
			}

			return temporary_directory;
		}


Test script:
---------------
<?php
define(str_repeat("A",$argv[1]),"a");
?>


Expected result:
----------------
[cx@82 /www]$ php define.php 8999999
Out of memory


Actual result:
--------------
[cx@82 /www]$ php define.php 9999999
Segmentation fault: 11

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-11-11 11:37 UTC] max at cxib dot net
use CVE-2011-4153
 [2011-11-18 07:12 UTC] stas@php.net
This bug has been fixed in SVN.

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.


 [2011-11-18 07:12 UTC] stas@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: stas
 [2011-11-18 08:46 UTC] stas@php.net
-Type: Security +Type: Bug
 [2011-11-18 09:31 UTC] pajoye@php.net
-CVE-ID: +CVE-ID: 2011-4153
 [2011-11-18 09:31 UTC] pajoye@php.net
Adding CVE.
 [2011-11-18 09:59 UTC] sixd@php.net
Automatic comment from SVN on behalf of sixd
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=319457
Log: Sync to 5.3 and check additional cases for #55748
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 20:01:45 2024 UTC