Merge branch 'PHP-5.6'

* PHP-5.6:
  fix format
  update NEWS
  Add test for bug #69522
  Update tests
  Fix bug #69522 - do not allow int overflow
  Forgot test file
  Fix bug #69403 and other int overflows
  Fixed bug #69418 - more s->p fixes for filenames
  Fixed bug #69364 - use smart_str to assemble strings
  Fix bug #69453 - don't try to cut empty string
  Fix bug #69545 - avoid overflow when reading list

Conflicts:
	Zend/zend_alloc.c
	Zend/zend_operators.c
	ext/ftp/ftp.c
	ext/pcntl/pcntl.c
	ext/standard/basic_functions.c
	ext/standard/dir.c
	ext/standard/file.c
	ext/standard/pack.c
	ext/standard/string.c
	main/rfc1867.c
This commit is contained in:
Stanislav Malyshev 2015-05-12 14:31:52 -07:00
commit 5a1bef8eef
18 changed files with 122 additions and 77 deletions

View File

@ -2293,13 +2293,13 @@ ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_
HANDLE_BLOCK_INTERRUPTIONS();
length = strlen(s)+1;
p = (char *) _emalloc(length ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
length = strlen(s);
p = (char *) _emalloc(safe_address(length, 1, 1) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
if (UNEXPECTED(p == NULL)) {
HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
}
memcpy(p, s, length);
memcpy(p, s, length+1);
HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
}
@ -2310,7 +2310,7 @@ ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LI
HANDLE_BLOCK_INTERRUPTIONS();
p = (char *) _emalloc(length+1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
p = (char *) _emalloc(safe_address(length, 1, 1) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
if (UNEXPECTED(p == NULL)) {
HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
@ -2328,7 +2328,7 @@ ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length)
HANDLE_BLOCK_INTERRUPTIONS();
p = (char *) malloc(length+1);
p = (char *) malloc(safe_address(length, 1, 1));
if (UNEXPECTED(p == NULL)) {
HANDLE_UNBLOCK_INTERRUPTIONS();
return p;

View File

@ -1784,8 +1784,8 @@ ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path)
databuf_t *data = NULL;
char *ptr;
int ch, lastch;
int size, rcvd;
int lines;
size_t size, rcvd;
size_t lines;
char **ret = NULL;
char **entry;
char *text;
@ -1827,7 +1827,7 @@ ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path)
lines = 0;
lastch = 0;
while ((rcvd = my_recv(ftp, data->fd, data->buf, FTP_BUFSIZE))) {
if (rcvd == -1) {
if (rcvd == -1 || rcvd > ((size_t)(-1))-size) {
goto bail;
}

View File

@ -783,7 +783,7 @@ PHP_FUNCTION(pcntl_exec)
size_t path_len;
zend_ulong key_num;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|aa", &path, &path_len, &args, &envs) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|aa", &path, &path_len, &args, &envs) == FAILURE) {
return;
}

View File

@ -434,7 +434,7 @@ bail:
entry.filename_len = i;
entry.filename = pestrndup(hdr->name, i, myphar->is_persistent);
if (entry.filename[entry.filename_len - 1] == '/') {
if (i > 0 && entry.filename[entry.filename_len - 1] == '/') {
/* some tar programs store directories with trailing slash */
entry.filename[entry.filename_len - 1] = '\0';
entry.filename_len--;

View File

@ -0,0 +1,21 @@
--TEST--
Phar: bug #69453: Memory Corruption in phar_parse_tarfile when entry filename starts with null
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE--
<?php
$fname = dirname(__FILE__) . '/bug69453.tar.phar';
try {
$r = new Phar($fname, 0);
} catch(UnexpectedValueException $e) {
echo $e;
}
?>
==DONE==
--EXPECTF--
exception 'UnexpectedValueException' with message 'phar error: "%s/bug69453.tar.phar" is a corrupted tar file (checksum mismatch of file "")' in %s:%d
Stack trace:
#0 %s/bug69453.php(%d): Phar->__construct('%s', 0)
#1 {main}
==DONE==

Binary file not shown.

View File

@ -5409,7 +5409,7 @@ PHP_FUNCTION(set_include_path)
char *old_value;
zend_string *key;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &new_value) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &new_value) == FAILURE) {
return;
}

View File

@ -224,7 +224,7 @@ static void _php_do_opendir(INTERNAL_FUNCTION_PARAMETERS, int createobject)
php_stream_context *context = NULL;
php_stream *dirp;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|r", &dirname, &dir_len, &zcontext) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|r", &dirname, &dir_len, &zcontext) == FAILURE) {
RETURN_NULL();
}
@ -300,7 +300,7 @@ PHP_FUNCTION(chroot)
int ret;
size_t str_len;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &str_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &str, &str_len) == FAILURE) {
RETURN_FALSE;
}

View File

@ -806,7 +806,7 @@ PHP_FUNCTION(tempnam)
int fd;
zend_string *p;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ps", &dir, &dir_len, &prefix, &prefix_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &dir, &dir_len, &prefix, &prefix_len) == FAILURE) {
return;
}
@ -1353,7 +1353,7 @@ PHP_FUNCTION(rmdir)
zval *zcontext = NULL;
php_stream_context *context;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|r", &dir, &dir_len, &zcontext) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|r", &dir, &dir_len, &zcontext) == FAILURE) {
RETURN_FALSE;
}

View File

@ -699,6 +699,12 @@ PHP_FUNCTION(unpack)
break;
}
if (size != 0 && size != -1 && size < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: integer overflow", type);
zval_dtor(return_value);
RETURN_FALSE;
}
/* Do actual unpacking */
for (i = 0; i != arg; i++ ) {
/* Space for name + number, safe as namelen is ensured <= 200 */
@ -714,7 +720,8 @@ PHP_FUNCTION(unpack)
if (size != 0 && size != -1 && INT_MAX - size + 1 < inputpos) {
php_error_docref(NULL, E_WARNING, "Type %c: integer overflow", type);
inputpos = 0;
zval_dtor(return_value);
RETURN_FALSE;
}
if ((inputpos + size) <= inputlen) {
@ -798,7 +805,7 @@ PHP_FUNCTION(unpack)
len = size * 2;
}
if (argb > 0) {
if (len > 0 && argb > 0) {
len -= argb % 2;
}

View File

@ -8,7 +8,7 @@ if (substr(PHP_OS, 0, 3) == 'WIN') {
?>
--FILE--
<?php
/*
/*
* Prototype : object dir(string $directory[, resource $context])
* Description: Directory class with properties, handle and class and methods read, rewind and close
* Source code: ext/standard/dir.c
@ -34,7 +34,7 @@ class A
}
// get a resource variable
$fp = fopen(__FILE__, "r"); // get a file handle
$fp = fopen(__FILE__, "r"); // get a file handle
$dfp = opendir( dirname(__FILE__) ); // get a dir handle
// unexpected values to be passed to $directory argument
@ -92,27 +92,27 @@ echo "Done";
-- Iteration 1 --
Warning: dir() expects parameter 1 to be string, array given in %s on line %d
Warning: dir() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-- Iteration 2 --
Warning: dir() expects parameter 1 to be string, array given in %s on line %d
Warning: dir() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-- Iteration 3 --
Warning: dir() expects parameter 1 to be string, array given in %s on line %d
Warning: dir() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-- Iteration 4 --
Warning: dir() expects parameter 1 to be string, array given in %s on line %d
Warning: dir() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-- Iteration 5 --
Warning: dir() expects parameter 1 to be string, array given in %s on line %d
Warning: dir() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-- Iteration 6 --
@ -151,16 +151,16 @@ bool(false)
-- Iteration 16 --
Warning: dir() expects parameter 1 to be string, resource given in %s on line %d
Warning: dir() expects parameter 1 to be a valid path, resource given in %s on line %d
NULL
-- Iteration 17 --
Warning: dir() expects parameter 1 to be string, resource given in %s on line %d
Warning: dir() expects parameter 1 to be a valid path, resource given in %s on line %d
NULL
-- Iteration 18 --
Warning: dir() expects parameter 1 to be string, object given in %s on line %d
Warning: dir() expects parameter 1 to be a valid path, object given in %s on line %d
NULL
Done
Done

View File

@ -9,7 +9,7 @@ if (substr(PHP_OS, 0, 3) == 'WIN') {
--FILE--
<?php
/* Prototype : mixed opendir(string $path[, resource $context])
* Description: Open a directory and return a dir_handle
* Description: Open a directory and return a dir_handle
* Source code: ext/standard/dir.c
*/
@ -30,7 +30,7 @@ unset ($unset_var);
// get a class
class classA {
var $path;
function __construct($path) {
$this->path = $path;
@ -73,7 +73,7 @@ $inputs = array(
false,
TRUE,
FALSE,
// empty data
/*16*/ "",
'',
@ -83,7 +83,7 @@ $inputs = array(
/*19*/ "$path",
'string',
$heredoc,
// object data
/*22*/ new classA($path),
@ -194,7 +194,7 @@ bool(false)
-- Iteration 18 --
Warning: opendir() expects parameter 1 to be string, array given in %s on line %d
Warning: opendir() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-- Iteration 19 --
@ -219,6 +219,6 @@ bool(false)
-- Iteration 25 --
Warning: opendir() expects parameter 1 to be string, resource given in %s on line %d
Warning: opendir() expects parameter 1 to be a valid path, resource given in %s on line %d
NULL
===DONE===

View File

@ -68,7 +68,7 @@ bool(false)
Warning: mkdir() expects parameter 1 to be a valid path, string given in %s on line %d
bool(false)
Warning: rmdir(%s): No such file or directory in %s on line %d
Warning: rmdir() expects parameter 1 to be a valid path, string given in %s on line %d
bool(false)
*** Testing mkdir() with miscelleneous input ***

View File

@ -22,9 +22,9 @@ if (!mkdir($file_path)) {
$file_path = realpath($file_path);
/* An array of prefixes */
/* An array of prefixes */
$names_arr = array(
/* Valid args (casting)*/
/* Valid args (casting)*/
-1,
TRUE,
FALSE,
@ -32,17 +32,17 @@ $names_arr = array(
"",
" ",
"\0",
/* Invalid args */
/* Invalid args */
array(),
/* Valid args*/
/* Valid args*/
/* prefix with path separator of a non existing directory*/
"/no/such/file/dir",
"/no/such/file/dir",
"php/php"
);
$res_arr = array(
/* Invalid args */
/* Invalid args */
true,
true,
true,
@ -53,7 +53,7 @@ $res_arr = array(
false,
/* prefix with path separator of a non existing directory*/
true,
true,
true
);
@ -72,7 +72,7 @@ for( $i=0; $i<count($names_arr); $i++ ) {
} else {
echo "Failed, not created in the correct directory " . realpath($file_dir) . ' vs ' . $file_path ."\n";
}
if (!is_writable($file_name)) {
printf("%o\n", fileperms($file_name) );
@ -105,7 +105,7 @@ Failed, not created in the correct directory %s vs %s
OK
-- Iteration 7 --
Warning: tempnam() expects parameter 2 to be string, array given in %s\ext\standard\tests\file\tempnam_variation3-win32.php on line %d
Warning: tempnam() expects parameter 2 to be a valid path, array given in %s\ext\standard\tests\file\tempnam_variation3-win32.php on line %d
OK
-- Iteration 8 --
OK

View File

@ -17,9 +17,9 @@ echo "*** Testing tempnam() with obscure prefixes ***\n";
$file_path = dirname(__FILE__)."/tempnamVar3";
mkdir($file_path);
/* An array of prefixes */
/* An array of prefixes */
$names_arr = array(
/* Invalid args */
/* Invalid args */
-1,
TRUE,
FALSE,
@ -30,7 +30,7 @@ $names_arr = array(
array(),
/* prefix with path separator of a non existing directory*/
"/no/such/file/dir",
"/no/such/file/dir",
"php/php"
);
@ -48,10 +48,10 @@ for( $i=0; $i<count($names_arr); $i++ ) {
echo "File permissions are => ";
printf("%o", fileperms($file_name) );
echo "\n";
echo "File created in => ";
$file_dir = dirname($file_name);
if ($file_dir == sys_get_temp_dir()) {
echo "temp dir\n";
}
@ -61,7 +61,7 @@ for( $i=0; $i<count($names_arr); $i++ ) {
else {
echo "unknown location\n";
}
}
else {
echo "-- File is not created --\n";
@ -100,12 +100,14 @@ File name is => %s/%s
File permissions are => 100600
File created in => directory specified
-- Iteration 6 --
File name is => %s/%s
File permissions are => 100600
File created in => directory specified
Warning: tempnam() expects parameter 2 to be a valid path, string given in %s on line %d
-- File is not created --
Warning: unlink(): %s in %s on line %d
-- Iteration 7 --
Warning: tempnam() expects parameter 2 to be string, array given in %s on line %d
Warning: tempnam() expects parameter 2 to be a valid path, array given in %s on line %d
-- File is not created --
Warning: unlink(): %s in %s on line %d

View File

@ -41,7 +41,7 @@ var_dump(get_include_path());
echo "Done\n";
?>
--EXPECTF--
--EXPECTF--
string(1) "."
Warning: get_include_path() expects exactly 0 parameters, 1 given in %s on line %d
@ -67,7 +67,7 @@ string(1) "."
NULL
string(1) "."
Warning: set_include_path() expects parameter 1 to be string, array given in %s on line %d
Warning: set_include_path() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
string(1) "."
NULL

View File

@ -0,0 +1,11 @@
--TEST--
Bug #69522 (heap buffer overflow in unpack())
--FILE--
<?php
$a = pack("AAAAAAAAAAAA", 1,2,3,4,5,6,7,8,9,10,11,12);
$b = unpack('h2147483648', $a);
?>
===DONE===
--EXPECTF--
Warning: unpack(): Type h: integer overflow in %s on line %d
===DONE===

View File

@ -33,6 +33,7 @@
#include "php_variables.h"
#include "rfc1867.h"
#include "ext/standard/php_string.h"
#include "ext/standard/php_smart_string.h"
#if defined(PHP_WIN32) && !defined(HAVE_ATOLL)
# define atoll(s) _atoi64(s)
@ -408,8 +409,9 @@ static int find_boundary(multipart_buffer *self, char *boundary)
static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
{
char *line;
mime_header_entry prev_entry = {0}, entry;
int prev_len, cur_len;
mime_header_entry entry = {0};
smart_string buf_value = {0};
char *key = NULL;
/* didn't find boundary, abort */
if (!find_boundary(self, self->boundary)) {
@ -421,7 +423,6 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
while( (line = get_line(self)) && line[0] != '\0' )
{
/* add header to table */
char *key = line;
char *value = NULL;
if (php_rfc1867_encoding_translation()) {
@ -434,31 +435,34 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
}
if (value) {
*value = 0;
if(buf_value.c && key) {
/* new entry, add the old one to the list */
smart_string_0(&buf_value);
entry.key = key;
entry.value = buf_value.c;
zend_llist_add_element(header, &entry);
buf_value.c = NULL;
key = NULL;
}
*value = '\0';
do { value++; } while(isspace(*value));
entry.value = estrdup(value);
entry.key = estrdup(key);
} else if (zend_llist_count(header)) { /* If no ':' on the line, add to previous line */
prev_len = (int)strlen(prev_entry.value);
cur_len = (int)strlen(line);
entry.value = emalloc(prev_len + cur_len + 1);
memcpy(entry.value, prev_entry.value, prev_len);
memcpy(entry.value + prev_len, line, cur_len);
entry.value[cur_len + prev_len] = '\0';
entry.key = estrdup(prev_entry.key);
zend_llist_remove_tail(header);
key = estrdup(line);
smart_string_appends(&buf_value, value);
} else if (buf_value.c) { /* If no ':' on the line, add to previous line */
smart_string_appends(&buf_value, line);
} else {
continue;
}
}
if(buf_value.c && key) {
/* add the last one to the list */
smart_string_0(&buf_value);
entry.key = key;
entry.value = buf_value.c;
zend_llist_add_element(header, &entry);
prev_entry = entry;
}
return 1;