Merge branch 'PHP-7.0' into PHP-7.1

* PHP-7.0: (48 commits)
  Update NEWs
  Unused label
  Fixed bug #72853 (stream_set_blocking doesn't work)
  fix test
  Bug #72663 - part 3
  Bug #72663 - part 2
  Bug #72663 - part 1
  Update NEWS
  BLock test with memory leak
  fix tests
  Fix TSRM build
  Fix bug #72850 - integer overflow in uuencode
  Fixed bug #72849 - integer overflow in urlencode
  Fix bug #72848 - integer overflow in quoted_printable_encode caused heap corruption
  Fix bug #72838 - 	Integer overflow lead to heap corruption in sql_regcase
  Fix bug #72837 - integer overflow in bzdecompress caused heap corruption
  Fix bug #72836 - integer overflow in base64_decode caused heap corruption
  Fix for bug #72807 - do not produce strings with negative length
  Fix for bug #72790 and bug #72799
  Fix bug #72730 - imagegammacorrect allows arbitrary write access
  ...

Conflicts:
	ext/standard/var_unserializer.c
This commit is contained in:
Xinchen Hui 2016-08-17 17:14:30 +08:00
commit ce6ad9bdd9
38 changed files with 1249 additions and 589 deletions

View file

@ -1503,21 +1503,21 @@ static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size, si
ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted"); ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted");
if (info & ZEND_MM_IS_SRUN) { if (info & ZEND_MM_IS_SRUN) {
int old_bin_num, bin_num; int old_bin_num = ZEND_MM_SRUN_BIN_NUM(info);
old_bin_num = ZEND_MM_SRUN_BIN_NUM(info);
old_size = bin_data_size[old_bin_num]; old_size = bin_data_size[old_bin_num];
bin_num = ZEND_MM_SMALL_SIZE_TO_BIN(size); if (size <= ZEND_MM_MAX_SMALL_SIZE) {
if (old_bin_num == bin_num) { int bin_num = ZEND_MM_SMALL_SIZE_TO_BIN(size);
if (old_bin_num == bin_num) {
#if ZEND_DEBUG #if ZEND_DEBUG
dbg = zend_mm_get_debug_info(heap, ptr); dbg = zend_mm_get_debug_info(heap, ptr);
dbg->size = real_size; dbg->size = real_size;
dbg->filename = __zend_filename; dbg->filename = __zend_filename;
dbg->orig_filename = __zend_orig_filename; dbg->orig_filename = __zend_orig_filename;
dbg->lineno = __zend_lineno; dbg->lineno = __zend_lineno;
dbg->orig_lineno = __zend_orig_lineno; dbg->orig_lineno = __zend_orig_lineno;
#endif #endif
return ptr; return ptr;
}
} }
} else /* if (info & ZEND_MM_IS_LARGE_RUN) */ { } else /* if (info & ZEND_MM_IS_LARGE_RUN) */ {
ZEND_MM_CHECK(ZEND_MM_ALIGNED_OFFSET(page_offset, ZEND_MM_PAGE_SIZE) == 0, "zend_mm_heap corrupted"); ZEND_MM_CHECK(ZEND_MM_ALIGNED_OFFSET(page_offset, ZEND_MM_PAGE_SIZE) == 0, "zend_mm_heap corrupted");

View file

@ -595,16 +595,26 @@ static PHP_FUNCTION(bzdecompress)
/* compression is better then 2:1, need to allocate more memory */ /* compression is better then 2:1, need to allocate more memory */
bzs.avail_out = source_len; bzs.avail_out = source_len;
size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
if (size > SIZE_MAX) {
/* no reason to continue if we're going to drop it anyway */
break;
}
dest = safe_erealloc(dest, 1, bzs.avail_out+1, (size_t) size ); dest = safe_erealloc(dest, 1, bzs.avail_out+1, (size_t) size );
bzs.next_out = dest + size; bzs.next_out = dest + size;
} }
if (error == BZ_STREAM_END || error == BZ_OK) { if (error == BZ_STREAM_END || error == BZ_OK) {
size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
dest = safe_erealloc(dest, 1, (size_t) size, 1); if (size > SIZE_MAX) {
dest[size] = '\0'; php_error_docref(NULL TSRMLS_CC, E_WARNING, "Decompressed size too big, max is %zd", SIZE_MAX);
RETVAL_STRINGL(dest, (int) size); efree(dest);
efree(dest); RETVAL_LONG(BZ_MEM_ERROR);
} else {
dest = safe_erealloc(dest, 1, (size_t) size, 1);
dest[size] = '\0';
RETVAL_STRINGL(dest, (size_t) size);
efree(dest);
}
} else { /* real error */ } else { /* real error */
efree(dest); efree(dest);
RETVAL_LONG(error); RETVAL_LONG(error);

View file

@ -3530,7 +3530,7 @@ PHP_FUNCTION(curl_reset)
PHP_FUNCTION(curl_escape) PHP_FUNCTION(curl_escape)
{ {
char *str = NULL, *res = NULL; char *str = NULL, *res = NULL;
size_t str_len = 0; size_t str_len = 0;
zval *zid; zval *zid;
php_curl *ch; php_curl *ch;
@ -3542,6 +3542,10 @@ PHP_FUNCTION(curl_escape)
RETURN_FALSE; RETURN_FALSE;
} }
if (ZEND_SIZE_T_INT_OVFL(str_len)) {
RETURN_FALSE;
}
if ((res = curl_easy_escape(ch->cp, str, str_len))) { if ((res = curl_easy_escape(ch->cp, str, str_len))) {
RETVAL_STRING(res); RETVAL_STRING(res);
curl_free(res); curl_free(res);
@ -3569,7 +3573,7 @@ PHP_FUNCTION(curl_unescape)
RETURN_FALSE; RETURN_FALSE;
} }
if (str_len > INT_MAX) { if (ZEND_SIZE_T_INT_OVFL(str_len)) {
RETURN_FALSE; RETURN_FALSE;
} }

View file

@ -3758,8 +3758,11 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offse
fgot = php_stream_read(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size); fgot = php_stream_read(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size);
if (fgot < ImageInfo->Thumbnail.size) { if (fgot < ImageInfo->Thumbnail.size) {
EXIF_ERRLOG_THUMBEOF(ImageInfo) EXIF_ERRLOG_THUMBEOF(ImageInfo)
efree(ImageInfo->Thumbnail.data);
ImageInfo->Thumbnail.data = NULL;
} else {
exif_thumbnail_build(ImageInfo);
} }
exif_thumbnail_build(ImageInfo);
} }
#ifdef EXIF_DEBUG #ifdef EXIF_DEBUG
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Read next IFD (THUMBNAIL) done"); exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Read next IFD (THUMBNAIL) done");

View file

@ -0,0 +1,71 @@
--TEST--
Bug #72627 (Memory Leakage In exif_process_IFD_in_TIFF)
--SKIPIF--
<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?>
--FILE--
<?php
$exif = exif_read_data(__DIR__ . '/bug72627.tiff',0,0,true);
var_dump($exif);
?>
--EXPECTF--
Warning: exif_read_data(%s): Thumbnail goes IFD boundary or end of file reached in %sbug72627.php on line %d
Warning: exif_read_data(%s): Error in TIFF: filesize(x04E2) less than start of IFD dir(x829A0004) in %sbug72627.php on line %d
Warning: exif_read_data(%s): Thumbnail goes IFD boundary or end of file reached in %sbug72627.php on line %d
array(11) {
["FileName"]=>
string(13) "bug72627.tiff"
["FileDateTime"]=>
int(%d)
["FileSize"]=>
int(1250)
["FileType"]=>
int(7)
["MimeType"]=>
string(10) "image/tiff"
["SectionsFound"]=>
string(30) "ANY_TAG, IFD0, THUMBNAIL, EXIF"
["COMPUTED"]=>
array(10) {
["html"]=>
string(24) "width="128" height="132""
["Height"]=>
int(132)
["Width"]=>
int(128)
["IsColor"]=>
int(0)
["ByteOrderMotorola"]=>
int(0)
["ApertureFNumber"]=>
string(5) "f/1.0"
["Thumbnail.FileType"]=>
int(2)
["Thumbnail.MimeType"]=>
string(10) "image/jpeg"
["Thumbnail.Height"]=>
int(132)
["Thumbnail.Width"]=>
int(128)
}
["XResolution"]=>
string(21) "1414812756/1414812756"
["THUMBNAIL"]=>
array(5) {
["ImageWidth"]=>
int(128)
["ImageLength"]=>
int(132)
["JPEGInterchangeFormat"]=>
int(1280)
["JPEGInterchangeFormatLength"]=>
int(100)
["THUMBNAIL"]=>
NULL
}
["ExposureTime"]=>
string(21) "1414812756/1414812756"
["FNumber"]=>
string(21) "1414812756/1414812756"
}

Binary file not shown.

View file

@ -1537,11 +1537,11 @@ PHP_FUNCTION(imagetruecolortopalette)
RETURN_FALSE; RETURN_FALSE;
} }
if (ncolors <= 0) { if (ncolors <= 0 || ZEND_LONG_INT_OVFL(ncolors)) {
php_error_docref(NULL, E_WARNING, "Number of colors has to be greater than zero"); php_error_docref(NULL, E_WARNING, "Number of colors has to be greater than zero and no more than %d", INT_MAX);
RETURN_FALSE; RETURN_FALSE;
} }
gdImageTrueColorToPalette(im, dither, ncolors); gdImageTrueColorToPalette(im, dither, (int)ncolors);
RETURN_TRUE; RETURN_TRUE;
} }
@ -3039,6 +3039,11 @@ PHP_FUNCTION(imagegammacorrect)
return; return;
} }
if ( input <= 0.0 || output <= 0.0 ) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Gamma values should be positive");
RETURN_FALSE;
}
if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) { if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
RETURN_FALSE; RETURN_FALSE;
} }

View file

@ -0,0 +1,17 @@
--TEST--
Bug #72697: select_colors write out-of-bounds
--SKIPIF--
<?php
if (!function_exists("imagecreatetruecolor")) die("skip");
if (PHP_INT_MAX !== 9223372036854775807) die("skip for 64-bit long systems only");
?>
--FILE--
<?php
$img=imagecreatetruecolor(10, 10);
imagetruecolortopalette($img, false, PHP_INT_MAX / 8);
?>
DONE
--EXPECTF--
Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than 2147483647 in %sbug72697.php on line %d
DONE

View file

@ -0,0 +1,15 @@
--TEST--
Bug #72730: imagegammacorrect allows arbitrary write access
--SKIPIF--
<?php
if (!function_exists("imagecreatetruecolor")) die("skip");
?>
--FILE--
<?php
$img = imagecreatetruecolor(1, 1);
imagegammacorrect($img, -1, 1337);
?>
DONE
--EXPECTF--
Warning: imagegammacorrect(): Gamma values should be positive in %sbug72730.php on line %d
DONE

View file

@ -25,4 +25,4 @@ Warning: imagetruecolortopalette() expects parameter 3 to be integer, resource g
Warning: imagetruecolortopalette() expects parameter 3 to be integer, array given in %s on line %d Warning: imagetruecolortopalette() expects parameter 3 to be integer, array given in %s on line %d
Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s on line %d

View file

@ -16,6 +16,6 @@ imagetruecolortopalette($image, true, -1);
?> ?>
--EXPECTF-- --EXPECTF--
Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s line %d
Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s line %d

View file

@ -633,6 +633,10 @@ PHP_FUNCTION(mcrypt_generic)
RETURN_FALSE RETURN_FALSE
} }
if (data_len > INT_MAX) {
php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX);
RETURN_FALSE;
}
/* Check blocksize */ /* Check blocksize */
if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */ if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */
block_size = mcrypt_enc_get_block_size(pm->td); block_size = mcrypt_enc_get_block_size(pm->td);
@ -645,10 +649,6 @@ PHP_FUNCTION(mcrypt_generic)
memset(ZSTR_VAL(data_str), 0, data_size); memset(ZSTR_VAL(data_str), 0, data_size);
memcpy(ZSTR_VAL(data_str), data, data_len); memcpy(ZSTR_VAL(data_str), data, data_len);
} else { /* It's not a block algorithm */ } else { /* It's not a block algorithm */
if (data_len > INT_MAX) {
php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX);
RETURN_FALSE;
}
data_size = (int)data_len; data_size = (int)data_len;
data_str = zend_string_alloc(data_size, 0); data_str = zend_string_alloc(data_size, 0);
memset(ZSTR_VAL(data_str), 0, data_size); memset(ZSTR_VAL(data_str), 0, data_size);
@ -688,6 +688,10 @@ PHP_FUNCTION(mdecrypt_generic)
} }
/* Check blocksize */ /* Check blocksize */
if (data_len > INT_MAX) {
php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX);
RETURN_FALSE;
}
if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */ if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */
block_size = mcrypt_enc_get_block_size(pm->td); block_size = mcrypt_enc_get_block_size(pm->td);
data_size = ((((int)data_len - 1) / block_size) + 1) * block_size; data_size = ((((int)data_len - 1) / block_size) + 1) * block_size;
@ -699,10 +703,6 @@ PHP_FUNCTION(mdecrypt_generic)
memset(data_s, 0, data_size); memset(data_s, 0, data_size);
memcpy(data_s, data, data_len); memcpy(data_s, data, data_len);
} else { /* It's not a block algorithm */ } else { /* It's not a block algorithm */
if (data_len > INT_MAX) {
php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX);
RETURN_FALSE;
}
data_size = (int)data_len; data_size = (int)data_len;
data_s = emalloc(data_size + 1); data_s = emalloc(data_size + 1);
memset(data_s, 0, data_size); memset(data_s, 0, data_size);

View file

@ -765,12 +765,19 @@ PS_SERIALIZER_DECODE_FUNC(php_serialize) /* {{{ */
const char *endptr = val + vallen; const char *endptr = val + vallen;
zval session_vars; zval session_vars;
php_unserialize_data_t var_hash; php_unserialize_data_t var_hash;
int result;
zend_string *var_name = zend_string_init("_SESSION", sizeof("_SESSION") - 1, 0); zend_string *var_name = zend_string_init("_SESSION", sizeof("_SESSION") - 1, 0);
ZVAL_NULL(&session_vars); ZVAL_NULL(&session_vars);
PHP_VAR_UNSERIALIZE_INIT(var_hash); PHP_VAR_UNSERIALIZE_INIT(var_hash);
php_var_unserialize(&session_vars, (const unsigned char **)&val, (const unsigned char *)endptr, &var_hash); result = php_var_unserialize(
&session_vars, (const unsigned char **)&val, (const unsigned char *)endptr, &var_hash);
PHP_VAR_UNSERIALIZE_DESTROY(var_hash); PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
if (!result) {
zval_ptr_dtor(&session_vars);
ZVAL_NULL(&session_vars);
}
if (!Z_ISUNDEF(PS(http_session_vars))) { if (!Z_ISUNDEF(PS(http_session_vars))) {
zval_ptr_dtor(&PS(http_session_vars)); zval_ptr_dtor(&PS(http_session_vars));
} }
@ -823,11 +830,13 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
int namelen; int namelen;
zend_string *name; zend_string *name;
php_unserialize_data_t var_hash; php_unserialize_data_t var_hash;
int skip = 0;
PHP_VAR_UNSERIALIZE_INIT(var_hash); PHP_VAR_UNSERIALIZE_INIT(var_hash);
for (p = val; p < endptr; ) { for (p = val; p < endptr; ) {
zval *tmp; zval *tmp;
skip = 0;
namelen = ((unsigned char)(*p)) & (~PS_BIN_UNDEF); namelen = ((unsigned char)(*p)) & (~PS_BIN_UNDEF);
if (namelen < 0 || namelen > PS_BIN_MAX || (p + namelen) >= endptr) { if (namelen < 0 || namelen > PS_BIN_MAX || (p + namelen) >= endptr) {
@ -844,8 +853,7 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
if ((tmp = zend_hash_find(&EG(symbol_table), name))) { if ((tmp = zend_hash_find(&EG(symbol_table), name))) {
if ((Z_TYPE_P(tmp) == IS_ARRAY && if ((Z_TYPE_P(tmp) == IS_ARRAY &&
Z_ARRVAL_P(tmp) == &EG(symbol_table)) || tmp == &PS(http_session_vars)) { Z_ARRVAL_P(tmp) == &EG(symbol_table)) || tmp == &PS(http_session_vars)) {
zend_string_release(name); skip = 1;
continue;
} }
} }
@ -854,7 +862,9 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
current = var_tmp_var(&var_hash); current = var_tmp_var(&var_hash);
if (php_var_unserialize(current, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash)) { if (php_var_unserialize(current, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash)) {
ZVAL_PTR(&rv, current); ZVAL_PTR(&rv, current);
php_set_session_var(name, &rv, &var_hash ); if (!skip) {
php_set_session_var(name, &rv, &var_hash);
}
} else { } else {
zend_string_release(name); zend_string_release(name);
php_session_normalize_vars(); php_session_normalize_vars();
@ -916,6 +926,7 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
zend_string *name; zend_string *name;
int has_value, retval = SUCCESS; int has_value, retval = SUCCESS;
php_unserialize_data_t var_hash; php_unserialize_data_t var_hash;
int skip = 0;
PHP_VAR_UNSERIALIZE_INIT(var_hash); PHP_VAR_UNSERIALIZE_INIT(var_hash);
@ -924,6 +935,7 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
while (p < endptr) { while (p < endptr) {
zval *tmp; zval *tmp;
q = p; q = p;
skip = 0;
while (*q != PS_DELIMITER) { while (*q != PS_DELIMITER) {
if (++q >= endptr) goto break_outer_loop; if (++q >= endptr) goto break_outer_loop;
} }
@ -941,7 +953,7 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
if ((tmp = zend_hash_find(&EG(symbol_table), name))) { if ((tmp = zend_hash_find(&EG(symbol_table), name))) {
if ((Z_TYPE_P(tmp) == IS_ARRAY && if ((Z_TYPE_P(tmp) == IS_ARRAY &&
Z_ARRVAL_P(tmp) == &EG(symbol_table)) || tmp == &PS(http_session_vars)) { Z_ARRVAL_P(tmp) == &EG(symbol_table)) || tmp == &PS(http_session_vars)) {
goto skip; skip = 1;
} }
} }
@ -950,16 +962,19 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
current = var_tmp_var(&var_hash); current = var_tmp_var(&var_hash);
if (php_var_unserialize(current, (const unsigned char **)&q, (const unsigned char *)endptr, &var_hash)) { if (php_var_unserialize(current, (const unsigned char **)&q, (const unsigned char *)endptr, &var_hash)) {
ZVAL_PTR(&rv, current); ZVAL_PTR(&rv, current);
php_set_session_var(name, &rv, &var_hash); if (!skip) {
php_set_session_var(name, &rv, &var_hash);
}
} else { } else {
zend_string_release(name); zend_string_release(name);
retval = FAILURE; retval = FAILURE;
goto break_outer_loop; goto break_outer_loop;
} }
} else { } else {
PS_ADD_VARL(name); if(!skip) {
PS_ADD_VARL(name);
}
} }
skip:
zend_string_release(name); zend_string_release(name);
p = q; p = q;

View file

@ -0,0 +1,17 @@
--TEST--
Bug #72681: PHP Session Data Injection Vulnerability
--SKIPIF--
<?php include('skipif.inc'); ?>
--FILE--
<?php
ini_set('session.serialize_handler', 'php');
session_start();
$GLOBALS['ryat'] = $GLOBALS;
$_SESSION['ryat'] = 'ryat|O:8:"stdClass":0:{}';
session_write_close();
session_start();
var_dump($_SESSION);
?>
--EXPECT--
array(0) {
}

View file

@ -1008,7 +1008,7 @@ static int php_snmp_parse_oid(zval *object, int st, struct objid_query *objid_qu
php_error_docref(NULL, E_WARNING, "Got empty OID array"); php_error_docref(NULL, E_WARNING, "Got empty OID array");
return FALSE; return FALSE;
} }
objid_query->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg) * zend_hash_num_elements(Z_ARRVAL_P(oid))); objid_query->vars = (snmpobjarg *)safe_emalloc(sizeof(snmpobjarg), zend_hash_num_elements(Z_ARRVAL_P(oid)), 0);
if (objid_query->vars == NULL) { if (objid_query->vars == NULL) {
php_error_docref(NULL, E_WARNING, "emalloc() failed while parsing oid array: %s", strerror(errno)); php_error_docref(NULL, E_WARNING, "emalloc() failed while parsing oid array: %s", strerror(errno));
efree(objid_query->vars); efree(objid_query->vars);

View file

@ -59,7 +59,7 @@ PHPAPI zend_string *php_base64_encode(const unsigned char *str, size_t length) /
unsigned char *p; unsigned char *p;
zend_string *result; zend_string *result;
result = zend_string_alloc(((length + 2) / 3) * 4 * sizeof(char), 0); result = zend_string_safe_alloc(((length + 2) / 3), 4 * sizeof(char), 0, 0);
p = (unsigned char *)ZSTR_VAL(result); p = (unsigned char *)ZSTR_VAL(result);
while (length > 2) { /* keep going until we have less than 24 bits */ while (length > 2) { /* keep going until we have less than 24 bits */

View file

@ -188,7 +188,8 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char
/* get the response */ /* get the response */
result = GET_FTP_RESULT(stream); result = GET_FTP_RESULT(stream);
if (result != 334) { if (result != 334) {
use_ssl = 0; php_stream_wrapper_log_error(wrapper, options, "Server doesn't support FTPS.");
goto connect_errexit;
} else { } else {
/* we must reuse the old SSL session id */ /* we must reuse the old SSL session id */
/* if we talk to an old ftpd-ssl */ /* if we talk to an old ftpd-ssl */

View file

@ -52,19 +52,22 @@
#define SMART_STRING_DO_REALLOC(d, what) \ #define SMART_STRING_DO_REALLOC(d, what) \
(d)->c = SMART_STRING_REALLOC((d)->c, (d)->a + 1, (what)) (d)->c = SMART_STRING_REALLOC((d)->c, (d)->a + 1, (what))
#define smart_string_alloc4(d, n, what, newlen) do { \ #define smart_string_alloc4(d, n, what, newlen) do { \
if (!(d)->c) { \ if (!(d)->c) { \
(d)->len = 0; \ (d)->len = 0; \
newlen = (n); \ newlen = (n); \
(d)->a = newlen < SMART_STRING_START_SIZE \ (d)->a = newlen < SMART_STRING_START_SIZE \
? SMART_STRING_START_SIZE \ ? SMART_STRING_START_SIZE \
: newlen + SMART_STRING_PREALLOC; \ : newlen + SMART_STRING_PREALLOC; \
SMART_STRING_DO_REALLOC(d, what); \ SMART_STRING_DO_REALLOC(d, what); \
} else { \ } else { \
if(UNEXPECTED(n > SIZE_MAX - (d)->len)) { \
zend_error(E_ERROR, "String size overflow"); \
} \
newlen = (d)->len + (n); \ newlen = (d)->len + (n); \
if (newlen >= (d)->a) { \ if (newlen >= (d)->a) { \
(d)->a = newlen + SMART_STRING_PREALLOC; \ (d)->a = newlen + SMART_STRING_PREALLOC; \
SMART_STRING_DO_REALLOC(d, what); \ SMART_STRING_DO_REALLOC(d, what); \
} \ } \
} \ } \
} while (0) } while (0)

View file

@ -275,7 +275,7 @@ PHP_FUNCTION(quoted_printable_encode)
RETURN_EMPTY_STRING(); RETURN_EMPTY_STRING();
} }
new_str = php_quot_print_encode((unsigned char *)ZSTR_VAL(str), (size_t)ZSTR_LEN(str)); new_str = php_quot_print_encode((unsigned char *)ZSTR_VAL(str), ZSTR_LEN(str));
RETURN_STR(new_str); RETURN_STR(new_str);
} }
/* }}} */ /* }}} */

View file

@ -0,0 +1,56 @@
--TEST--
Bug #72663 (1): Don't call __destruct if __wakeup not called or fails
--FILE--
<?php
class Test1 {
public function __wakeup() {
echo "Wakeup\n";
}
public function __destruct() {
echo "Dtor\n";
}
}
class Test2 {
public function __wakeup() {
throw new Exception('Unserialization forbidden');
}
public function __destruct() {
echo "Dtor\n";
}
}
// Unserialize object with error in properties
$s = 'O:5:"Test1":1:{s:10:"";}';
var_dump(unserialize($s));
// Variation: Object is turned into a reference
$s = 'O:5:"Test1":2:{i:0;R:1;s:10:"";}';
var_dump(unserialize($s));
// Unserialize object with throwing __wakeup
$s = 'O:5:"Test2":0:{}';
try {
var_dump(unserialize($s));
} catch (Exception $e) {
echo "Caught\n";
}
//
// Variation: Object is turned into a reference
$s = 'O:5:"Test2":1:{i:0;R:1;}';
try {
var_dump(unserialize($s));
} catch (Exception $e) {
echo "Caught\n";
}
?>
--EXPECTF--
Notice: unserialize(): Error at offset 17 of 24 bytes in %s on line %d
bool(false)
Notice: unserialize(): Error at offset 25 of 32 bytes in %s on line %d
bool(false)
Caught
Caught

View file

@ -0,0 +1,27 @@
--TEST--
Bug #72663 (2): Don't allow references into failed unserialize
--FILE--
<?php
class obj implements Serializable {
public $data;
function serialize() {
return serialize($this->data);
}
function unserialize($data) {
$this->data = unserialize($data);
}
}
$inner = 'a:1:{i:0;O:9:"Exception":2:{s:7:"'."\0".'*'."\0".'file";R:4;}';
$exploit = 'a:2:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:1;R:4;}';
var_dump(unserialize($exploit));
?>
--EXPECTF--
Notice: unserialize(): Unexpected end of serialized data in %s on line %d
Notice: unserialize(): Error at offset 46 of 47 bytes in %s on line %d
Notice: unserialize(): Error at offset 79 of 80 bytes in %s on line %d
bool(false)

View file

@ -0,0 +1,17 @@
--TEST--
Bug #72663 (3): If unserialization fails, don't initialize the session with the result
--SKIPIF--
<?php if (!extension_loaded('session')) die('skip Session extension required'); ?>
--INI--
session.serialize_handler=php_serialize
--FILE--
<?php
session_start();
$sess = 'O:9:"Exception":2:{s:7:"'."\0".'*'."\0".'file";R:1;}';
session_decode($sess);
var_dump($_SESSION);
?>
--EXPECTF--
Notice: session_decode(): Unexpected end of serialized data in %s on line %d
array(0) {
}

View file

@ -0,0 +1,59 @@
--TEST--
Bug #72853 (stream_set_blocking doesn't work)
--SKIPIF--
<?php
if(substr(PHP_OS, 0, 3) == 'WIN' ) {
die('skip not for windows');
}
?>
--FILE--
<?php
$descs = array(
0 => array('pipe', 'r'), // stdin
1 => array('pipe', 'w'), // stdout
);
$p = proc_open("ls", $descs, $pipes, '.', NULL, NULL);
stream_set_blocking($pipes[1], false);
var_dump(stream_get_meta_data($pipes[1]));
stream_set_blocking($pipes[1], true);
while ($outs = fgets($pipes[1], 1024)) {
}
var_dump(stream_get_meta_data($pipes[1]));
proc_close($p);
?>
--EXPECTF--
array(7) {
["timed_out"]=>
bool(false)
["blocked"]=>
bool(false)
["eof"]=>
bool(false)
["stream_type"]=>
string(5) "STDIO"
["mode"]=>
string(1) "r"
["unread_bytes"]=>
int(0)
["seekable"]=>
bool(false)
}
array(7) {
["timed_out"]=>
bool(false)
["blocked"]=>
bool(true)
["eof"]=>
bool(true)
["stream_type"]=>
string(5) "STDIO"
["mode"]=>
string(1) "r"
["unread_bytes"]=>
int(0)
["seekable"]=>
bool(false)
}

View file

@ -0,0 +1,65 @@
--TEST--
Bug #70436: Use After Free Vulnerability in unserialize()
--FILE--
<?php
class obj implements Serializable
{
var $data;
function serialize()
{
return serialize($this->data);
}
function unserialize($data)
{
$this->data = unserialize($data);
}
}
$fakezval = ptr2str(1122334455);
$fakezval .= ptr2str(0);
$fakezval .= "\x00\x00\x00\x00";
$fakezval .= "\x01";
$fakezval .= "\x00";
$fakezval .= "\x00\x00";
$inner = 'C:3:"obj":3:{ryat';
$exploit = 'a:4:{i:0;i:1;i:1;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:2;s:'.strlen($fakezval).':"'.$fakezval.'";i:3;R:5;}';
$data = unserialize($exploit);
var_dump($data);
function ptr2str($ptr)
{
$out = '';
for ($i = 0; $i < 8; $i++) {
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}
?>
DONE
--EXPECTF--
Notice: unserialize(): Error at offset 0 of 3 bytes in %sbug70436.php on line %d
Notice: unserialize(): Error at offset 17 of 17 bytes in %sbug70436.php on line %d
array(4) {
[0]=>
int(1)
[1]=>
object(obj)#%d (1) {
["data"]=>
bool(false)
}
[2]=>
string(24) "%s"
[3]=>
bool(false)
}
DONE

View file

@ -0,0 +1,26 @@
--TEST--
Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization
--FILE--
<?php
class obj implements Serializable {
var $data;
function serialize() {
return serialize($this->data);
}
function unserialize($data) {
$this->data = unserialize($data);
}
}
$inner = 'a:1:{i:0;O:9:"Exception":2:{s:7:"'."\0".'*'."\0".'file";R:4;}';
$exploit = 'a:2:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:1;R:4;}';
$data = unserialize($exploit);
echo $data[1];
?>
DONE
--EXPECTF--
Notice: unserialize(): Unexpected end of serialized data in %sbug72663.php on line %d
Notice: unserialize(): Error at offset 46 of 47 bytes in %sbug72663.php on line %d
DONE

View file

@ -0,0 +1,17 @@
--TEST--
Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization
--FILE--
<?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
$sess = 'O:9:"Exception":2:{s:7:"'."\0".'*'."\0".'file";R:1;}';
session_decode($sess);
var_dump($_SESSION);
?>
DONE
--EXPECTF--
Notice: session_decode(): Unexpected end of serialized data in %sbug72663_2.php on line %d
array(0) {
}
DONE

View file

@ -0,0 +1,20 @@
--TEST--
Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization
--XFAIL--
Memory leak, TBF later.
--FILE--
<?php
class obj {
var $ryat;
function __wakeup() {
$this->ryat = str_repeat('A', 0x112);
}
}
$poc = 'O:8:"stdClass":1:{i:0;O:3:"obj":1:{s:4:"ryat";R:1;';
unserialize($poc);
?>
DONE
--EXPECTF--
Notice: unserialize(): Error at offset 51 of 50 bytes in %sbug72663_3.php on line %d
DONE

View file

@ -71,8 +71,10 @@ PHPAPI zend_string *php_uuencode(char *src, size_t src_len) /* {{{ */
char *p, *s, *e, *ee; char *p, *s, *e, *ee;
zend_string *dest; zend_string *dest;
/* encoded length is ~ 38% greater than the original */ /* encoded length is ~ 38% greater than the original
dest = zend_string_alloc((size_t)ceil(src_len * 1.38) + 46, 0); Use 1.5 for easier calculation.
*/
dest = zend_string_safe_alloc(src_len/2, 3, 46, 0);
p = ZSTR_VAL(dest); p = ZSTR_VAL(dest);
s = src; s = src;
e = src + src_len; e = src + src_len;

File diff suppressed because it is too large Load diff

View file

@ -340,6 +340,8 @@ static inline size_t parse_uiv(const unsigned char *p)
#define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash, HashTable *classes #define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash, HashTable *classes
#define UNSERIALIZE_PASSTHRU rval, p, max, var_hash, classes #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash, classes
static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER);
static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops) static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
{ {
while (elements-- > 0) { while (elements-- > 0) {
@ -348,7 +350,7 @@ static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTab
ZVAL_UNDEF(&key); ZVAL_UNDEF(&key);
if (!php_var_unserialize_ex(&key, p, max, NULL, classes)) { if (!php_var_unserialize_internal(&key, p, max, NULL, classes)) {
zval_dtor(&key); zval_dtor(&key);
return 0; return 0;
} }
@ -404,7 +406,7 @@ string_key:
} }
} }
if (!php_var_unserialize_ex(data, p, max, var_hash, classes)) { if (!php_var_unserialize_internal(data, p, max, var_hash, classes)) {
zval_dtor(&key); zval_dtor(&key);
return 0; return 0;
} }
@ -494,23 +496,32 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
zval retval; zval retval;
zval fname; zval fname;
HashTable *ht; HashTable *ht;
zend_bool has_wakeup;
if (Z_TYPE_P(rval) != IS_OBJECT) { if (Z_TYPE_P(rval) != IS_OBJECT) {
return 0; return 0;
} }
has_wakeup = Z_OBJCE_P(rval) != PHP_IC_ENTRY
&& zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1);
ht = Z_OBJPROP_P(rval); ht = Z_OBJPROP_P(rval);
zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED)); zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED));
if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) { if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
if (has_wakeup) {
ZVAL_DEREF(rval);
GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED;
}
return 0; return 0;
} }
ZVAL_DEREF(rval); ZVAL_DEREF(rval);
if (Z_OBJCE_P(rval) != PHP_IC_ENTRY && if (has_wakeup) {
zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1)) {
ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1); ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1);
BG(serialize_lock)++; BG(serialize_lock)++;
call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL); if (call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) {
GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED;
}
BG(serialize_lock)--; BG(serialize_lock)--;
zval_dtor(&fname); zval_dtor(&fname);
zval_dtor(&retval); zval_dtor(&retval);
@ -521,7 +532,6 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
} }
return finish_nested_data(UNSERIALIZE_PASSTHRU); return finish_nested_data(UNSERIALIZE_PASSTHRU);
} }
#ifdef PHP_WIN32 #ifdef PHP_WIN32
# pragma optimize("", on) # pragma optimize("", on)
@ -533,8 +543,34 @@ PHPAPI int php_var_unserialize(zval *rval, const unsigned char **p, const unsign
return php_var_unserialize_ex(UNSERIALIZE_PASSTHRU); return php_var_unserialize_ex(UNSERIALIZE_PASSTHRU);
} }
PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER) PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
{
var_entries *orig_var_entries = (*var_hash)->last;
zend_long orig_used_slots = orig_var_entries ? orig_var_entries->used_slots : 0;
int result;
result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU);
if (!result) {
/* If the unserialization failed, mark all elements that have been added to var_hash
* as NULL. This will forbid their use by other unserialize() calls in the same
* unserialization context. */
var_entries *e = orig_var_entries;
zend_long s = orig_used_slots;
while (e) {
for (; s < e->used_slots; s++) {
e->data[s] = NULL;
}
e = e->next;
s = 0;
}
}
return result;
}
static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
{ {
const unsigned char *cursor, *limit, *marker, *start; const unsigned char *cursor, *limit, *marker, *start;
zval *rval_ref; zval *rval_ref;

View file

@ -1,5 +1,7 @@
--TEST-- --TEST--
Bug #72142: WDDX Packet Injection Vulnerability in wddx_serialize_value() Bug #72142: WDDX Packet Injection Vulnerability in wddx_serialize_value()
--SKIPIF--
<?php if (!extension_loaded("wddx")) print "skip"; ?>
--FILE-- --FILE--
<?php <?php

View file

@ -0,0 +1,34 @@
--TEST--
Bug #72749: wddx_deserialize allows illegal memory access
--SKIPIF--
<?php
if (!extension_loaded('wddx')) {
die('skip. wddx not available');
}
?>
--FILE--
<?php
$xml = <<<XML
<?xml version='1.0'?>
<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
<wddxPacket version='1.0'>
<header/>
<data>
<struct>
<var name='aDateTime3'>
<dateTime>2\r2004-09-10T05:52:49+00</dateTime>
</var>
</struct>
</data>
</wddxPacket>
XML;
$array = wddx_deserialize($xml);
var_dump($array);
?>
--EXPECT--
array(1) {
["aDateTime3"]=>
string(24) "2
2004-09-10T05:52:49+00"
}

View file

@ -0,0 +1,34 @@
--TEST--
Bug #72750: wddx_deserialize null dereference
--SKIPIF--
<?php
if (!extension_loaded('wddx')) {
die('skip. wddx not available');
}
?>
--FILE--
<?php
$xml = <<< XML
<?xml version='1.0'?>
<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
<wddxPacket version='1.0'>
<header/>
<data>
<struct>
<var name='aBinary'>
<binary length='11'>\\tYmluYXJRhdGE=</binary>
</var>
</struct>
</data>
</wddxPacket>
XML;
$array = wddx_deserialize($xml);
var_dump($array);
?>
--EXPECT--
array(1) {
["aBinary"]=>
string(0) ""
}

View file

@ -0,0 +1,36 @@
--TEST--
Bug 72790: wddx_deserialize null dereference with invalid xml
--SKIPIF--
<?php
if (!extension_loaded('wddx')) {
die('skip. wddx not available');
}
?>
--FILE--
<?php
$xml = <<< XML
<?xml version='1.0' ?>
<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
<wddxPacket version='1.0'>
|array>
<var name="XXXX">
<boolean value="this">
</boolean>
</var>
<var name="YYYY">
<var name="UUUU">
<var name="EZEZ">
</var>
</var>
</var>
</array>
</wddxPacket>
XML;
$array = wddx_deserialize($xml);
var_dump($array);
?>
--EXPECTF--
Notice: Undefined variable: array in %s%ebug72790.php on line %d
NULL

View file

@ -0,0 +1,29 @@
--TEST--
Bug #72799: wddx_deserialize null dereference in php_wddx_pop_element
--SKIPIF--
<?php
if (!extension_loaded('wddx')) {
die('skip. wddx not available');
}
?>
--FILE--
<?php
$xml = <<<XML
<?xml version='1.0'?>
<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
<wddxPacket version="1.0">
<var name="XXXX">
<boolean value="1">
<dateTime>1998-06-12T04:32:12+00</dateTime>
</boolean>
</var>
</wddxPacket>
XML;
$array = wddx_deserialize($xml);
var_dump($array);
?>
--EXPECTF--
Notice: Undefined variable: array in %s%ebug72799.php on line 16
NULL

View file

@ -886,10 +886,10 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
if (Z_TYPE(ent1->data) == IS_UNDEF) { if (Z_TYPE(ent1->data) == IS_UNDEF) {
if (stack->top > 1) { if (stack->top > 1) {
stack->top--; stack->top--;
efree(ent1);
} else { } else {
stack->done = 1; stack->done = 1;
} }
efree(ent1);
return; return;
} }
@ -897,7 +897,11 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
zend_string *new_str = php_base64_decode( zend_string *new_str = php_base64_decode(
(unsigned char *)Z_STRVAL(ent1->data), Z_STRLEN(ent1->data)); (unsigned char *)Z_STRVAL(ent1->data), Z_STRLEN(ent1->data));
zval_ptr_dtor(&ent1->data); zval_ptr_dtor(&ent1->data);
ZVAL_STR(&ent1->data, new_str); if (new_str) {
ZVAL_STR(&ent1->data, new_str);
} else {
ZVAL_EMPTY_STRING(&ent1->data);
}
} }
/* Call __wakeup() method on the object. */ /* Call __wakeup() method on the object. */
@ -917,7 +921,7 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
wddx_stack_top(stack, (void**)&ent2); wddx_stack_top(stack, (void**)&ent2);
/* if non-existent field */ /* if non-existent field */
if (ent2->type == ST_FIELD && Z_ISUNDEF(ent2->data)) { if (Z_ISUNDEF(ent2->data)) {
zval_ptr_dtor(&ent1->data); zval_ptr_dtor(&ent1->data);
efree(ent1); efree(ent1);
return; return;
@ -1030,16 +1034,23 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len)
case ST_DATETIME: { case ST_DATETIME: {
char *tmp; char *tmp;
tmp = emalloc(len + 1); if (Z_TYPE(ent->data) == IS_STRING) {
memcpy(tmp, (char *)s, len); tmp = safe_emalloc(Z_STRLEN(ent->data), 1, (size_t)len + 1);
memcpy(tmp, Z_STRVAL(ent->data), Z_STRLEN(ent->data));
memcpy(tmp + Z_STRLEN(ent->data), s, len);
len += Z_STRLEN(ent->data);
zval_dtor(&ent->data);
} else {
tmp = emalloc(len + 1);
memcpy(tmp, (char *)s, len);
}
tmp[len] = '\0'; tmp[len] = '\0';
Z_LVAL(ent->data) = php_parse_date(tmp, NULL); ZVAL_LONG(&ent->data, php_parse_date(tmp, NULL));
/* date out of range < 1969 or > 2038 */ /* date out of range < 1969 or > 2038 */
if (Z_LVAL(ent->data) == -1) { if (Z_LVAL(ent->data) == -1) {
ZVAL_STRINGL(&ent->data, (char *)s, len); ZVAL_STRINGL(&ent->data, (char *)tmp, len);
} }
efree(tmp);
} }
break; break;
@ -1073,8 +1084,12 @@ int php_wddx_deserialize_ex(const char *value, size_t vallen, zval *return_value
if (stack.top == 1) { if (stack.top == 1) {
wddx_stack_top(&stack, (void**)&ent); wddx_stack_top(&stack, (void**)&ent);
ZVAL_COPY(return_value, &ent->data); if (Z_ISUNDEF(ent->data)) {
retval = SUCCESS; retval = FAILURE;
} else {
ZVAL_COPY(return_value, &ent->data);
retval = SUCCESS;
}
} else { } else {
retval = FAILURE; retval = FAILURE;
} }

View file

@ -144,7 +144,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path
char *path_file; char *path_file;
int resolved_basedir_len; int resolved_basedir_len;
int resolved_name_len; int resolved_name_len;
int path_len; size_t path_len;
int nesting_level = 0; int nesting_level = 0;
/* Special case basedir==".": Use script-directory */ /* Special case basedir==".": Use script-directory */
@ -153,7 +153,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path
strlcpy(local_open_basedir, basedir, sizeof(local_open_basedir)); strlcpy(local_open_basedir, basedir, sizeof(local_open_basedir));
} }
path_len = (int)strlen(path); path_len = strlen(path);
if (path_len > (MAXPATHLEN - 1)) { if (path_len > (MAXPATHLEN - 1)) {
/* empty and too long paths are invalid */ /* empty and too long paths are invalid */
return -1; return -1;
@ -164,7 +164,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path
return -1; return -1;
} }
path_len = (int)strlen(resolved_name); path_len = strlen(resolved_name);
memcpy(path_tmp, resolved_name, path_len + 1); /* safe */ memcpy(path_tmp, resolved_name, path_len + 1); /* safe */
while (VCWD_REALPATH(path_tmp, resolved_name) == NULL) { while (VCWD_REALPATH(path_tmp, resolved_name) == NULL) {

View file

@ -857,7 +857,19 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
data->is_pipe_blocking = value; data->is_pipe_blocking = value;
return PHP_STREAM_OPTION_RETURN_OK; return PHP_STREAM_OPTION_RETURN_OK;
#endif #endif
case PHP_STREAM_OPTION_META_DATA_API:
if (fd == -1)
return -1;
#ifdef O_NONBLOCK
flags = fcntl(fd, F_GETFL, 0);
add_assoc_bool((zval*)ptrparam, "timed_out", 0);
add_assoc_bool((zval*)ptrparam, "blocked", (flags & O_NONBLOCK)? 0 : 1);
add_assoc_bool((zval*)ptrparam, "eof", stream->eof);
return PHP_STREAM_OPTION_RETURN_OK;
#endif
return -1;
default: default:
return PHP_STREAM_OPTION_RETURN_NOTIMPL; return PHP_STREAM_OPTION_RETURN_NOTIMPL;
} }