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
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: 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

Pull Requests

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 Nov 21 15:01:30 2024 UTC