summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2015-09-01 11:40:15 -0700
committerStanislav Malyshev <stas@php.net>2015-09-01 11:40:15 -0700
commit48cfd1160b4667115f33c4398215759d5e0643d8 (patch)
tree400a688b74adb2d1577c46f37a2a870f00988663
parent9ff333439721dd42faa2e1c838c178633703ef0c (diff)
parent7c31203935589ab4fcb104041ef9d87f747bfee4 (diff)
downloadphp-git-48cfd1160b4667115f33c4398215759d5e0643d8.tar.gz
Merge branch 'PHP-5.4.45' into PHP-5.4
* PHP-5.4.45: Improve fix for #70172 Fix bug #70312 - HAVAL gives wrong hashes in specific cases fix test add test Fix bug #70366 - use-after-free vulnerability in unserialize() with SplDoublyLinkedList Fix bug #70365 - use-after-free vulnerability in unserialize() with SplObjectStorage Fix bug #70172 - Use After Free Vulnerability in unserialize() Fix bug #70388 - SOAP serialize_function_call() type confusion Fixed bug #70350: ZipArchive::extractTo allows for directory traversal when creating directories Improve fix for #70385 Fix bug #70345 (Multiple vulnerabilities related to PCRE functions) Fix bug #70385 (Buffer over-read in exif_read_data with TIFF IFD tag byte value of 32 bytes) Fix bug #70219 (Use after free vulnerability in session deserializer) Fix for bug #69782
-rw-r--r--ext/exif/exif.c212
-rw-r--r--ext/hash/hash_haval.c10
-rw-r--r--ext/hash/tests/bug70312.phpt18
-rw-r--r--ext/pcre/php_pcre.c152
-rw-r--r--ext/pcre/tests/bug70345.phpt24
-rw-r--r--ext/session/session.c36
-rw-r--r--ext/session/tests/session_decode_error2.phpt518
-rw-r--r--ext/session/tests/session_decode_variation3.phpt2
-rw-r--r--ext/soap/soap.c96
-rw-r--r--ext/soap/tests/bug70388.phpt17
-rw-r--r--ext/spl/spl_dllist.c1
-rw-r--r--ext/spl/spl_observer.c2
-rw-r--r--ext/spl/tests/bug70155.phpt50
-rw-r--r--ext/spl/tests/bug70365.phpt50
-rw-r--r--ext/spl/tests/bug70366.phpt54
-rw-r--r--ext/standard/tests/serialize/bug70172.phpt54
-rw-r--r--ext/standard/tests/serialize/bug70172_2.phpt68
-rw-r--r--ext/standard/tests/serialize/bug70219.phpt38
-rw-r--r--ext/standard/var.c24
-rw-r--r--ext/standard/var_unserializer.c140
-rw-r--r--ext/standard/var_unserializer.re76
-rw-r--r--ext/xsl/xsltprocessor.c142
-rw-r--r--ext/zip/php_zip.c78
-rw-r--r--ext/zip/tests/bug70350.phpt33
24 files changed, 1018 insertions, 877 deletions
diff --git a/ext/exif/exif.c b/ext/exif/exif.c
index 7f95ff43ea..05041c5f00 100644
--- a/ext/exif/exif.c
+++ b/ext/exif/exif.c
@@ -74,7 +74,7 @@
#include "php_ini.h"
#include "ext/standard/php_string.h"
#include "ext/standard/php_image.h"
-#include "ext/standard/info.h"
+#include "ext/standard/info.h"
/* needed for ssize_t definition */
#include <sys/types.h>
@@ -161,7 +161,7 @@ ZEND_BEGIN_MODULE_GLOBALS(exif)
char * encode_jis;
char * decode_jis_be;
char * decode_jis_le;
-ZEND_END_MODULE_GLOBALS(exif)
+ZEND_END_MODULE_GLOBALS(exif)
ZEND_DECLARE_MODULE_GLOBALS(exif)
@@ -170,7 +170,7 @@ ZEND_DECLARE_MODULE_GLOBALS(exif)
#else
#define EXIF_G(v) (exif_globals.v)
#endif
-
+
/* {{{ PHP_INI
*/
@@ -213,7 +213,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("exif.decode_jis_intel", "JIS", PHP_INI_ALL, OnUpdateDecode, decode_jis_le, zend_exif_globals, exif_globals)
PHP_INI_END()
/* }}} */
-
+
/* {{{ PHP_GINIT_FUNCTION
*/
static PHP_GINIT_FUNCTION(exif)
@@ -233,9 +233,9 @@ PHP_MINIT_FUNCTION(exif)
{
REGISTER_INI_ENTRIES();
if (zend_hash_exists(&module_registry, "mbstring", sizeof("mbstring"))) {
- REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", 1, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", 1, CONST_CS | CONST_PERSISTENT);
} else {
- REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", 0, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", 0, CONST_CS | CONST_PERSISTENT);
}
return SUCCESS;
}
@@ -265,7 +265,7 @@ zend_module_entry exif_module_entry = {
exif_module_deps,
"exif",
exif_functions,
- PHP_MINIT(exif),
+ PHP_MINIT(exif),
PHP_MSHUTDOWN(exif),
NULL, NULL,
PHP_MINFO(exif),
@@ -278,7 +278,7 @@ zend_module_entry exif_module_entry = {
NULL,
NULL,
STANDARD_MODULE_PROPERTIES_EX
-#else
+#else
STANDARD_MODULE_PROPERTIES
#endif
};
@@ -667,73 +667,73 @@ static tag_info_array tag_table_IFD = {
{ 0x0213, "YCbCrPositioning"},
{ 0x0214, "ReferenceBlackWhite"},
{ 0x02BC, "ExtensibleMetadataPlatform"}, /* XAP: Extensible Authoring Publishing, obsoleted by XMP: Extensible Metadata Platform */
- { 0x0301, "Gamma"},
- { 0x0302, "ICCProfileDescriptor"},
- { 0x0303, "SRGBRenderingIntent"},
- { 0x0320, "ImageTitle"},
- { 0x5001, "ResolutionXUnit"},
- { 0x5002, "ResolutionYUnit"},
- { 0x5003, "ResolutionXLengthUnit"},
- { 0x5004, "ResolutionYLengthUnit"},
- { 0x5005, "PrintFlags"},
- { 0x5006, "PrintFlagsVersion"},
- { 0x5007, "PrintFlagsCrop"},
- { 0x5008, "PrintFlagsBleedWidth"},
- { 0x5009, "PrintFlagsBleedWidthScale"},
- { 0x500A, "HalftoneLPI"},
- { 0x500B, "HalftoneLPIUnit"},
- { 0x500C, "HalftoneDegree"},
- { 0x500D, "HalftoneShape"},
- { 0x500E, "HalftoneMisc"},
- { 0x500F, "HalftoneScreen"},
- { 0x5010, "JPEGQuality"},
- { 0x5011, "GridSize"},
- { 0x5012, "ThumbnailFormat"},
- { 0x5013, "ThumbnailWidth"},
- { 0x5014, "ThumbnailHeight"},
- { 0x5015, "ThumbnailColorDepth"},
- { 0x5016, "ThumbnailPlanes"},
- { 0x5017, "ThumbnailRawBytes"},
- { 0x5018, "ThumbnailSize"},
- { 0x5019, "ThumbnailCompressedSize"},
- { 0x501A, "ColorTransferFunction"},
- { 0x501B, "ThumbnailData"},
- { 0x5020, "ThumbnailImageWidth"},
- { 0x5021, "ThumbnailImageHeight"},
- { 0x5022, "ThumbnailBitsPerSample"},
- { 0x5023, "ThumbnailCompression"},
- { 0x5024, "ThumbnailPhotometricInterp"},
- { 0x5025, "ThumbnailImageDescription"},
- { 0x5026, "ThumbnailEquipMake"},
- { 0x5027, "ThumbnailEquipModel"},
- { 0x5028, "ThumbnailStripOffsets"},
- { 0x5029, "ThumbnailOrientation"},
- { 0x502A, "ThumbnailSamplesPerPixel"},
- { 0x502B, "ThumbnailRowsPerStrip"},
- { 0x502C, "ThumbnailStripBytesCount"},
- { 0x502D, "ThumbnailResolutionX"},
- { 0x502E, "ThumbnailResolutionY"},
- { 0x502F, "ThumbnailPlanarConfig"},
- { 0x5030, "ThumbnailResolutionUnit"},
- { 0x5031, "ThumbnailTransferFunction"},
- { 0x5032, "ThumbnailSoftwareUsed"},
- { 0x5033, "ThumbnailDateTime"},
- { 0x5034, "ThumbnailArtist"},
- { 0x5035, "ThumbnailWhitePoint"},
- { 0x5036, "ThumbnailPrimaryChromaticities"},
- { 0x5037, "ThumbnailYCbCrCoefficients"},
- { 0x5038, "ThumbnailYCbCrSubsampling"},
- { 0x5039, "ThumbnailYCbCrPositioning"},
- { 0x503A, "ThumbnailRefBlackWhite"},
- { 0x503B, "ThumbnailCopyRight"},
- { 0x5090, "LuminanceTable"},
- { 0x5091, "ChrominanceTable"},
- { 0x5100, "FrameDelay"},
- { 0x5101, "LoopCount"},
- { 0x5110, "PixelUnit"},
- { 0x5111, "PixelPerUnitX"},
- { 0x5112, "PixelPerUnitY"},
- { 0x5113, "PaletteHistogram"},
+ { 0x0301, "Gamma"},
+ { 0x0302, "ICCProfileDescriptor"},
+ { 0x0303, "SRGBRenderingIntent"},
+ { 0x0320, "ImageTitle"},
+ { 0x5001, "ResolutionXUnit"},
+ { 0x5002, "ResolutionYUnit"},
+ { 0x5003, "ResolutionXLengthUnit"},
+ { 0x5004, "ResolutionYLengthUnit"},
+ { 0x5005, "PrintFlags"},
+ { 0x5006, "PrintFlagsVersion"},
+ { 0x5007, "PrintFlagsCrop"},
+ { 0x5008, "PrintFlagsBleedWidth"},
+ { 0x5009, "PrintFlagsBleedWidthScale"},
+ { 0x500A, "HalftoneLPI"},
+ { 0x500B, "HalftoneLPIUnit"},
+ { 0x500C, "HalftoneDegree"},
+ { 0x500D, "HalftoneShape"},
+ { 0x500E, "HalftoneMisc"},
+ { 0x500F, "HalftoneScreen"},
+ { 0x5010, "JPEGQuality"},
+ { 0x5011, "GridSize"},
+ { 0x5012, "ThumbnailFormat"},
+ { 0x5013, "ThumbnailWidth"},
+ { 0x5014, "ThumbnailHeight"},
+ { 0x5015, "ThumbnailColorDepth"},
+ { 0x5016, "ThumbnailPlanes"},
+ { 0x5017, "ThumbnailRawBytes"},
+ { 0x5018, "ThumbnailSize"},
+ { 0x5019, "ThumbnailCompressedSize"},
+ { 0x501A, "ColorTransferFunction"},
+ { 0x501B, "ThumbnailData"},
+ { 0x5020, "ThumbnailImageWidth"},
+ { 0x5021, "ThumbnailImageHeight"},
+ { 0x5022, "ThumbnailBitsPerSample"},
+ { 0x5023, "ThumbnailCompression"},
+ { 0x5024, "ThumbnailPhotometricInterp"},
+ { 0x5025, "ThumbnailImageDescription"},
+ { 0x5026, "ThumbnailEquipMake"},
+ { 0x5027, "ThumbnailEquipModel"},
+ { 0x5028, "ThumbnailStripOffsets"},
+ { 0x5029, "ThumbnailOrientation"},
+ { 0x502A, "ThumbnailSamplesPerPixel"},
+ { 0x502B, "ThumbnailRowsPerStrip"},
+ { 0x502C, "ThumbnailStripBytesCount"},
+ { 0x502D, "ThumbnailResolutionX"},
+ { 0x502E, "ThumbnailResolutionY"},
+ { 0x502F, "ThumbnailPlanarConfig"},
+ { 0x5030, "ThumbnailResolutionUnit"},
+ { 0x5031, "ThumbnailTransferFunction"},
+ { 0x5032, "ThumbnailSoftwareUsed"},
+ { 0x5033, "ThumbnailDateTime"},
+ { 0x5034, "ThumbnailArtist"},
+ { 0x5035, "ThumbnailWhitePoint"},
+ { 0x5036, "ThumbnailPrimaryChromaticities"},
+ { 0x5037, "ThumbnailYCbCrCoefficients"},
+ { 0x5038, "ThumbnailYCbCrSubsampling"},
+ { 0x5039, "ThumbnailYCbCrPositioning"},
+ { 0x503A, "ThumbnailRefBlackWhite"},
+ { 0x503B, "ThumbnailCopyRight"},
+ { 0x5090, "LuminanceTable"},
+ { 0x5091, "ChrominanceTable"},
+ { 0x5100, "FrameDelay"},
+ { 0x5101, "LoopCount"},
+ { 0x5110, "PixelUnit"},
+ { 0x5111, "PixelPerUnitX"},
+ { 0x5112, "PixelPerUnitY"},
+ { 0x5113, "PaletteHistogram"},
{ 0x1000, "RelatedImageFileFormat"},
{ 0x800D, "ImageID"},
{ 0x80E3, "Matteing"}, /* obsoleted by ExtraSamples */
@@ -939,7 +939,7 @@ static tag_info_array tag_table_VND_NIKON = {
{ 0x000b, "Converter"},
TAG_TABLE_END
};
-
+
static tag_info_array tag_table_VND_NIKON_990 = {
{ 0x0001, "Version"},
{ 0x0002, "ISOSetting"},
@@ -958,7 +958,7 @@ static tag_info_array tag_table_VND_NIKON_990 = {
{ 0x0010, "DataDump"},
TAG_TABLE_END
};
-
+
static tag_info_array tag_table_VND_OLYMPUS = {
{ 0x0200, "SpecialMode"},
{ 0x0201, "JPEGQuality"},
@@ -1224,7 +1224,7 @@ char * exif_dump_data(int *dump_free, int format, int components, int length, in
if (components > 0) {
dump = erealloc(dump, len + 2 + 1);
snprintf(dump + len, 2 + 1, ", ");
- len += 2;
+ len += 2;
components--;
} else{
break;
@@ -1574,7 +1574,7 @@ typedef struct {
static void exif_error_docref(const char *docref EXIFERR_DC, const image_info_type *ImageInfo, int type, const char *format, ...)
{
va_list args;
-
+
va_start(args, format);
#ifdef EXIF_DEBUG
{
@@ -2627,7 +2627,7 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
*pszEncoding = estrdup((const char*)szValuePtr);
szValuePtr = szValuePtr+8;
ByteCount -= 8;
- /* First try to detect BOM: ZERO WIDTH NOBREAK SPACE (FEFF 16)
+ /* First try to detect BOM: ZERO WIDTH NOBREAK SPACE (FEFF 16)
* since we have no encoding support for the BOM yet we skip that.
*/
if (!memcmp(szValuePtr, "\xFE\xFF", 2)) {
@@ -2645,8 +2645,8 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
}
/* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX */
if (zend_multibyte_encoding_converter(
- (unsigned char**)pszInfoPtr,
- &len,
+ (unsigned char**)pszInfoPtr,
+ &len,
(unsigned char*)szValuePtr,
ByteCount,
zend_multibyte_fetch_encoding(ImageInfo->encode_unicode TSRMLS_CC),
@@ -2666,8 +2666,8 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
ByteCount -= 8;
/* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX */
if (zend_multibyte_encoding_converter(
- (unsigned char**)pszInfoPtr,
- &len,
+ (unsigned char**)pszInfoPtr,
+ &len,
(unsigned char*)szValuePtr,
ByteCount,
zend_multibyte_fetch_encoding(ImageInfo->encode_jis TSRMLS_CC),
@@ -2701,12 +2701,12 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
* Process unicode field in IFD. */
static int exif_process_unicode(image_info_type *ImageInfo, xp_field_type *xp_field, int tag, char *szValuePtr, int ByteCount TSRMLS_DC)
{
- xp_field->tag = tag;
+ xp_field->tag = tag;
xp_field->value = NULL;
/* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX */
if (zend_multibyte_encoding_converter(
- (unsigned char**)&xp_field->value,
- &xp_field->size,
+ (unsigned char**)&xp_field->value,
+ &xp_field->size,
(unsigned char*)szValuePtr,
ByteCount,
zend_multibyte_fetch_encoding(ImageInfo->encode_unicode TSRMLS_CC),
@@ -2731,7 +2731,7 @@ static int exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * valu
if (i==sizeof(maker_note_array)/sizeof(maker_note_type))
return FALSE;
maker_note = maker_note_array+i;
-
+
/*exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "check (%s,%s)", maker_note->make?maker_note->make:"", maker_note->model?maker_note->model:"");*/
if (maker_note->make && (!ImageInfo->make || strcmp(maker_note->make, ImageInfo->make)))
continue;
@@ -2852,9 +2852,9 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
offset_val = php_ifd_get32u(dir_entry+8, ImageInfo->motorola_intel);
/* If its bigger than 4 bytes, the dir entry contains an offset. */
value_ptr = offset_base+offset_val;
- /*
+ /*
dir_entry is ImageInfo->file.list[sn].data+2+i*12
- offset_base is ImageInfo->file.list[sn].data-dir_offset
+ offset_base is ImageInfo->file.list[sn].data-dir_offset
dir_entry - offset_base is dir_offset+2+i*12
*/
if (byte_count > IFDlength || offset_val > IFDlength-byte_count || value_ptr < dir_entry || offset_val < (size_t)(dir_entry-offset_base)) {
@@ -2925,18 +2925,18 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
case TAG_COMP_IMAGE_WIDTH:
ImageInfo->Thumbnail.width = exif_convert_any_to_int(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC);
break;
-
+
case TAG_IMAGEHEIGHT:
case TAG_COMP_IMAGE_HEIGHT:
ImageInfo->Thumbnail.height = exif_convert_any_to_int(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC);
break;
-
+
case TAG_STRIP_OFFSETS:
case TAG_JPEG_INTERCHANGE_FORMAT:
/* accept both formats */
ImageInfo->Thumbnail.offset = exif_convert_any_to_int(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC);
break;
-
+
case TAG_STRIP_BYTE_COUNTS:
if (ImageInfo->FileType == IMAGE_FILETYPE_TIFF_II || ImageInfo->FileType == IMAGE_FILETYPE_TIFF_MM) {
ImageInfo->Thumbnail.filetype = ImageInfo->FileType;
@@ -2946,7 +2946,7 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
}
ImageInfo->Thumbnail.size = exif_convert_any_to_int(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC);
break;
-
+
case TAG_JPEG_INTERCHANGE_FORMAT_LEN:
if (ImageInfo->Thumbnail.filetype == IMAGE_FILETYPE_UNKNOWN) {
ImageInfo->Thumbnail.filetype = IMAGE_FILETYPE_JPEG;
@@ -2964,16 +2964,16 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
if (length<byte_count-1) {
/* When there are any characters after the first NUL */
ImageInfo->CopyrightPhotographer = estrdup(value_ptr);
- ImageInfo->CopyrightEditor = estrdup(value_ptr+length+1);
+ ImageInfo->CopyrightEditor = estrndup(value_ptr+length+1, byte_count-length-1);
spprintf(&ImageInfo->Copyright, 0, "%s, %s", value_ptr, value_ptr+length+1);
/* format = TAG_FMT_UNDEFINED; this musn't be ASCII */
/* but we are not supposed to change this */
/* keep in mind that image_info does not store editor value */
} else {
- ImageInfo->Copyright = estrdup(value_ptr);
+ ImageInfo->Copyright = estrndup(value_ptr, byte_count);
}
}
- break;
+ break;
case TAG_USERCOMMENT:
ImageInfo->UserCommentLength = exif_process_user_comment(ImageInfo, &(ImageInfo->UserComment), &(ImageInfo->UserCommentEncoding), value_ptr, byte_count TSRMLS_CC);
@@ -3061,10 +3061,10 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
break;
case TAG_MAKE:
- ImageInfo->make = estrdup(value_ptr);
+ ImageInfo->make = estrndup(value_ptr, byte_count);
break;
case TAG_MODEL:
- ImageInfo->model = estrdup(value_ptr);
+ ImageInfo->model = estrndup(value_ptr, byte_count);
break;
case TAG_MAKER_NOTE:
@@ -3414,7 +3414,7 @@ static int exif_scan_JPEG_header(image_info_type *ImageInfo TSRMLS_DC)
if ((itemlen - 2) < 6) {
return FALSE;
}
-
+
exif_process_SOFn(Data, marker, &sof_info);
ImageInfo->Width = sof_info.width;
ImageInfo->Height = sof_info.height;
@@ -3459,21 +3459,21 @@ static int exif_scan_thumbnail(image_info_type *ImageInfo TSRMLS_DC)
}
for (;;) {
pos += length;
- if (pos>=ImageInfo->Thumbnail.size)
+ if (pos>=ImageInfo->Thumbnail.size)
return FALSE;
c = data[pos++];
- if (pos>=ImageInfo->Thumbnail.size)
+ if (pos>=ImageInfo->Thumbnail.size)
return FALSE;
if (c != 0xFF) {
return FALSE;
}
n = 8;
while ((c = data[pos++]) == 0xFF && n--) {
- if (pos+3>=ImageInfo->Thumbnail.size)
+ if (pos+3>=ImageInfo->Thumbnail.size)
return FALSE;
/* +3 = pos++ of next check when reaching marker + 2 bytes for length */
}
- if (c == 0xFF)
+ if (c == 0xFF)
return FALSE;
marker = c;
length = php_jpg_get16(data+pos);
@@ -3787,7 +3787,7 @@ static int exif_scan_FILE_header(image_info_type *ImageInfo TSRMLS_DC)
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "File has TIFF/II format");
#endif
ImageInfo->sections_found |= FOUND_IFD0;
- if (exif_process_IFD_in_TIFF(ImageInfo,
+ if (exif_process_IFD_in_TIFF(ImageInfo,
php_ifd_get32u(file_header + 4, ImageInfo->motorola_intel),
SECTION_IFD0 TSRMLS_CC)) {
ret = TRUE;
@@ -3967,7 +3967,7 @@ PHP_FUNCTION(exif_read_data)
sections_str = exif_get_sectionlist(ImageInfo.sections_found TSRMLS_CC);
#ifdef EXIF_DEBUG
- if (sections_str)
+ if (sections_str)
exif_error_docref(NULL EXIFERR_CC, &ImageInfo, E_NOTICE, "Sections found: %s", sections_str[0] ? sections_str : "None");
#endif
diff --git a/ext/hash/hash_haval.c b/ext/hash/hash_haval.c
index 32437cecdf..21027438cc 100644
--- a/ext/hash/hash_haval.c
+++ b/ext/hash/hash_haval.c
@@ -336,7 +336,7 @@ PHP_HASH_API void PHP_HAVAL128Final(unsigned char *digest, PHP_HAVAL_CTX * conte
/* Pad out to 118 mod 128.
*/
- index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+ index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
padLen = (index < 118) ? (118 - index) : (246 - index);
PHP_HAVALUpdate(context, PADDING, padLen);
@@ -390,7 +390,7 @@ PHP_HASH_API void PHP_HAVAL160Final(unsigned char *digest, PHP_HAVAL_CTX * conte
/* Pad out to 118 mod 128.
*/
- index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+ index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
padLen = (index < 118) ? (118 - index) : (246 - index);
PHP_HAVALUpdate(context, PADDING, padLen);
@@ -444,7 +444,7 @@ PHP_HASH_API void PHP_HAVAL192Final(unsigned char *digest, PHP_HAVAL_CTX * conte
/* Pad out to 118 mod 128.
*/
- index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+ index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
padLen = (index < 118) ? (118 - index) : (246 - index);
PHP_HAVALUpdate(context, PADDING, padLen);
@@ -484,7 +484,7 @@ PHP_HASH_API void PHP_HAVAL224Final(unsigned char *digest, PHP_HAVAL_CTX * conte
/* Pad out to 118 mod 128.
*/
- index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+ index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
padLen = (index < 118) ? (118 - index) : (246 - index);
PHP_HAVALUpdate(context, PADDING, padLen);
@@ -525,7 +525,7 @@ PHP_HASH_API void PHP_HAVAL256Final(unsigned char *digest, PHP_HAVAL_CTX * conte
/* Pad out to 118 mod 128.
*/
- index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+ index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
padLen = (index < 118) ? (118 - index) : (246 - index);
PHP_HAVALUpdate(context, PADDING, padLen);
diff --git a/ext/hash/tests/bug70312.phpt b/ext/hash/tests/bug70312.phpt
new file mode 100644
index 0000000000..5ded1ac5a5
--- /dev/null
+++ b/ext/hash/tests/bug70312.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #70312 HAVAL gives wrong hashes in specific cases
+--SKIPIF--
+<?php if(!extension_loaded("hash")) print "skip"; ?>
+--FILE--
+<?php
+var_dump(hash('haval128,5', '1234567890123456789012345678901234567890123456789012345678901234'));
+var_dump(hash('haval160,5', '1234567890123456789012345678901234567890123456789012345678901234'));
+var_dump(hash('haval192,5', '1234567890123456789012345678901234567890123456789012345678901234'));
+var_dump(hash('haval224,5', '1234567890123456789012345678901234567890123456789012345678901234'));
+var_dump(hash('haval256,5', '1234567890123456789012345678901234567890123456789012345678901234'));
+?>
+--EXPECTF--
+string(32) "f3f0d23819b87228b4b70ee350afaa9d"
+string(40) "aded6485e137f11d7292212ba3fa961714df0564"
+string(48) "e53da2b16269fe732e9a898a96707a9f28404d7333b02286"
+string(56) "c574fb307f0817b514b9bb2e7c4bfaffb7ad667aca3c8b523fefcf10"
+string(64) "fb73c19300b14d5cb393d929bf005e6c2d459a4c9c009e9813af1d2d3637ee8f" \ No newline at end of file
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
index d7a4309b24..071b1a7dcf 100644
--- a/ext/pcre/php_pcre.c
+++ b/ext/pcre/php_pcre.c
@@ -136,7 +136,7 @@ static PHP_MINFO_FUNCTION(pcre)
static PHP_MINIT_FUNCTION(pcre)
{
REGISTER_INI_ENTRIES();
-
+
REGISTER_LONG_CONSTANT("PREG_PATTERN_ORDER", PREG_PATTERN_ORDER, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PREG_SET_ORDER", PREG_SET_ORDER, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PREG_OFFSET_CAPTURE", PREG_OFFSET_CAPTURE, CONST_CS | CONST_PERSISTENT);
@@ -276,18 +276,18 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
#endif
}
}
-
+
p = regex;
-
+
/* Parse through the leading whitespace, and display a warning if we
get to the end without encountering a delimiter. */
while (isspace((int)*(unsigned char *)p)) p++;
if (*p == 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
p < regex + regex_len ? "Null byte in regex" : "Empty regular expression");
return NULL;
}
-
+
/* Get the delimiter and display a warning if it is alphanumeric
or a backslash. */
delimiter = *p++;
@@ -340,7 +340,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
}
return NULL;
}
-
+
/* Make a copy of the actual pattern. */
pattern = estrndup(p, pp-p);
@@ -348,7 +348,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
pp++;
/* Parse through the options, setting appropriate flags. Display
- a warning if we encounter an unknown modifier. */
+ a warning if we encounter an unknown modifier. */
while (pp < regex + regex_len) {
switch (*pp++) {
/* Perl compatible options */
@@ -356,7 +356,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
case 'm': coptions |= PCRE_MULTILINE; break;
case 's': coptions |= PCRE_DOTALL; break;
case 'x': coptions |= PCRE_EXTENDED; break;
-
+
/* PCRE specific options */
case 'A': coptions |= PCRE_ANCHORED; break;
case 'D': coptions |= PCRE_DOLLAR_ENDONLY;break;
@@ -369,12 +369,12 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
the PCRE_UCP option. */
#ifdef PCRE_UCP
coptions |= PCRE_UCP;
-#endif
+#endif
break;
/* Custom preg options */
case 'e': poptions |= PREG_REPLACE_EVAL; break;
-
+
case ' ':
case '\n':
break;
@@ -453,7 +453,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
* at end of request. However PCRE_G(pcre_cache) must be consistent
* on the next request as well. So we disable usage of interned strings
* as hash keys especually for this table.
- * See bug #63180
+ * See bug #63180
*/
if (IS_INTERNED(regex)) {
regex = tmp = estrndup(regex, regex_len);
@@ -482,7 +482,7 @@ PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *preg_
if (preg_options) {
*preg_options = pce ? pce->preg_options : 0;
}
-
+
return pce ? pce->re : NULL;
}
/* }}} */
@@ -492,7 +492,7 @@ PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *preg_
PHPAPI pcre* pcre_get_compiled_regex_ex(char *regex, pcre_extra **extra, int *preg_options, int *compile_options TSRMLS_DC)
{
pcre_cache_entry * pce = pcre_get_compiled_regex_cache(regex, strlen(regex) TSRMLS_CC);
-
+
if (extra) {
*extra = pce ? pce->extra : NULL;
}
@@ -502,7 +502,7 @@ PHPAPI pcre* pcre_get_compiled_regex_ex(char *regex, pcre_extra **extra, int *pr
if (compile_options) {
*compile_options = pce ? pce->compile_options : 0;
}
-
+
return pce ? pce->re : NULL;
}
/* }}} */
@@ -519,7 +519,7 @@ static inline void add_offset_pair(zval *result, char *str, int len, int offset,
/* Add (match, offset) to the return value */
add_next_index_stringl(match_pair, str, len, 1);
add_next_index_long(match_pair, offset);
-
+
if (name) {
zval_add_ref(&match_pair);
zend_hash_update(Z_ARRVAL_P(result), name, strlen(name)+1, &match_pair, sizeof(zval *), NULL);
@@ -544,13 +544,13 @@ static void php_do_pcre_match(INTERNAL_FUNCTION_PARAMETERS, int global) /* {{{ *
&subject, &subject_len, &subpats, &flags, &start_offset) == FAILURE) {
RETURN_FALSE;
}
-
+
/* Compile regex or get it from cache. */
if ((pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
- php_pcre_match_impl(pce, subject, subject_len, return_value, subpats,
+ php_pcre_match_impl(pce, subject, subject_len, return_value, subpats,
global, ZEND_NUM_ARGS() >= 4, flags, start_offset TSRMLS_CC);
}
/* }}} */
@@ -653,7 +653,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
matched = 0;
PCRE_G(error_code) = PHP_PCRE_NO_ERROR;
-
+
do {
/* Execute the regular expression. */
count = pcre_exec(pce->re, extra, subject, subject_len, start_offset,
@@ -675,7 +675,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
/* If subpatterns array has been passed, fill it in with values. */
if (subpats != NULL) {
/* Try to get the list of substrings and display a warning if failed. */
- if (pcre_get_substring_list(subject, offsets, count, &stringlist) < 0) {
+ if ((offsets[1] - offsets[0] < 0) || pcre_get_substring_list(subject, offsets, count, &stringlist) < 0) {
efree(subpat_names);
efree(offsets);
if (match_sets) efree(match_sets);
@@ -710,7 +710,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
ALLOC_ZVAL(result_set);
array_init(result_set);
INIT_PZVAL(result_set);
-
+
/* Add all the subpatterns to it */
for (i = 0; i < count; i++) {
if (offset_capture) {
@@ -762,13 +762,13 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
pcre_handle_exec_error(count TSRMLS_CC);
break;
}
-
+
/* If we have matched an empty string, mimic what Perl's /g options does.
This turns out to be rather cunning. First we set PCRE_NOTEMPTY and try
the match again at the same point. If this fails (picked up above) we
advance to the next character. */
g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY | PCRE_ANCHORED : 0;
-
+
/* Advance to the position right after the last full match */
start_offset = offsets[1];
} while (global);
@@ -785,7 +785,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
}
efree(match_sets);
}
-
+
efree(offsets);
efree(subpat_names);
@@ -835,7 +835,7 @@ static int preg_get_backref(char **str, int *backref)
walk++;
} else
return 0;
-
+
if (*walk && *walk >= '0' && *walk <= '9') {
*backref = *backref * 10 + *walk - '0';
walk++;
@@ -847,9 +847,9 @@ static int preg_get_backref(char **str, int *backref)
else
walk++;
}
-
+
*str = walk;
- return 1;
+ return 1;
}
/* }}} */
@@ -859,7 +859,7 @@ static int preg_do_repl_func(zval *function, char *subject, int *offsets, char *
{
zval *retval_ptr; /* Function return value */
zval **args[1]; /* Argument to pass to function */
- zval *subpats; /* Captured subpatterns */
+ zval *subpats; /* Captured subpatterns */
int result_len; /* Return value length */
int i;
@@ -910,11 +910,11 @@ static int preg_do_eval(char *eval_str, int eval_str_len, char *subject,
int backref; /* Current backref */
char *compiled_string_description;
smart_str code = {0};
-
+
eval_str_end = eval_str + eval_str_len;
walk = segment = eval_str;
walk_last = 0;
-
+
while (walk < eval_str_end) {
/* If found a backreference.. */
if ('\\' == *walk || '$' == *walk) {
@@ -967,15 +967,15 @@ static int preg_do_eval(char *eval_str, int eval_str_len, char *subject,
}
efree(compiled_string_description);
convert_to_string(&retval);
-
+
/* Save the return value and its length */
*result = estrndup(Z_STRVAL(retval), Z_STRLEN(retval));
result_len = Z_STRLEN(retval);
-
+
/* Clean up */
zval_dtor(&retval);
smart_str_free(&code);
-
+
return result_len;
}
/* }}} */
@@ -994,13 +994,13 @@ PHPAPI char *php_pcre_replace(char *regex, int regex_len,
return NULL;
}
- return php_pcre_replace_impl(pce, subject, subject_len, replace_val,
+ return php_pcre_replace_impl(pce, subject, subject_len, replace_val,
is_callable_replace, result_len, limit, replace_count TSRMLS_CC);
}
/* }}} */
/* {{{ php_pcre_replace_impl() */
-PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *replace_val,
+PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *replace_val,
int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC)
{
pcre_extra *extra = pce->extra;/* Holds results of studying */
@@ -1072,7 +1072,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
}
offsets = (int *)safe_emalloc(size_offsets, sizeof(int), 0);
-
+
alloc_len = 2 * subject_len + 1;
result = safe_emalloc(alloc_len, sizeof(char), 0);
@@ -1081,7 +1081,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
*result_len = 0;
start_offset = 0;
PCRE_G(error_code) = PHP_PCRE_NO_ERROR;
-
+
while (1) {
/* Execute the regular expression. */
count = pcre_exec(pce->re, extra, subject, subject_len, start_offset,
@@ -1098,7 +1098,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
piece = subject + start_offset;
- if (count > 0 && (limit == -1 || limit > 0)) {
+ if (count > 0 && (offsets[1] - offsets[0] >= 0) && (limit == -1 || limit > 0)) {
if (replace_count) {
++*replace_count;
}
@@ -1106,7 +1106,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
match = subject + offsets[0];
new_len = *result_len + offsets[0] - start_offset; /* part before the match */
-
+
/* If evaluating, do it and add the return string's length */
if (eval) {
eval_result_len = preg_do_eval(replace, replace_len, subject,
@@ -1151,7 +1151,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
/* copy replacement and backrefs */
walkbuf = result + *result_len;
-
+
/* If evaluating or using custom function, copy result to the buffer
* and clean up. */
if (eval || is_callable_replace) {
@@ -1219,13 +1219,13 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
result = NULL;
break;
}
-
+
/* If we have matched an empty string, mimic what Perl's /g options does.
This turns out to be rather cunning. First we set PCRE_NOTEMPTY and try
the match again at the same point. If this fails (picked up above) we
advance to the next character. */
g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY | PCRE_ANCHORED : 0;
-
+
/* Advance to the next piece. */
start_offset = offsets[1];
}
@@ -1249,18 +1249,18 @@ static char *php_replace_in_subject(zval *regex, zval *replace, zval **subject,
*result;
int subject_len;
- /* Make sure we're dealing with strings. */
+ /* Make sure we're dealing with strings. */
convert_to_string_ex(subject);
/* FIXME: This might need to be changed to STR_EMPTY_ALLOC(). Check if this zval could be dtor()'ed somehow */
ZVAL_STRINGL(&empty_replace, "", 0, 0);
-
+
/* If regex is an array */
if (Z_TYPE_P(regex) == IS_ARRAY) {
/* Duplicate subject string for repeated replacement */
subject_value = estrndup(Z_STRVAL_PP(subject), Z_STRLEN_PP(subject));
subject_len = Z_STRLEN_PP(subject);
*result_len = subject_len;
-
+
zend_hash_internal_pointer_reset(Z_ARRVAL_P(regex));
replace_value = replace;
@@ -1269,9 +1269,9 @@ static char *php_replace_in_subject(zval *regex, zval *replace, zval **subject,
/* For each entry in the regex array, get the entry */
while (zend_hash_get_current_data(Z_ARRVAL_P(regex), (void **)&regex_entry) == SUCCESS) {
- /* Make sure we're dealing with strings. */
+ /* Make sure we're dealing with strings. */
convert_to_string_ex(regex_entry);
-
+
/* If replace is an array and not a callable construct */
if (Z_TYPE_P(replace) == IS_ARRAY && !is_callable_replace) {
/* Get current entry */
@@ -1286,7 +1286,7 @@ static char *php_replace_in_subject(zval *regex, zval *replace, zval **subject,
replace_value = &empty_replace;
}
}
-
+
/* Do the actual replacement and put the result back into subject_value
for further replacements. */
if ((result = php_pcre_replace(Z_STRVAL_PP(regex_entry),
@@ -1342,12 +1342,12 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
ulong num_key;
char *callback_name;
int replace_count=0, old_replace_count;
-
+
/* Get function parameters and do error-checking. */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ|lZ", &regex, &replace, &subject, &limit, &zcount) == FAILURE) {
return;
}
-
+
if (!is_callable_replace && Z_TYPE_PP(replace) == IS_ARRAY && Z_TYPE_PP(regex) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter mismatch, pattern is a string while replacement is an array");
RETURN_FALSE;
@@ -1373,10 +1373,10 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
if (ZEND_NUM_ARGS() > 3) {
limit_val = limit;
}
-
+
if (Z_TYPE_PP(regex) != IS_ARRAY)
convert_to_string_ex(regex);
-
+
/* if subject is an array */
if (Z_TYPE_PP(subject) == IS_ARRAY) {
array_init(return_value);
@@ -1404,7 +1404,7 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
efree(result);
}
}
-
+
zend_hash_move_forward(Z_ARRVAL_PP(subject));
}
} else { /* if subject is not an array */
@@ -1421,7 +1421,7 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
zval_dtor(*zcount);
ZVAL_LONG(*zcount, replace_count);
}
-
+
}
/* }}} */
@@ -1449,7 +1449,7 @@ static PHP_FUNCTION(preg_filter)
}
/* }}} */
-/* {{{ proto array preg_split(string pattern, string subject [, int limit [, int flags]])
+/* {{{ proto array preg_split(string pattern, string subject [, int limit [, int flags]])
Split string into an array using a perl-style regular expression as a delimiter */
static PHP_FUNCTION(preg_split)
{
@@ -1461,12 +1461,12 @@ static PHP_FUNCTION(preg_split)
long flags = 0; /* Match control flags */
pcre_cache_entry *pce; /* Compiled regular expression */
- /* Get function parameters and do error checking */
+ /* Get function parameters and do error checking */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll", &regex, &regex_len,
&subject, &subject_len, &limit_val, &flags) == FAILURE) {
RETURN_FALSE;
}
-
+
/* Compile regex or get it from cache. */
if ((pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC)) == NULL) {
RETURN_FALSE;
@@ -1501,7 +1501,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
no_empty = flags & PREG_SPLIT_NO_EMPTY;
delim_capture = flags & PREG_SPLIT_DELIM_CAPTURE;
offset_capture = flags & PREG_SPLIT_OFFSET_CAPTURE;
-
+
if (limit_val == 0) {
limit_val = -1;
}
@@ -1512,7 +1512,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
}
extra->match_limit = PCRE_G(backtrack_limit);
extra->match_limit_recursion = PCRE_G(recursion_limit);
-
+
/* Initialize return value */
array_init(return_value);
@@ -1524,13 +1524,13 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
}
size_offsets = (size_offsets + 1) * 3;
offsets = (int *)safe_emalloc(size_offsets, sizeof(int), 0);
-
+
/* Start at the beginning of the string */
start_offset = 0;
next_offset = 0;
last_match = subject;
PCRE_G(error_code) = PHP_PCRE_NO_ERROR;
-
+
/* Get next piece if no limit or limit not yet reached and something matched*/
while ((limit_val == -1 || limit_val > 1)) {
count = pcre_exec(pce->re, extra, subject,
@@ -1545,9 +1545,9 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
php_error_docref(NULL TSRMLS_CC,E_NOTICE, "Matched, but too many substrings");
count = size_offsets/3;
}
-
+
/* If something matched */
- if (count > 0) {
+ if (count > 0 && (offsets[1] - offsets[0] >= 0)) {
if (!no_empty || &subject[offsets[0]] != last_match) {
if (offset_capture) {
@@ -1563,7 +1563,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
if (limit_val != -1)
limit_val--;
}
-
+
last_match = &subject[offsets[1]];
next_offset = offsets[1];
@@ -1620,7 +1620,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
the match again at the same point. If this fails (picked up above) we
advance to the next character. */
g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY | PCRE_ANCHORED : 0;
-
+
/* Advance to the position right after the last full match */
start_offset = offsets[1];
}
@@ -1639,7 +1639,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
}
}
-
+
/* Clean up */
efree(offsets);
}
@@ -1660,13 +1660,13 @@ static PHP_FUNCTION(preg_quote)
delim_char=0, /* Delimiter character to be quoted */
c; /* Current character */
zend_bool quote_delim = 0; /* Whether to quote additional delim char */
-
+
/* Get the arguments and check for errors */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &in_str, &in_str_len,
&delim, &delim_len) == FAILURE) {
return;
}
-
+
in_str_end = in_str + in_str_len;
/* Nothing to do if we got an empty string */
@@ -1678,11 +1678,11 @@ static PHP_FUNCTION(preg_quote)
delim_char = delim[0];
quote_delim = 1;
}
-
+
/* Allocate enough memory so that even if each character
is quoted, we won't run out of room */
out_str = safe_emalloc(4, in_str_len, 1);
-
+
/* Go through the string and quote necessary characters */
for(p = in_str, q = out_str; p != in_str_end; p++) {
c = *p;
@@ -1726,7 +1726,7 @@ static PHP_FUNCTION(preg_quote)
}
}
*q = '\0';
-
+
/* Reallocate string and return it */
RETVAL_STRINGL(erealloc(out_str, q - out_str + 1), q - out_str, 0);
}
@@ -1747,12 +1747,12 @@ static PHP_FUNCTION(preg_grep)
&input, &flags) == FAILURE) {
return;
}
-
+
/* Compile regex or get it from cache. */
if ((pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
-
+
php_pcre_grep_impl(pce, input, return_value, flags TSRMLS_CC);
}
/* }}} */
@@ -1770,9 +1770,9 @@ PHPAPI void php_pcre_grep_impl(pcre_cache_entry *pce, zval *input, zval *return
zend_bool invert; /* Whether to return non-matching
entries */
int rc;
-
+
invert = flags & PREG_GREP_INVERT ? 1 : 0;
-
+
if (extra == NULL) {
extra_data.flags = PCRE_EXTRA_MATCH_LIMIT | PCRE_EXTRA_MATCH_LIMIT_RECURSION;
extra = &extra_data;
@@ -1788,7 +1788,7 @@ PHPAPI void php_pcre_grep_impl(pcre_cache_entry *pce, zval *input, zval *return
}
size_offsets = (size_offsets + 1) * 3;
offsets = (int *)safe_emalloc(size_offsets, sizeof(int), 0);
-
+
/* Initialize return array */
array_init(return_value);
@@ -1901,7 +1901,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_preg_split, 0, 0, 2)
ZEND_ARG_INFO(0, pattern)
ZEND_ARG_INFO(0, subject)
ZEND_ARG_INFO(0, limit)
- ZEND_ARG_INFO(0, flags)
+ ZEND_ARG_INFO(0, flags)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_preg_quote, 0, 0, 1)
diff --git a/ext/pcre/tests/bug70345.phpt b/ext/pcre/tests/bug70345.phpt
new file mode 100644
index 0000000000..0947ba3daa
--- /dev/null
+++ b/ext/pcre/tests/bug70345.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Bug #70345 (Multiple vulnerabilities related to PCRE functions)
+--FILE--
+<?php
+$regex = '/(?=xyz\K)/';
+$subject = "aaaaxyzaaaa";
+
+$v = preg_split($regex, $subject);
+print_r($v);
+
+$regex = '/(a(?=xyz\K))/';
+$subject = "aaaaxyzaaaa";
+preg_match($regex, $subject, $matches);
+
+var_dump($matches);
+--EXPECTF--
+Array
+(
+ [0] => aaaaxyzaaaa
+)
+
+Warning: preg_match(): Get subpatterns list failed in %s on line %d
+array(0) {
+}
diff --git a/ext/session/session.c b/ext/session/session.c
index 306aba3a7d..0e53c62133 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -210,16 +210,18 @@ static char *php_session_encode(int *newlen TSRMLS_DC) /* {{{ */
}
/* }}} */
-static void php_session_decode(const char *val, int vallen TSRMLS_DC) /* {{{ */
+static int php_session_decode(const char *val, int vallen TSRMLS_DC) /* {{{ */
{
if (!PS(serializer)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown session.serialize_handler. Failed to decode session object");
- return;
+ return FAILURE;
}
if (PS(serializer)->decode(val, vallen TSRMLS_CC) == FAILURE) {
php_session_destroy(TSRMLS_C);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to decode session object. Session has been destroyed");
+ return FAILURE;
}
+ return SUCCESS;
}
/* }}} */
@@ -413,7 +415,7 @@ PHPAPI char *php_session_create_id(PS_CREATE_SID_ARGS) /* {{{ */
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The ini setting hash_bits_per_character is out of range (should be 4, 5, or 6) - using 4 for now");
}
-
+
outid = emalloc((size_t)((digest_len + 2) * ((8.0f / PS(hash_bits_per_character)) + 0.5)));
j = (int) (bin_to_readable((char *)digest, digest_len, outid, (char)PS(hash_bits_per_character)) - outid);
efree(digest);
@@ -855,8 +857,11 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
ALLOC_INIT_ZVAL(current);
if (php_var_unserialize(&current, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) {
php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC);
+ } else {
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return FAILURE;
}
- zval_ptr_dtor(&current);
+ var_push_dtor_no_addref(&var_hash, &current);
}
PS_ADD_VARL(name, namelen);
efree(name);
@@ -947,8 +952,13 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
ALLOC_INIT_ZVAL(current);
if (php_var_unserialize(&current, (const unsigned char **) &q, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) {
php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC);
+ } else {
+ var_push_dtor_no_addref(&var_hash, &current);
+ efree(name);
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return FAILURE;
}
- zval_ptr_dtor(&current);
+ var_push_dtor_no_addref(&var_hash, &current);
}
PS_ADD_VARL(name, namelen);
skip:
@@ -1744,7 +1754,7 @@ static PHP_FUNCTION(session_set_save_handler)
}
efree(name);
}
-
+
if (PS(mod) && PS(mod) != &ps_mod_user) {
zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
}
@@ -1922,9 +1932,7 @@ static PHP_FUNCTION(session_decode)
return;
}
- php_session_decode(str, str_len TSRMLS_CC);
-
- RETURN_TRUE;
+ RETVAL_BOOL(php_session_decode(str, str_len TSRMLS_CC) == SUCCESS);
}
/* }}} */
@@ -2516,12 +2524,12 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
case MULTIPART_EVENT_FILE_START: {
multipart_event_file_start *data = (multipart_event_file_start *) event_data;
- /* Do nothing when $_POST["PHP_SESSION_UPLOAD_PROGRESS"] is not set
+ /* Do nothing when $_POST["PHP_SESSION_UPLOAD_PROGRESS"] is not set
* or when we have no session id */
if (!Z_TYPE(progress->sid) || !progress->key.c) {
break;
}
-
+
/* First FILE_START event, initializing data */
if (!progress->data) {
@@ -2571,7 +2579,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
add_assoc_zval_ex(progress->current_file, "bytes_processed", sizeof("bytes_processed"), progress->current_file_bytes_processed);
add_next_index_zval(progress->files, progress->current_file);
-
+
Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;
php_session_rfc1867_update(progress, 0 TSRMLS_CC);
@@ -2583,7 +2591,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
if (!Z_TYPE(progress->sid) || !progress->key.c) {
break;
}
-
+
Z_LVAL_P(progress->current_file_bytes_processed) = data->offset + data->length;
Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;
@@ -2596,7 +2604,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
if (!Z_TYPE(progress->sid) || !progress->key.c) {
break;
}
-
+
if (data->temp_filename) {
add_assoc_string_ex(progress->current_file, "tmp_name", sizeof("tmp_name"), data->temp_filename, 1);
}
diff --git a/ext/session/tests/session_decode_error2.phpt b/ext/session/tests/session_decode_error2.phpt
index 4160f87855..515047b675 100644
--- a/ext/session/tests/session_decode_error2.phpt
+++ b/ext/session/tests/session_decode_error2.phpt
@@ -53,563 +53,247 @@ array(0) {
}
-- Iteration 4 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+
+Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
+bool(false)
+array(0) {
}
-- Iteration 5 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 6 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 7 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 8 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 9 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 10 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 11 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 12 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 13 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 14 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 15 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 16 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 17 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 18 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 19 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 20 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 21 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 22 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 23 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 24 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 25 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 26 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 27 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 28 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 29 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 30 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 31 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 32 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 33 --
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 34 --
-bool(true)
-array(1) {
- ["foo"]=>
- array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
+bool(false)
+array(0) {
}
-- Iteration 35 --
-bool(true)
-array(1) {
- ["foo"]=>
- array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
+bool(false)
+array(0) {
}
-- Iteration 36 --
-bool(true)
-array(1) {
- ["foo"]=>
- array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
+bool(false)
+array(0) {
}
-- Iteration 37 --
-bool(true)
-array(1) {
- ["foo"]=>
- array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
+bool(false)
+array(0) {
}
-- Iteration 38 --
-bool(true)
-array(1) {
- ["foo"]=>
- array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
+bool(false)
+array(0) {
}
-- Iteration 39 --
-bool(true)
-array(2) {
- ["foo"]=>
- array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["guff"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 40 --
-bool(true)
-array(2) {
- ["foo"]=>
- array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["guff"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 41 --
-bool(true)
-array(2) {
- ["foo"]=>
- array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["guff"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 42 --
-bool(true)
-array(2) {
- ["foo"]=>
- array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["guff"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 43 --
-bool(true)
-array(2) {
- ["foo"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["guff"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
+bool(false)
+array(0) {
}
-- Iteration 44 --
-bool(true)
-array(2) {
- ["foo"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["guff"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
+bool(false)
+array(0) {
}
-- Iteration 45 --
-bool(true)
-array(2) {
- ["foo"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["guff"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
+bool(false)
+array(0) {
}
-- Iteration 46 --
-bool(true)
-array(2) {
- ["foo"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["guff"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
+bool(false)
+array(0) {
}
-- Iteration 47 --
-bool(true)
-array(2) {
- ["foo"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["guff"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
+bool(false)
+array(0) {
}
-- Iteration 48 --
-bool(true)
-array(3) {
- ["foo"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["guff"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["blah"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 49 --
-bool(true)
-array(3) {
- ["foo"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["guff"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["blah"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 50 --
-bool(true)
-array(3) {
- ["foo"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["guff"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["blah"]=>
- NULL
+bool(false)
+array(0) {
}
-- Iteration 51 --
-bool(true)
-array(3) {
- ["foo"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["guff"]=>
- &array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- }
- ["blah"]=>
- NULL
+bool(false)
+array(0) {
}
-bool(true)
-Done
+Warning: session_destroy(): Trying to destroy uninitialized session in %s/session_decode_error2.php on line %d
+bool(false)
+Done
diff --git a/ext/session/tests/session_decode_variation3.phpt b/ext/session/tests/session_decode_variation3.phpt
index 4a6f768713..096053171d 100644
--- a/ext/session/tests/session_decode_variation3.phpt
+++ b/ext/session/tests/session_decode_variation3.phpt
@@ -49,7 +49,7 @@ array(3) {
}
Warning: session_decode(): Unknown session.serialize_handler. Failed to decode session object in %s on line %d
-bool(true)
+bool(false)
array(3) {
["foo"]=>
int(1234567890)
diff --git a/ext/soap/soap.c b/ext/soap/soap.c
index 1b8f545b85..a0e64a3900 100644
--- a/ext/soap/soap.c
+++ b/ext/soap/soap.c
@@ -989,7 +989,7 @@ static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht TSRMLS_DC)
HashTable *ht2;
HashPosition pos1, pos2;
HashTable *typemap = NULL;
-
+
zend_hash_internal_pointer_reset_ex(ht, &pos1);
while (zend_hash_get_current_data_ex(ht, (void**)&tmp, &pos1) == SUCCESS) {
char *type_name = NULL;
@@ -1033,7 +1033,7 @@ static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht TSRMLS_DC)
}
}
zend_hash_move_forward_ex(ht2, &pos2);
- }
+ }
if (type_name) {
smart_str nscat = {0};
@@ -1063,7 +1063,7 @@ static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht TSRMLS_DC)
new_enc->to_xml = enc->to_xml;
new_enc->to_zval = enc->to_zval;
new_enc->details.map = emalloc(sizeof(soapMapping));
- memset(new_enc->details.map, 0, sizeof(soapMapping));
+ memset(new_enc->details.map, 0, sizeof(soapMapping));
if (to_xml) {
zval_add_ref(&to_xml);
new_enc->details.map->to_xml = to_xml;
@@ -1120,7 +1120,7 @@ PHP_METHOD(SoapServer, SoapServer)
if (Z_TYPE_P(wsdl) != IS_STRING && Z_TYPE_P(wsdl) != IS_NULL) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
}
-
+
service = emalloc(sizeof(soapService));
memset(service, 0, sizeof(soapService));
service->send_errors = 1;
@@ -1155,7 +1155,7 @@ PHP_METHOD(SoapServer, SoapServer)
if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
Z_TYPE_PP(tmp) == IS_STRING) {
xmlCharEncodingHandlerPtr encoding;
-
+
encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
if (encoding == NULL) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_PP(tmp));
@@ -1215,7 +1215,7 @@ PHP_METHOD(SoapServer, SoapServer)
}
}
}
-
+
if (typemap_ht) {
service->typemap = soap_create_typemap(service->sdl, typemap_ht TSRMLS_CC);
}
@@ -1345,7 +1345,7 @@ PHP_METHOD(SoapServer, getFunctions)
if (zend_parse_parameters_none() == FAILURE) {
return;
}
-
+
FETCH_THIS_SERVICE(service);
array_init(return_value);
@@ -1505,7 +1505,7 @@ PHP_METHOD(SoapServer, handle)
FETCH_THIS_SERVICE(service);
SOAP_GLOBAL(soap_version) = service->version;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &arg, &arg_len) == FAILURE) {
return;
}
@@ -1930,7 +1930,7 @@ PHP_METHOD(SoapServer, handle)
if (size == 0) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Dump memory failed");
- }
+ }
if (soap_version == SOAP_1_2) {
sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
@@ -2147,10 +2147,10 @@ static void soap_error_handler(int error_num, const char *error_filename, const
use_exceptions = 1;
}
- if ((error_num == E_USER_ERROR ||
- error_num == E_COMPILE_ERROR ||
+ if ((error_num == E_USER_ERROR ||
+ error_num == E_COMPILE_ERROR ||
error_num == E_CORE_ERROR ||
- error_num == E_ERROR ||
+ error_num == E_ERROR ||
error_num == E_PARSE) &&
use_exceptions) {
zval *fault, *exception;
@@ -2219,10 +2219,10 @@ static void soap_error_handler(int error_num, const char *error_filename, const
va_list argcopy;
#endif
- if (error_num == E_USER_ERROR ||
- error_num == E_COMPILE_ERROR ||
+ if (error_num == E_USER_ERROR ||
+ error_num == E_COMPILE_ERROR ||
error_num == E_CORE_ERROR ||
- error_num == E_ERROR ||
+ error_num == E_ERROR ||
error_num == E_PARSE) {
char* code = SOAP_GLOBAL(error_code);
@@ -2452,13 +2452,13 @@ PHP_METHOD(SoapClient, SoapClient)
if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
Z_TYPE_PP(tmp) == IS_STRING) {
xmlCharEncodingHandlerPtr encoding;
-
+
encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
if (encoding == NULL) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_PP(tmp));
} else {
xmlCharEncCloseFunc(encoding);
- add_property_stringl(this_ptr, "_encoding", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
+ add_property_stringl(this_ptr, "_encoding", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
}
if (zend_hash_find(ht, "classmap", sizeof("classmap"), (void**)&tmp) == SUCCESS &&
@@ -2493,7 +2493,7 @@ PHP_METHOD(SoapClient, SoapClient)
if (context) {
add_property_resource(this_ptr, "_stream_context", context->rsrc_id);
}
-
+
if (zend_hash_find(ht, "cache_wsdl", sizeof("cache_wsdl"), (void**)&tmp) == SUCCESS &&
Z_TYPE_PP(tmp) == IS_LONG) {
cache_wsdl = Z_LVAL_PP(tmp);
@@ -2503,7 +2503,7 @@ PHP_METHOD(SoapClient, SoapClient)
Z_TYPE_PP(tmp) == IS_STRING) {
add_property_stringl(this_ptr, "_user_agent", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
-
+
if (zend_hash_find(ht, "keep_alive", sizeof("keep_alive"), (void**)&tmp) == SUCCESS &&
(Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) && Z_LVAL_PP(tmp) == 0) {
add_property_long(this_ptr, "_keep_alive", 0);
@@ -2606,7 +2606,7 @@ static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *act
xmlFree(buf);
if (ret && zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
return FALSE;
- }
+ }
return ret;
}
@@ -2903,8 +2903,10 @@ PHP_METHOD(SoapClient, __call)
}
zend_hash_internal_pointer_reset(default_headers);
while (zend_hash_get_current_data(default_headers, (void**)&tmp) == SUCCESS) {
- Z_ADDREF_PP(tmp);
- zend_hash_next_index_insert(soap_headers, tmp, sizeof(zval *), NULL);
+ if(Z_TYPE_PP(tmp) == IS_OBJECT) {
+ Z_ADDREF_PP(tmp);
+ zend_hash_next_index_insert(soap_headers, tmp, sizeof(zval *), NULL);
+ }
zend_hash_move_forward(default_headers);
}
} else {
@@ -2912,7 +2914,7 @@ PHP_METHOD(SoapClient, __call)
free_soap_headers = 0;
}
}
-
+
arg_count = zend_hash_num_elements(Z_ARRVAL_P(args));
if (arg_count > 0) {
@@ -2978,7 +2980,7 @@ PHP_METHOD(SoapClient, __getTypes)
HashPosition pos;
FETCH_THIS_SDL(sdl);
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -3007,7 +3009,7 @@ PHP_METHOD(SoapClient, __getTypes)
PHP_METHOD(SoapClient, __getLastRequest)
{
zval **tmp;
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -3030,7 +3032,7 @@ PHP_METHOD(SoapClient, __getLastResponse)
if (zend_parse_parameters_none() == FAILURE) {
return;
}
-
+
if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_response", sizeof("__last_response"), (void **)&tmp) == SUCCESS &&
Z_TYPE_PP(tmp) == IS_STRING) {
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
@@ -3045,11 +3047,11 @@ PHP_METHOD(SoapClient, __getLastResponse)
PHP_METHOD(SoapClient, __getLastRequestHeaders)
{
zval **tmp;
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
-
+
if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_request_headers", sizeof("__last_request_headers"), (void **)&tmp) == SUCCESS &&
Z_TYPE_PP(tmp) == IS_STRING) {
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
@@ -3064,7 +3066,7 @@ PHP_METHOD(SoapClient, __getLastRequestHeaders)
PHP_METHOD(SoapClient, __getLastResponseHeaders)
{
zval **tmp;
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -3209,10 +3211,10 @@ PHP_METHOD(SoapClient, __setSoapHeaders)
/* {{{ proto string SoapClient::__setLocation([string new_location])
- Sets the location option (the endpoint URL that will be touched by the
+ Sets the location option (the endpoint URL that will be touched by the
following SOAP requests).
If new_location is not specified or null then SoapClient will use endpoint
- from WSDL file.
+ from WSDL file.
The function returns old value of location options. */
PHP_METHOD(SoapClient, __setLocation)
{
@@ -3261,10 +3263,10 @@ static void set_soap_fault(zval *obj, char *fault_code_ns, char *fault_code, cha
if (Z_TYPE_P(obj) != IS_OBJECT) {
object_init_ex(obj, soap_fault_class_entry);
}
-
+
add_property_string(obj, "faultstring", fault_string ? fault_string : "", 1);
zend_update_property_string(zend_exception_get_default(TSRMLS_C), obj, "message", sizeof("message")-1, (fault_string ? fault_string : "") TSRMLS_CC);
-
+
if (fault_code != NULL) {
int soap_version = SOAP_GLOBAL(soap_version);
@@ -3689,7 +3691,7 @@ ignore_header:
func = func->children;
}
deserialize_parameters(func, function, num_params, parameters TSRMLS_CC);
-
+
encode_finish();
return function;
@@ -3971,8 +3973,8 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
}
if (fault_ns == NULL &&
- fault &&
- fault->details &&
+ fault &&
+ fault->details &&
zend_hash_num_elements(fault->details) == 1) {
sdlParamPtr sparam;
@@ -3996,7 +3998,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
xmlChar *code = xmlBuildQName(BAD_CAST(str), nsptr->prefix, NULL, 0);
xmlNodeSetContent(node, code);
xmlFree(code);
- } else {
+ } else {
xmlNodeSetContentLen(node, BAD_CAST(str), (int)new_len);
}
efree(str);
@@ -4022,7 +4024,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
xmlChar *code = xmlBuildQName(BAD_CAST(str), nsptr->prefix, NULL, 0);
xmlNodeSetContent(node, code);
xmlFree(code);
- } else {
+ } else {
xmlNodeSetContentLen(node, BAD_CAST(str), (int)new_len);
}
efree(str);
@@ -4194,7 +4196,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
encode_finish();
- if (function && function->responseName == NULL &&
+ if (function && function->responseName == NULL &&
body->children == NULL && head == NULL) {
xmlFreeDoc(doc);
return NULL;
@@ -4328,11 +4330,18 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
if (head) {
zval** header;
- zend_hash_internal_pointer_reset(soap_headers);
- while (zend_hash_get_current_data(soap_headers,(void**)&header) == SUCCESS) {
- HashTable *ht = Z_OBJPROP_PP(header);
+ for(zend_hash_internal_pointer_reset(soap_headers);
+ zend_hash_get_current_data(soap_headers,(void**)&header) == SUCCESS;
+ zend_hash_move_forward(soap_headers)
+ ) {
+ HashTable *ht;
zval **name, **ns, **tmp;
+ if (Z_TYPE_PP(header) != IS_OBJECT) {
+ continue;
+ }
+
+ ht = Z_OBJPROP_PP(header);
if (zend_hash_find(ht, "name", sizeof("name"), (void**)&name) == SUCCESS &&
Z_TYPE_PP(name) == IS_STRING &&
zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&ns) == SUCCESS &&
@@ -4371,7 +4380,6 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
xmlSetNs(h, nsptr);
set_soap_header_attributes(h, ht, version);
}
- zend_hash_move_forward(soap_headers);
}
}
@@ -4482,7 +4490,7 @@ static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int inde
return *tmp;
} else {
HashPosition pos;
-
+
zend_hash_internal_pointer_reset_ex(ht, &pos);
while (zend_hash_get_current_data_ex(ht, (void **)&tmp, &pos) != FAILURE) {
if ((*tmp)->paramName && strcmp(param_name, (*tmp)->paramName) == 0) {
diff --git a/ext/soap/tests/bug70388.phpt b/ext/soap/tests/bug70388.phpt
new file mode 100644
index 0000000000..49a8efc0ff
--- /dev/null
+++ b/ext/soap/tests/bug70388.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #70388 (SOAP serialize_function_call() type confusion / RCE)
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+$dummy = unserialize('O:10:"SoapClient":3:{s:3:"uri";s:1:"X";s:8:"location";s:22:"http://localhost/a.xml";s:17:"__default_headers";a:1:{i:1;s:1337:"'.str_repeat("X", 1337).'";}}');
+try {
+ var_dump($dummy->notexisting());
+} catch(Exception $e) {
+ var_dump($e->getMessage());
+ var_dump(get_class($e));
+}
+?>
+--EXPECTF--
+string(%d) "%s"
+string(9) "SoapFault" \ No newline at end of file
diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c
index 011d7a6e3c..ebe61c3f7a 100644
--- a/ext/spl/spl_dllist.c
+++ b/ext/spl/spl_dllist.c
@@ -1221,6 +1221,7 @@ SPL_METHOD(SplDoublyLinkedList, unserialize)
zval_ptr_dtor(&elem);
goto error;
}
+ var_push_dtor(&var_hash, &elem);
spl_ptr_llist_push(intern->llist, elem TSRMLS_CC);
}
diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c
index 5d94a3b7b3..6a2e3211e5 100644
--- a/ext/spl/spl_observer.c
+++ b/ext/spl/spl_observer.c
@@ -853,6 +853,7 @@ SPL_METHOD(SplObjectStorage, unserialize)
zval_ptr_dtor(&pentry);
goto outexcept;
}
+ var_push_dtor(&var_hash, &pentry);
if(Z_TYPE_P(pentry) != IS_OBJECT) {
zval_ptr_dtor(&pentry);
goto outexcept;
@@ -864,6 +865,7 @@ SPL_METHOD(SplObjectStorage, unserialize)
zval_ptr_dtor(&pinf);
goto outexcept;
}
+ var_push_dtor(&var_hash, &pinf);
}
hash = spl_object_storage_get_hash(intern, getThis(), pentry, &hash_len TSRMLS_CC);
diff --git a/ext/spl/tests/bug70155.phpt b/ext/spl/tests/bug70155.phpt
new file mode 100644
index 0000000000..1730a1a587
--- /dev/null
+++ b/ext/spl/tests/bug70155.phpt
@@ -0,0 +1,50 @@
+--TEST--
+SPL: Bug #70155 Use After Free Vulnerability in unserialize() with SPLArrayObject
+--FILE--
+<?php
+$inner = 'x:i:0;O:12:"DateInterval":1:{s:1:"y";i:3;};m:a:1:{i:0;R:2;}';
+$exploit = 'C:11:"ArrayObject":'.strlen($inner).':{'.$inner.'}';
+$data = unserialize($exploit);
+
+var_dump($data);
+?>
+===DONE===
+--EXPECTF--
+object(ArrayObject)#1 (2) {
+ [0]=>
+ int(0)
+ ["storage":"ArrayObject":private]=>
+ object(DateInterval)#2 (15) {
+ ["y"]=>
+ int(3)
+ ["m"]=>
+ int(-1)
+ ["d"]=>
+ int(-1)
+ ["h"]=>
+ int(-1)
+ ["i"]=>
+ int(-1)
+ ["s"]=>
+ int(-1)
+ ["weekday"]=>
+ int(-1)
+ ["weekday_behavior"]=>
+ int(-1)
+ ["first_last_day_of"]=>
+ int(-1)
+ ["invert"]=>
+ int(0)
+ ["days"]=>
+ int(-1)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(-1)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
+ }
+}
+===DONE===
diff --git a/ext/spl/tests/bug70365.phpt b/ext/spl/tests/bug70365.phpt
new file mode 100644
index 0000000000..c18110e3ca
--- /dev/null
+++ b/ext/spl/tests/bug70365.phpt
@@ -0,0 +1,50 @@
+--TEST--
+SPL: Bug #70365 use-after-free vulnerability in unserialize() with SplObjectStorage
+--FILE--
+<?php
+class obj {
+ var $ryat;
+ function __wakeup() {
+ $this->ryat = 1;
+ }
+}
+
+$fakezval = ptr2str(1122334455);
+$fakezval .= ptr2str(0);
+$fakezval .= "\x00\x00\x00\x00";
+$fakezval .= "\x01";
+$fakezval .= "\x00";
+$fakezval .= "\x00\x00";
+
+$inner = 'x:i:1;O:8:"stdClass":0:{},i:1;;m:a:0:{}';
+$exploit = 'a:5:{i:0;i:1;i:1;C:16:"SplObjectStorage":'.strlen($inner).':{'.$inner.'}i:2;O:3:"obj":1:{s:4:"ryat";R:3;}i:3;R:6;i:4;s:'.strlen($fakezval).':"'.$fakezval.'";}';
+
+$data = unserialize($exploit);
+
+var_dump($data);
+
+function ptr2str($ptr)
+{
+ $out = '';
+ for ($i = 0; $i < 8; $i++) {
+ $out .= chr($ptr & 0xff);
+ $ptr >>= 8;
+ }
+ return $out;
+}
+--EXPECTF--
+array(5) {
+ [0]=>
+ int(1)
+ [1]=>
+ &int(1)
+ [2]=>
+ object(obj)#%d (1) {
+ ["ryat"]=>
+ &int(1)
+ }
+ [3]=>
+ int(1)
+ [4]=>
+ string(24) "%s"
+}
diff --git a/ext/spl/tests/bug70366.phpt b/ext/spl/tests/bug70366.phpt
new file mode 100644
index 0000000000..c9aa584ae2
--- /dev/null
+++ b/ext/spl/tests/bug70366.phpt
@@ -0,0 +1,54 @@
+--TEST--
+SPL: Bug #70366 use-after-free vulnerability in unserialize() with SplDoublyLinkedList
+--FILE--
+<?php
+class obj {
+ var $ryat;
+ function __wakeup() {
+ $this->ryat = 1;
+ }
+}
+
+$fakezval = ptr2str(1122334455);
+$fakezval .= ptr2str(0);
+$fakezval .= "\x00\x00\x00\x00";
+$fakezval .= "\x01";
+$fakezval .= "\x00";
+$fakezval .= "\x00\x00";
+
+$inner = 'i:1234;:i:1;';
+$exploit = 'a:5:{i:0;i:1;i:1;C:19:"SplDoublyLinkedList":'.strlen($inner).':{'.$inner.'}i:2;O:3:"obj":1:{s:4:"ryat";R:3;}i:3;a:1:{i:0;R:5;}i:4;s:'.strlen($fakezval).':"'.$fakezval.'";}';
+
+$data = unserialize($exploit);
+
+var_dump($data);
+
+function ptr2str($ptr)
+{
+ $out = '';
+ for ($i = 0; $i < 8; $i++) {
+ $out .= chr($ptr & 0xff);
+ $ptr >>= 8;
+ }
+ return $out;
+}
+?>
+--EXPECTF--
+array(5) {
+ [0]=>
+ int(1)
+ [1]=>
+ &int(1)
+ [2]=>
+ object(obj)#%d (1) {
+ ["ryat"]=>
+ &int(1)
+ }
+ [3]=>
+ array(1) {
+ [0]=>
+ int(1)
+ }
+ [4]=>
+ string(24) "%s"
+} \ No newline at end of file
diff --git a/ext/standard/tests/serialize/bug70172.phpt b/ext/standard/tests/serialize/bug70172.phpt
new file mode 100644
index 0000000000..0a4aa4be16
--- /dev/null
+++ b/ext/standard/tests/serialize/bug70172.phpt
@@ -0,0 +1,54 @@
+--TEST--
+Bug #70172 - Use After Free Vulnerability in unserialize()
+--XFAIL--
+Memory leak on debug build, needs fix.
+--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 = 'r:2;';
+$exploit = 'a:2:{i:0;i:1;i:1;C:3:"obj":'.strlen($inner).':{'.$inner.'}}';
+
+$data = unserialize($exploit);
+
+for ($i = 0; $i < 5; $i++) {
+ $v[$i] = $fakezval.$i;
+}
+
+var_dump($data);
+
+function ptr2str($ptr)
+{
+ $out = '';
+ for ($i = 0; $i < 8; $i++) {
+ $out .= chr($ptr & 0xff);
+ $ptr >>= 8;
+ }
+ return $out;
+}
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ int(1)
+ [1]=>
+ object(obj)#%d (1) {
+ ["data"]=>
+ int(1)
+ }
+} \ No newline at end of file
diff --git a/ext/standard/tests/serialize/bug70172_2.phpt b/ext/standard/tests/serialize/bug70172_2.phpt
new file mode 100644
index 0000000000..ae48341a46
--- /dev/null
+++ b/ext/standard/tests/serialize/bug70172_2.phpt
@@ -0,0 +1,68 @@
+--TEST--
+Bug #70172 - 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);
+ }
+}
+
+class obj2 {
+ var $ryat;
+ function __wakeup() {
+ $this->ryat = 1;
+ }
+}
+
+$fakezval = ptr2str(1122334455);
+$fakezval .= ptr2str(0);
+$fakezval .= "\x00\x00\x00\x00";
+$fakezval .= "\x01";
+$fakezval .= "\x00";
+$fakezval .= "\x00\x00";
+
+$inner = 'r:2;';
+$exploit = 'a:2:{i:0;O:4:"obj2":1:{s:4:"ryat";C:3:"obj":'.strlen($inner).':{'.$inner.'}}i:1;a:1:{i:0;a:1:{i:0;R:4;}}}';
+
+$data = unserialize($exploit);
+
+for ($i = 0; $i < 5; $i++) {
+ $v[$i] = $fakezval.$i;
+}
+
+var_dump($data);
+
+function ptr2str($ptr)
+{
+ $out = '';
+ for ($i = 0; $i < 8; $i++) {
+ $out .= chr($ptr & 0xff);
+ $ptr >>= 8;
+ }
+ return $out;
+}
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ object(obj2)#%d (1) {
+ ["ryat"]=>
+ int(1)
+ }
+ [1]=>
+ array(1) {
+ [0]=>
+ array(1) {
+ [0]=>
+ object(obj2)#%d (1) {
+ ["ryat"]=>
+ int(1)
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ext/standard/tests/serialize/bug70219.phpt b/ext/standard/tests/serialize/bug70219.phpt
new file mode 100644
index 0000000000..84a059f365
--- /dev/null
+++ b/ext/standard/tests/serialize/bug70219.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Bug #70219 Use after free vulnerability in session deserializer
+--FILE--
+<?php
+class obj implements Serializable {
+ var $data;
+ function serialize() {
+ return serialize($this->data);
+ }
+ function unserialize($data) {
+ session_start();
+ session_decode($data);
+ }
+}
+
+$inner = 'ryat|a:1:{i:0;a:1:{i:1;';
+$exploit = 'a:2:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:1;R:4;}';
+
+$data = unserialize($exploit);
+
+for ($i = 0; $i < 5; $i++) {
+ $v[$i] = 'hi'.$i;
+}
+
+var_dump($data);
+?>
+--EXPECTF--
+Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s on line %d
+array(2) {
+ [0]=>
+ object(obj)#%d (1) {
+ ["data"]=>
+ NULL
+ }
+ [1]=>
+ array(0) {
+ }
+}
diff --git a/ext/standard/var.c b/ext/standard/var.c
index 7603ff2ee0..113b8cb66a 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -373,7 +373,7 @@ static int php_array_element_export(zval **zv TSRMLS_DC, int num_args, va_list a
smart_str_appendc(buf, ',');
smart_str_appendc(buf, '\n');
-
+
return 0;
}
/* }}} */
@@ -392,7 +392,7 @@ static int php_object_element_export(zval **zv TSRMLS_DC, int num_args, va_list
const char *pname;
char *pname_esc;
int pname_esc_len;
-
+
zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength - 1,
&class_name, &pname);
pname_esc = php_addcslashes(pname, strlen(pname), &pname_esc_len, 0,
@@ -469,7 +469,7 @@ PHPAPI void php_var_export_ex(zval **struc, int level, smart_str *buf TSRMLS_DC)
buffer_append_spaces(buf, level - 1);
}
smart_str_appendc(buf, ')');
-
+
break;
case IS_OBJECT:
@@ -802,7 +802,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var
BG(serialize_lock)++;
res = call_user_function_ex(CG(function_table), &struc, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
BG(serialize_lock)--;
-
+
if (EG(exception)) {
if (retval_ptr) {
zval_ptr_dtor(&retval_ptr);
@@ -951,6 +951,8 @@ PHP_FUNCTION(unserialize)
int buf_len;
const unsigned char *p;
php_unserialize_data_t var_hash;
+ int oldlevel;
+ zval *old_rval = return_value;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
RETURN_FALSE;
@@ -970,6 +972,20 @@ PHP_FUNCTION(unserialize)
}
RETURN_FALSE;
}
+ if (return_value != old_rval) {
+ /*
+ * Terrible hack due to the fact that executor passes us zval *,
+ * but unserialize with r/R wants to replace it with another zval *
+ */
+ zval_dtor(old_rval);
+ *old_rval = *return_value;
+ zval_copy_ctor(old_rval);
+ var_push_dtor_no_addref(&var_hash, &return_value);
+ /* FIXME: old_rval is not freed in some scenarios, see bug #70172
+ var_push_dtor_no_addref(&var_hash, &old_rval); */
+ } else {
+ var_push_dtor(&var_hash, &return_value);
+ }
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
}
/* }}} */
diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c
index ee0cac4762..5f2336ec14 100644
--- a/ext/standard/var_unserializer.c
+++ b/ext/standard/var_unserializer.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.7.5 on Tue Mar 17 13:14:30 2015 */
+/* Generated by re2c 0.13.7.5 on Mon Aug 31 23:15:46 2015 */
#line 1 "ext/standard/var_unserializer.re"
/*
+----------------------------------------------------------------------+
@@ -69,7 +69,7 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
var_hash = (*var_hashx)->last_dtor;
#if VAR_ENTRIES_DBG
- fprintf(stderr, "var_push_dtor(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
+ fprintf(stderr, "var_push_dtor(%p, %ld): %d\n", *rval, var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
#endif
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
@@ -92,9 +92,15 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval **rval)
{
- var_entries *var_hash = (*var_hashx)->last_dtor;
+ var_entries *var_hash;
+
+ if (!var_hashx || !*var_hashx) {
+ return;
+ }
+
+ var_hash = (*var_hashx)->last_dtor;
#if VAR_ENTRIES_DBG
- fprintf(stderr, "var_push_dtor_no_addref(%ld): %d (%d)\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval), Z_REFCOUNT_PP(rval));
+ fprintf(stderr, "var_push_dtor_no_addref(%p, %ld): %d (%d)\n", *rval, var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval), Z_REFCOUNT_PP(rval));
#endif
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
@@ -121,7 +127,7 @@ PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **n
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(nzval));
#endif
-
+
while (var_hash) {
for (i = 0; i < var_hash->used_slots; i++) {
if (var_hash->data[i] == ozval) {
@@ -139,7 +145,7 @@ static int var_access(php_unserialize_data_t *var_hashx, long id, zval ***store)
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_access(%ld): %ld\n", var_hash?var_hash->used_slots:-1L, id);
#endif
-
+
while (id >= VAR_ENTRIES_MAX && var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
var_hash = var_hash->next;
id -= VAR_ENTRIES_MAX;
@@ -162,7 +168,7 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L);
#endif
-
+
while (var_hash) {
next = var_hash->next;
efree(var_hash);
@@ -170,9 +176,12 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
}
var_hash = (*var_hashx)->first_dtor;
-
+
while (var_hash) {
for (i = 0; i < var_hash->used_slots; i++) {
+#if VAR_ENTRIES_DBG
+ fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_hash->data[i], Z_REFCOUNT_P(var_hash->data[i]));
+#endif
zval_ptr_dtor(&var_hash->data[i]);
}
next = var_hash->next;
@@ -233,7 +242,7 @@ static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen
#define YYMARKER marker
-#line 241 "ext/standard/var_unserializer.re"
+#line 250 "ext/standard/var_unserializer.re"
@@ -251,7 +260,7 @@ static inline long parse_iv2(const unsigned char *p, const unsigned char **q)
case '+':
p++;
}
-
+
while (1) {
cursor = (char)*p;
if (cursor >= '0' && cursor <= '9') {
@@ -280,7 +289,7 @@ static inline size_t parse_uiv(const unsigned char *p)
if (*p == '+') {
p++;
}
-
+
while (1) {
cursor = *p;
if (cursor >= '0' && cursor <= '9') {
@@ -304,24 +313,20 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
ALLOC_INIT_ZVAL(key);
if (!php_var_unserialize(&key, p, max, NULL TSRMLS_CC)) {
- zval_dtor(key);
- FREE_ZVAL(key);
+ var_push_dtor_no_addref(var_hash, &key);
return 0;
}
if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
- zval_dtor(key);
- FREE_ZVAL(key);
+ var_push_dtor_no_addref(var_hash, &key);
return 0;
}
ALLOC_INIT_ZVAL(data);
if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
- zval_dtor(key);
- FREE_ZVAL(key);
- zval_dtor(data);
- FREE_ZVAL(data);
+ var_push_dtor_no_addref(var_hash, &key);
+ var_push_dtor_no_addref(var_hash, &data);
return 0;
}
@@ -350,9 +355,7 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
sizeof data, NULL);
}
var_push_dtor(var_hash, &data);
-
- zval_dtor(key);
- FREE_ZVAL(key);
+ var_push_dtor_no_addref(var_hash, &key);
if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
(*p)--;
@@ -402,11 +405,11 @@ static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
{
long elements;
-
+
elements = parse_iv2((*p) + 2, p);
(*p) += 2;
-
+
/* The internal class check here is a BC fix only, userspace classes implementing the
Serializable interface have eventually an inconsistent behavior at this place when
unserialized from a manipulated string. Additionaly the interal classes can possibly
@@ -470,21 +473,21 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
limit = max;
cursor = *p;
-
+
if (YYCURSOR >= YYLIMIT) {
return 0;
}
-
+
if (var_hash && cursor[0] != 'R') {
var_push(var_hash, rval);
}
start = cursor;
-
-
-#line 488 "ext/standard/var_unserializer.c"
+
+
+#line 491 "ext/standard/var_unserializer.c"
{
YYCTYPE yych;
static const unsigned char yybm[] = {
@@ -544,9 +547,9 @@ yy2:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy95;
yy3:
-#line 839 "ext/standard/var_unserializer.re"
+#line 845 "ext/standard/var_unserializer.re"
{ return 0; }
-#line 550 "ext/standard/var_unserializer.c"
+#line 553 "ext/standard/var_unserializer.c"
yy4:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy89;
@@ -589,13 +592,13 @@ yy13:
goto yy3;
yy14:
++YYCURSOR;
-#line 833 "ext/standard/var_unserializer.re"
+#line 839 "ext/standard/var_unserializer.re"
{
/* this is the case where we have less data than planned */
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
return 0; /* not sure if it should be 0 or 1 here? */
}
-#line 599 "ext/standard/var_unserializer.c"
+#line 602 "ext/standard/var_unserializer.c"
yy16:
yych = *++YYCURSOR;
goto yy3;
@@ -626,7 +629,7 @@ yy20:
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 687 "ext/standard/var_unserializer.re"
+#line 692 "ext/standard/var_unserializer.re"
{
size_t len, len2, len3, maxlen;
long elements;
@@ -642,10 +645,11 @@ yy20:
zval **args[1];
zval *arg_func_name;
+ if (!var_hash) return 0;
if (*start == 'C') {
custom_object = 1;
}
-
+
INIT_PZVAL(*rval);
len2 = len = parse_uiv(start + 2);
maxlen = max - YYCURSOR;
@@ -694,14 +698,14 @@ yy20:
efree(class_name);
return 0;
}
-
+
/* Check for unserialize callback */
if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
incomplete_class = 1;
ce = PHP_IC_ENTRY;
break;
}
-
+
/* Call unserialize callback */
MAKE_STD_ZVAL(user_func);
ZVAL_STRING(user_func, PG(unserialize_callback_func), 1);
@@ -734,7 +738,7 @@ yy20:
zval_ptr_dtor(&arg_func_name);
return 0;
}
-
+
/* The callback function may have defined the class */
if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
ce = *pce;
@@ -762,7 +766,7 @@ yy20:
efree(class_name);
return ret;
}
-
+
elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
if (incomplete_class) {
@@ -772,7 +776,7 @@ yy20:
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
-#line 776 "ext/standard/var_unserializer.c"
+#line 780 "ext/standard/var_unserializer.c"
yy25:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -797,15 +801,16 @@ yy27:
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 679 "ext/standard/var_unserializer.re"
+#line 683 "ext/standard/var_unserializer.re"
{
+ if (!var_hash) return 0;
INIT_PZVAL(*rval);
-
+
return object_common2(UNSERIALIZE_PASSTHRU,
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
}
-#line 809 "ext/standard/var_unserializer.c"
+#line 814 "ext/standard/var_unserializer.c"
yy32:
yych = *++YYCURSOR;
if (yych == '+') goto yy33;
@@ -826,11 +831,12 @@ yy34:
yych = *++YYCURSOR;
if (yych != '{') goto yy18;
++YYCURSOR;
-#line 659 "ext/standard/var_unserializer.re"
+#line 662 "ext/standard/var_unserializer.re"
{
long elements = parse_iv(start + 2);
/* use iv() not uiv() in order to check data range */
*p = YYCURSOR;
+ if (!var_hash) return 0;
if (elements < 0) {
return 0;
@@ -846,7 +852,7 @@ yy34:
return finish_nested_data(UNSERIALIZE_PASSTHRU);
}
-#line 850 "ext/standard/var_unserializer.c"
+#line 856 "ext/standard/var_unserializer.c"
yy39:
yych = *++YYCURSOR;
if (yych == '+') goto yy40;
@@ -867,7 +873,7 @@ yy41:
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 630 "ext/standard/var_unserializer.re"
+#line 633 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
char *str;
@@ -896,7 +902,7 @@ yy41:
ZVAL_STRINGL(*rval, str, len, 0);
return 1;
}
-#line 900 "ext/standard/var_unserializer.c"
+#line 906 "ext/standard/var_unserializer.c"
yy46:
yych = *++YYCURSOR;
if (yych == '+') goto yy47;
@@ -917,7 +923,7 @@ yy48:
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 602 "ext/standard/var_unserializer.re"
+#line 605 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
char *str;
@@ -945,7 +951,7 @@ yy48:
ZVAL_STRINGL(*rval, str, len, 1);
return 1;
}
-#line 949 "ext/standard/var_unserializer.c"
+#line 955 "ext/standard/var_unserializer.c"
yy53:
yych = *++YYCURSOR;
if (yych <= '/') {
@@ -1033,7 +1039,7 @@ yy61:
}
yy63:
++YYCURSOR;
-#line 592 "ext/standard/var_unserializer.re"
+#line 595 "ext/standard/var_unserializer.re"
{
#if SIZEOF_LONG == 4
use_double:
@@ -1043,7 +1049,7 @@ use_double:
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
return 1;
}
-#line 1047 "ext/standard/var_unserializer.c"
+#line 1053 "ext/standard/var_unserializer.c"
yy65:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -1102,7 +1108,7 @@ yy73:
yych = *++YYCURSOR;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 577 "ext/standard/var_unserializer.re"
+#line 580 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
INIT_PZVAL(*rval);
@@ -1117,7 +1123,7 @@ yy73:
return 1;
}
-#line 1121 "ext/standard/var_unserializer.c"
+#line 1127 "ext/standard/var_unserializer.c"
yy76:
yych = *++YYCURSOR;
if (yych == 'N') goto yy73;
@@ -1144,7 +1150,7 @@ yy79:
if (yych <= '9') goto yy79;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 550 "ext/standard/var_unserializer.re"
+#line 553 "ext/standard/var_unserializer.re"
{
#if SIZEOF_LONG == 4
int digits = YYCURSOR - start - 3;
@@ -1171,7 +1177,7 @@ yy79:
ZVAL_LONG(*rval, parse_iv(start + 2));
return 1;
}
-#line 1175 "ext/standard/var_unserializer.c"
+#line 1181 "ext/standard/var_unserializer.c"
yy83:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
@@ -1179,24 +1185,24 @@ yy83:
yych = *++YYCURSOR;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 543 "ext/standard/var_unserializer.re"
+#line 546 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_BOOL(*rval, parse_iv(start + 2));
return 1;
}
-#line 1190 "ext/standard/var_unserializer.c"
+#line 1196 "ext/standard/var_unserializer.c"
yy87:
++YYCURSOR;
-#line 536 "ext/standard/var_unserializer.re"
+#line 539 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_NULL(*rval);
return 1;
}
-#line 1200 "ext/standard/var_unserializer.c"
+#line 1206 "ext/standard/var_unserializer.c"
yy89:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -1219,7 +1225,7 @@ yy91:
if (yych <= '9') goto yy91;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 513 "ext/standard/var_unserializer.re"
+#line 516 "ext/standard/var_unserializer.re"
{
long id;
@@ -1239,10 +1245,10 @@ yy91:
*rval = *rval_ref;
Z_ADDREF_PP(rval);
Z_UNSET_ISREF_PP(rval);
-
+
return 1;
}
-#line 1246 "ext/standard/var_unserializer.c"
+#line 1252 "ext/standard/var_unserializer.c"
yy95:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -1265,7 +1271,7 @@ yy97:
if (yych <= '9') goto yy97;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 492 "ext/standard/var_unserializer.re"
+#line 495 "ext/standard/var_unserializer.re"
{
long id;
@@ -1278,17 +1284,17 @@ yy97:
}
if (*rval != NULL) {
- zval_ptr_dtor(rval);
+ var_push_dtor_no_addref(var_hash, rval);
}
*rval = *rval_ref;
Z_ADDREF_PP(rval);
Z_SET_ISREF_PP(rval);
-
+
return 1;
}
-#line 1290 "ext/standard/var_unserializer.c"
+#line 1296 "ext/standard/var_unserializer.c"
}
-#line 841 "ext/standard/var_unserializer.re"
+#line 847 "ext/standard/var_unserializer.re"
return 0;
diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re
index abac77ccea..ed821521e0 100644
--- a/ext/standard/var_unserializer.re
+++ b/ext/standard/var_unserializer.re
@@ -67,7 +67,7 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
var_hash = (*var_hashx)->last_dtor;
#if VAR_ENTRIES_DBG
- fprintf(stderr, "var_push_dtor(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
+ fprintf(stderr, "var_push_dtor(%p, %ld): %d\n", *rval, var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
#endif
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
@@ -90,9 +90,15 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval **rval)
{
- var_entries *var_hash = (*var_hashx)->last_dtor;
+ var_entries *var_hash;
+
+ if (!var_hashx || !*var_hashx) {
+ return;
+ }
+
+ var_hash = (*var_hashx)->last_dtor;
#if VAR_ENTRIES_DBG
- fprintf(stderr, "var_push_dtor_no_addref(%ld): %d (%d)\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval), Z_REFCOUNT_PP(rval));
+ fprintf(stderr, "var_push_dtor_no_addref(%p, %ld): %d (%d)\n", *rval, var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval), Z_REFCOUNT_PP(rval));
#endif
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
@@ -119,7 +125,7 @@ PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **n
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(nzval));
#endif
-
+
while (var_hash) {
for (i = 0; i < var_hash->used_slots; i++) {
if (var_hash->data[i] == ozval) {
@@ -137,7 +143,7 @@ static int var_access(php_unserialize_data_t *var_hashx, long id, zval ***store)
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_access(%ld): %ld\n", var_hash?var_hash->used_slots:-1L, id);
#endif
-
+
while (id >= VAR_ENTRIES_MAX && var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
var_hash = var_hash->next;
id -= VAR_ENTRIES_MAX;
@@ -160,7 +166,7 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L);
#endif
-
+
while (var_hash) {
next = var_hash->next;
efree(var_hash);
@@ -168,9 +174,12 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
}
var_hash = (*var_hashx)->first_dtor;
-
+
while (var_hash) {
for (i = 0; i < var_hash->used_slots; i++) {
+#if VAR_ENTRIES_DBG
+ fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_hash->data[i], Z_REFCOUNT_P(var_hash->data[i]));
+#endif
zval_ptr_dtor(&var_hash->data[i]);
}
next = var_hash->next;
@@ -255,7 +264,7 @@ static inline long parse_iv2(const unsigned char *p, const unsigned char **q)
case '+':
p++;
}
-
+
while (1) {
cursor = (char)*p;
if (cursor >= '0' && cursor <= '9') {
@@ -284,7 +293,7 @@ static inline size_t parse_uiv(const unsigned char *p)
if (*p == '+') {
p++;
}
-
+
while (1) {
cursor = *p;
if (cursor >= '0' && cursor <= '9') {
@@ -308,24 +317,20 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
ALLOC_INIT_ZVAL(key);
if (!php_var_unserialize(&key, p, max, NULL TSRMLS_CC)) {
- zval_dtor(key);
- FREE_ZVAL(key);
+ var_push_dtor_no_addref(var_hash, &key);
return 0;
}
if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
- zval_dtor(key);
- FREE_ZVAL(key);
+ var_push_dtor_no_addref(var_hash, &key);
return 0;
}
ALLOC_INIT_ZVAL(data);
if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
- zval_dtor(key);
- FREE_ZVAL(key);
- zval_dtor(data);
- FREE_ZVAL(data);
+ var_push_dtor_no_addref(var_hash, &key);
+ var_push_dtor_no_addref(var_hash, &data);
return 0;
}
@@ -354,9 +359,7 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
sizeof data, NULL);
}
var_push_dtor(var_hash, &data);
-
- zval_dtor(key);
- FREE_ZVAL(key);
+ var_push_dtor_no_addref(var_hash, &key);
if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
(*p)--;
@@ -406,11 +409,11 @@ static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
{
long elements;
-
+
elements = parse_iv2((*p) + 2, p);
(*p) += 2;
-
+
/* The internal class check here is a BC fix only, userspace classes implementing the
Serializable interface have eventually an inconsistent behavior at this place when
unserialized from a manipulated string. Additionaly the interal classes can possibly
@@ -474,19 +477,19 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
limit = max;
cursor = *p;
-
+
if (YYCURSOR >= YYLIMIT) {
return 0;
}
-
+
if (var_hash && cursor[0] != 'R') {
var_push(var_hash, rval);
}
start = cursor;
-
-
+
+
/*!re2c
"R:" iv ";" {
@@ -501,12 +504,12 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
}
if (*rval != NULL) {
- zval_ptr_dtor(rval);
+ var_push_dtor_no_addref(var_hash, rval);
}
*rval = *rval_ref;
Z_ADDREF_PP(rval);
Z_SET_ISREF_PP(rval);
-
+
return 1;
}
@@ -529,7 +532,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
*rval = *rval_ref;
Z_ADDREF_PP(rval);
Z_UNSET_ISREF_PP(rval);
-
+
return 1;
}
@@ -660,6 +663,7 @@ use_double:
long elements = parse_iv(start + 2);
/* use iv() not uiv() in order to check data range */
*p = YYCURSOR;
+ if (!var_hash) return 0;
if (elements < 0) {
return 0;
@@ -677,9 +681,10 @@ use_double:
}
"o:" iv ":" ["] {
+ if (!var_hash) return 0;
INIT_PZVAL(*rval);
-
+
return object_common2(UNSERIALIZE_PASSTHRU,
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
}
@@ -699,10 +704,11 @@ object ":" uiv ":" ["] {
zval **args[1];
zval *arg_func_name;
+ if (!var_hash) return 0;
if (*start == 'C') {
custom_object = 1;
}
-
+
INIT_PZVAL(*rval);
len2 = len = parse_uiv(start + 2);
maxlen = max - YYCURSOR;
@@ -751,14 +757,14 @@ object ":" uiv ":" ["] {
efree(class_name);
return 0;
}
-
+
/* Check for unserialize callback */
if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
incomplete_class = 1;
ce = PHP_IC_ENTRY;
break;
}
-
+
/* Call unserialize callback */
MAKE_STD_ZVAL(user_func);
ZVAL_STRING(user_func, PG(unserialize_callback_func), 1);
@@ -791,7 +797,7 @@ object ":" uiv ":" ["] {
zval_ptr_dtor(&arg_func_name);
return 0;
}
-
+
/* The callback function may have defined the class */
if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
ce = *pce;
@@ -819,7 +825,7 @@ object ":" uiv ":" ["] {
efree(class_name);
return ret;
}
-
+
elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
if (incomplete_class) {
diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c
index 67c90f501f..d21a8ebcb7 100644
--- a/ext/xsl/xsltprocessor.c
+++ b/ext/xsl/xsltprocessor.c
@@ -81,10 +81,10 @@ ZEND_END_ARG_INFO();
/* }}} */
/*
-* class xsl_xsltprocessor
+* class xsl_xsltprocessor
*
* URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
-* Since:
+* Since:
*/
const zend_function_entry php_xsl_xsltprocessor_class_functions[] = {
@@ -111,9 +111,9 @@ static char *php_xsl_xslt_string_to_xpathexpr(const char *str TSRMLS_DC)
xmlChar *value;
int str_len;
-
+
str_len = xmlStrlen(string) + 3;
-
+
if (xmlStrchr(string, '"')) {
if (xmlStrchr(string, '\'')) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create XPath expression (string contains both quote and double-quotes)");
@@ -133,7 +133,7 @@ static char *php_xsl_xslt_string_to_xpathexpr(const char *str TSRMLS_DC)
Translates a PHP array to a libxslt parameters array */
static char **php_xsl_xslt_make_params(HashTable *parht, int xpath_params TSRMLS_DC)
{
-
+
int parsize;
zval **value;
char *xpath_expr, *string_key = NULL;
@@ -158,7 +158,7 @@ static char **php_xsl_xslt_make_params(HashTable *parht, int xpath_params TSRMLS
SEPARATE_ZVAL(value);
convert_to_string(*value);
}
-
+
if (!xpath_params) {
xpath_expr = php_xsl_xslt_string_to_xpathexpr(Z_STRVAL_PP(value) TSRMLS_CC);
} else {
@@ -192,7 +192,7 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
char *str;
char *callable = NULL;
xsl_object *intern;
-
+
TSRMLS_FETCH();
if (! zend_is_executing(TSRMLS_C)) {
@@ -219,15 +219,17 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
}
}
}
-
+
if (error == 1) {
for (i = nargs - 1; i >= 0; i--) {
obj = valuePop(ctxt);
- xmlXPathFreeObject(obj);
+ if (obj) {
+ xmlXPathFreeObject(obj);
+ }
}
return;
}
-
+
fci.param_count = nargs - 1;
if (fci.param_count > 0) {
fci.params = safe_emalloc(fci.param_count, sizeof(zval**), 0);
@@ -265,7 +267,7 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
if (node->type == XML_NAMESPACE_DECL) {
xmlNsPtr curns;
xmlNodePtr nsparent;
-
+
nsparent = node->_private;
curns = xmlNewNs(NULL, node->name, NULL);
if (node->children) {
@@ -297,14 +299,16 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
xmlXPathFreeObject(obj);
fci.params[i] = &args[i];
}
-
+
fci.size = sizeof(fci);
fci.function_table = EG(function_table);
-
+
obj = valuePop(ctxt);
- if (obj->stringval == NULL) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Handler name must be a string");
- xmlXPathFreeObject(obj);
+ if (obj == NULL || obj->stringval == NULL) {
+ if (obj) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Handler name must be a string");
+ xmlXPathFreeObject(obj);
+ }
valuePush(ctxt, xmlXPathNewString(""));
if (fci.param_count > 0) {
for (i = 0; i < nargs - 1; i++) {
@@ -313,12 +317,12 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
efree(args);
efree(fci.params);
}
- return;
+ return;
}
INIT_PZVAL(&handler);
ZVAL_STRING(&handler, obj->stringval, 1);
xmlXPathFreeObject(obj);
-
+
fci.function_name = &handler;
fci.symbol_table = NULL;
fci.object_ptr = NULL;
@@ -328,7 +332,7 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
if (!zend_make_callable(&handler, &callable TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", callable);
valuePush(ctxt, xmlXPathNewString(""));
- } else if ( intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable, strlen(callable) + 1) == 0) {
+ } else if ( intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable, strlen(callable) + 1) == 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not allowed to call handler '%s()'", callable);
/* Push an empty string, so that we at least have an xslt result... */
valuePush(ctxt, xmlXPathNewString(""));
@@ -392,7 +396,7 @@ void xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs) /* {{
/* {{{ proto void xsl_xsltprocessor_import_stylesheet(domdocument doc);
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
-Since:
+Since:
*/
PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
{
@@ -404,13 +408,13 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
xmlNode *nodep = NULL;
zend_object_handlers *std_hnd;
zval *cloneDocu, *member;
-
+
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oo", &id, xsl_xsltprocessor_class_entry, &docp) == FAILURE) {
RETURN_FALSE;
}
nodep = php_libxml_import_node(docp TSRMLS_CC);
-
+
if (nodep) {
doc = nodep->doc;
}
@@ -419,7 +423,7 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
RETURN_FALSE;
}
- /* libxslt uses _private, so we must copy the imported
+ /* libxslt uses _private, so we must copy the imported
stylesheet document otherwise the node proxies will be a mess */
newdoc = xmlCopyDoc(doc, 1);
xmlNodeSetBase((xmlNodePtr) newdoc, (xmlChar *)doc->URL);
@@ -436,7 +440,7 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
RETURN_FALSE;
}
- intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
+ intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
std_hnd = zend_get_std_object_handlers();
MAKE_STD_ZVAL(member);
@@ -463,10 +467,10 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
intern->hasKeys = clone_docu;
}
- if ((oldsheetp = (xsltStylesheetPtr)intern->ptr)) {
+ if ((oldsheetp = (xsltStylesheetPtr)intern->ptr)) {
/* free wrapper */
if (((xsltStylesheetPtr) intern->ptr)->_private != NULL) {
- ((xsltStylesheetPtr) intern->ptr)->_private = NULL;
+ ((xsltStylesheetPtr) intern->ptr)->_private = NULL;
}
xsltFreeStylesheet((xsltStylesheetPtr) intern->ptr);
intern->ptr = NULL;
@@ -494,7 +498,7 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl
xsltSecurityPrefsPtr secPrefs = NULL;
node = php_libxml_import_node(docp TSRMLS_CC);
-
+
if (node) {
doc = node->doc;
}
@@ -507,7 +511,7 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl
php_error_docref(NULL TSRMLS_CC, E_WARNING, "No stylesheet associated to this object");
return NULL;
}
-
+
if (intern->profiling) {
if (php_check_open_basedir(intern->profiling TSRMLS_CC)) {
f = NULL;
@@ -517,7 +521,7 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl
} else {
f = NULL;
}
-
+
if (intern->parameter) {
params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC);
}
@@ -549,7 +553,7 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl
efree(member);
secPrefsValue = intern->securityPrefs;
-
+
/* This whole if block can be removed, when we remove the xsl.security_prefs php.ini option in PHP 6+ */
secPrefsIni= INI_INT("xsl.security_prefs");
/* if secPrefsIni has the same value as secPrefsValue, all is fine */
@@ -569,38 +573,38 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl
/* if securityPrefs is set to NONE, we don't have to do any checks, but otherwise... */
if (secPrefsValue != XSL_SECPREF_NONE) {
- secPrefs = xsltNewSecurityPrefs();
- if (secPrefsValue & XSL_SECPREF_READ_FILE ) {
- if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid)) {
+ secPrefs = xsltNewSecurityPrefs();
+ if (secPrefsValue & XSL_SECPREF_READ_FILE ) {
+ if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid)) {
secPrefsError = 1;
}
}
- if (secPrefsValue & XSL_SECPREF_WRITE_FILE ) {
- if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid)) {
+ if (secPrefsValue & XSL_SECPREF_WRITE_FILE ) {
+ if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid)) {
secPrefsError = 1;
}
}
- if (secPrefsValue & XSL_SECPREF_CREATE_DIRECTORY ) {
- if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid)) {
+ if (secPrefsValue & XSL_SECPREF_CREATE_DIRECTORY ) {
+ if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid)) {
secPrefsError = 1;
}
}
- if (secPrefsValue & XSL_SECPREF_READ_NETWORK) {
- if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid)) {
+ if (secPrefsValue & XSL_SECPREF_READ_NETWORK) {
+ if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid)) {
secPrefsError = 1;
}
}
- if (secPrefsValue & XSL_SECPREF_WRITE_NETWORK) {
- if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid)) {
+ if (secPrefsValue & XSL_SECPREF_WRITE_NETWORK) {
+ if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid)) {
secPrefsError = 1;
}
}
-
- if (0 != xsltSetCtxtSecurityPrefs(secPrefs, ctxt)) {
+
+ if (0 != xsltSetCtxtSecurityPrefs(secPrefs, ctxt)) {
secPrefsError = 1;
}
}
-
+
if (secPrefsError == 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't set libxslt security properties, not doing transformation for security reasons");
} else {
@@ -609,7 +613,7 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl
if (f) {
fclose(f);
}
-
+
xsltFreeTransformContext(ctxt);
if (secPrefs) {
xsltFreeSecurityPrefs(secPrefs);
@@ -617,7 +621,7 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl
if (intern->node_list != NULL) {
zend_hash_destroy(intern->node_list);
- FREE_HASHTABLE(intern->node_list);
+ FREE_HASHTABLE(intern->node_list);
intern->node_list = NULL;
}
@@ -640,7 +644,7 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl
/* {{{ proto domdocument xsl_xsltprocessor_transform_to_doc(domnode doc);
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
-Since:
+Since:
*/
PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
{
@@ -677,13 +681,13 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
found = zend_lookup_class(ret_class, ret_class_len, &ce TSRMLS_CC);
if ((found != SUCCESS) || !instanceof_function(*ce, curce TSRMLS_CC)) {
xmlFreeDoc(newdocp);
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Expecting class compatible with %s, '%s' given", curclass_name, ret_class);
RETURN_FALSE;
}
object_init_ex(return_value, *ce);
-
+
interndoc = (php_libxml_node_object *)zend_objects_get_address(return_value TSRMLS_CC);
php_libxml_increment_doc_ref(interndoc, newdocp TSRMLS_CC);
php_libxml_increment_node_ptr(interndoc, (xmlNodePtr)newdocp, (void *)interndoc TSRMLS_CC);
@@ -693,7 +697,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
} else {
RETURN_FALSE;
}
-
+
}
/* }}} end xsl_xsltprocessor_transform_to_doc */
@@ -707,7 +711,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri)
int ret, uri_len;
char *uri;
xsl_object *intern;
-
+
id = getThis();
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
sheetp = (xsltStylesheetPtr) intern->ptr;
@@ -739,7 +743,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml)
xmlChar *doc_txt_ptr;
int doc_txt_len;
xsl_object *intern;
-
+
id = getThis();
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
sheetp = (xsltStylesheetPtr) intern->ptr;
@@ -770,7 +774,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml)
*/
PHP_FUNCTION(xsl_xsltprocessor_set_parameter)
{
-
+
zval *id;
zval *array_value, **entry, *new_string;
xsl_object *intern;
@@ -786,34 +790,34 @@ PHP_FUNCTION(xsl_xsltprocessor_set_parameter)
while (zend_hash_get_current_data(Z_ARRVAL_P(array_value), (void **)&entry) == SUCCESS) {
SEPARATE_ZVAL(entry);
convert_to_string_ex(entry);
-
+
if (zend_hash_get_current_key_ex(Z_ARRVAL_P(array_value), &string_key, &string_key_len, &idx, 0, NULL) != HASH_KEY_IS_STRING) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter array");
RETURN_FALSE;
}
-
+
ALLOC_ZVAL(new_string);
Z_ADDREF_PP(entry);
COPY_PZVAL_TO_ZVAL(*new_string, *entry);
-
+
zend_hash_update(intern->parameter, string_key, string_key_len, &new_string, sizeof(zval*), NULL);
zend_hash_move_forward(Z_ARRVAL_P(array_value));
}
RETURN_TRUE;
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "sss", &namespace, &namespace_len, &name, &name_len, &value, &value_len) == SUCCESS) {
-
+
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
-
+
MAKE_STD_ZVAL(new_string);
ZVAL_STRING(new_string, value, 1);
-
+
zend_hash_update(intern->parameter, name, name_len + 1, &new_string, sizeof(zval*), NULL);
RETURN_TRUE;
} else {
WRONG_PARAM_COUNT;
}
-
+
}
/* }}} end xsl_xsltprocessor_set_parameter */
@@ -828,7 +832,7 @@ PHP_FUNCTION(xsl_xsltprocessor_get_parameter)
xsl_object *intern;
DOM_GET_THIS(id);
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &namespace, &namespace_len, &name, &name_len) == FAILURE) {
RETURN_FALSE;
}
@@ -852,7 +856,7 @@ PHP_FUNCTION(xsl_xsltprocessor_remove_parameter)
xsl_object *intern;
DOM_GET_THIS(id);
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &namespace, &namespace_len, &name, &name_len) == FAILURE) {
RETURN_FALSE;
}
@@ -876,7 +880,7 @@ PHP_FUNCTION(xsl_xsltprocessor_register_php_functions)
char *name;
DOM_GET_THIS(id);
-
+
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "a", &array_value) == SUCCESS) {
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
zend_hash_internal_pointer_reset(Z_ARRVAL_P(array_value));
@@ -884,10 +888,10 @@ PHP_FUNCTION(xsl_xsltprocessor_register_php_functions)
while (zend_hash_get_current_data(Z_ARRVAL_P(array_value), (void **)&entry) == SUCCESS) {
SEPARATE_ZVAL(entry);
convert_to_string_ex(entry);
-
+
MAKE_STD_ZVAL(new_string);
ZVAL_LONG(new_string,1);
-
+
zend_hash_update(intern->registered_phpfunctions, Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) + 1, &new_string, sizeof(zval*), NULL);
zend_hash_move_forward(Z_ARRVAL_P(array_value));
}
@@ -895,17 +899,17 @@ PHP_FUNCTION(xsl_xsltprocessor_register_php_functions)
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == SUCCESS) {
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
-
+
MAKE_STD_ZVAL(new_string);
ZVAL_LONG(new_string,1);
zend_hash_update(intern->registered_phpfunctions, name, name_len + 1, &new_string, sizeof(zval*), NULL);
intern->registerPhpFunctions = 2;
-
+
} else {
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
intern->registerPhpFunctions = 1;
}
-
+
}
/* }}} end xsl_xsltprocessor_register_php_functions(); */
@@ -947,7 +951,7 @@ PHP_FUNCTION(xsl_xsltprocessor_set_security_prefs)
return;
}
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
- oldSecurityPrefs = intern->securityPrefs;
+ oldSecurityPrefs = intern->securityPrefs;
intern->securityPrefs = securityPrefs;
/* set this to 1 so that we know, it was set through this method. Can be removed, when we remove the ini setting */
intern->securityPrefsSet = 1;
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index abc21c7f15..6c872ebfb0 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -133,7 +133,7 @@ static char * php_zip_make_relative_path(char *path, int path_len) /* {{{ */
}
/* }}} */
-#ifdef PHP_ZIP_USE_OO
+#ifdef PHP_ZIP_USE_OO
/* {{{ php_zip_extract_file */
static int php_zip_extract_file(struct zip * za, char *dest, char *file, int file_len TSRMLS_DC)
{
@@ -174,7 +174,7 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
/* it is a directory only, see #40228 */
if (path_cleaned_len > 1 && IS_SLASH(path_cleaned[path_cleaned_len - 1])) {
- len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file);
+ len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, path_cleaned);
is_dir_only = 1;
} else {
memcpy(file_dirname, path_cleaned, path_cleaned_len);
@@ -295,7 +295,7 @@ done:
}
/* }}} */
-static int php_zip_add_file(struct zip *za, const char *filename, size_t filename_len,
+static int php_zip_add_file(struct zip *za, const char *filename, size_t filename_len,
char *entry_name, size_t entry_name_len, long offset_start, long offset_len TSRMLS_DC) /* {{{ */
{
struct zip_source *zs;
@@ -345,7 +345,7 @@ static int php_zip_add_file(struct zip *za, const char *filename, size_t filenam
}
/* }}} */
-static int php_zip_parse_options(zval *options, long *remove_all_path,
+static int php_zip_parse_options(zval *options, long *remove_all_path,
char **remove_path, int *remove_path_len, char **add_path, int *add_path_len TSRMLS_DC) /* {{{ */
{
zval **option;
@@ -375,11 +375,11 @@ static int php_zip_parse_options(zval *options, long *remove_all_path,
}
if (Z_STRLEN_PP(option) >= MAXPATHLEN) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path string is too long (max: %i, %i given)",
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path string is too long (max: %i, %i given)",
MAXPATHLEN - 1, Z_STRLEN_PP(option));
return -1;
}
- *remove_path_len = Z_STRLEN_PP(option);
+ *remove_path_len = Z_STRLEN_PP(option);
*remove_path = Z_STRVAL_PP(option);
}
@@ -395,11 +395,11 @@ static int php_zip_parse_options(zval *options, long *remove_all_path,
}
if (Z_STRLEN_PP(option) >= MAXPATHLEN) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)",
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)",
MAXPATHLEN - 1, Z_STRLEN_PP(option));
return -1;
}
- *add_path_len = Z_STRLEN_PP(option);
+ *add_path_len = Z_STRLEN_PP(option);
*add_path = Z_STRVAL_PP(option);
}
return 1;
@@ -528,7 +528,7 @@ int php_zip_glob(char *pattern, int pattern_len, long flags, zval *return_value
glob_t globbuf;
int n;
int ret;
-
+
if (pattern_len >= MAXPATHLEN) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
return -1;
@@ -539,9 +539,9 @@ int php_zip_glob(char *pattern, int pattern_len, long flags, zval *return_value
return -1;
}
-#ifdef ZTS
+#ifdef ZTS
if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) {
- result = VCWD_GETCWD(cwd, MAXPATHLEN);
+ result = VCWD_GETCWD(cwd, MAXPATHLEN);
if (!result) {
cwd[0] = '\0';
}
@@ -554,7 +554,7 @@ int php_zip_glob(char *pattern, int pattern_len, long flags, zval *return_value
snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
pattern = work_pattern;
- }
+ }
#endif
globbuf.gl_offs = 0;
@@ -564,7 +564,7 @@ int php_zip_glob(char *pattern, int pattern_len, long flags, zval *return_value
/* Some glob implementation simply return no data if no matches
were found, others return the GLOB_NOMATCH error code.
We don't want to treat GLOB_NOMATCH as an error condition
- so that PHP glob() behaves the same on both types of
+ so that PHP glob() behaves the same on both types of
implementations and so that 'foreach (glob() as ...'
can be used for simple glob() calls without further error
checking.
@@ -593,11 +593,11 @@ int php_zip_glob(char *pattern, int pattern_len, long flags, zval *return_value
for (n = 0; n < globbuf.gl_pathc; n++) {
/* we need to do this everytime since GLOB_ONLYDIR does not guarantee that
* all directories will be filtered. GNU libc documentation states the
- * following:
- * If the information about the type of the file is easily available
- * non-directories will be rejected but no extra work will be done to
- * determine the information for each file. I.e., the caller must still be
- * able to filter directories out.
+ * following:
+ * If the information about the type of the file is easily available
+ * non-directories will be rejected but no extra work will be done to
+ * determine the information for each file. I.e., the caller must still be
+ * able to filter directories out.
*/
if (flags & GLOB_ONLYDIR) {
struct stat s;
@@ -633,9 +633,9 @@ int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *r
int files_cnt;
char **namelist;
-#ifdef ZTS
+#ifdef ZTS
if (!IS_ABSOLUTE_PATH(path, path_len)) {
- result = VCWD_GETCWD(cwd, MAXPATHLEN);
+ result = VCWD_GETCWD(cwd, MAXPATHLEN);
if (!result) {
cwd[0] = '\0';
}
@@ -648,7 +648,7 @@ int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *r
snprintf(work_path, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, path);
path = work_path;
- }
+ }
#endif
if (ZIP_OPENBASEDIR_CHECKPATH(path)) {
@@ -665,7 +665,7 @@ int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *r
re = pcre_get_compiled_regex(regexp, &pcre_extra, &preg_options TSRMLS_CC);
if (!re) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid expression");
- return -1;
+ return -1;
}
array_init(return_value);
@@ -678,7 +678,7 @@ int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *r
int matches;
int namelist_len = strlen(namelist[i]);
-
+
if ((namelist_len == 1 && namelist[i][0] == '.') ||
(namelist_len == 2 && namelist[i][0] == '.' && namelist[i][1] == '.')) {
efree(namelist[i]);
@@ -686,7 +686,7 @@ int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *r
}
if ((path_len + namelist_len + 1) >= MAXPATHLEN) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)",
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)",
MAXPATHLEN - 1, (path_len + namelist_len + 1));
efree(namelist[i]);
break;
@@ -709,7 +709,7 @@ int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *r
/* 0 means that the vector is too small to hold all the captured substring offsets */
if (matches < 0) {
efree(namelist[i]);
- continue;
+ continue;
}
add_next_index_string(return_value, fullpath, 1);
@@ -785,7 +785,7 @@ static const zend_function_entry zip_functions[] = {
/* }}} */
/* {{{ ZE2 OO definitions */
-#ifdef PHP_ZIP_USE_OO
+#ifdef PHP_ZIP_USE_OO
static zend_class_entry *zip_class_entry;
static zend_object_handlers zip_object_handlers;
@@ -805,7 +805,7 @@ typedef struct _zip_prop_handler {
#endif
/* }}} */
-#ifdef PHP_ZIP_USE_OO
+#ifdef PHP_ZIP_USE_OO
static void php_zip_register_prop_handler(HashTable *prop_handler, char *name, zip_read_int_t read_int_func, zip_read_const_char_t read_char_func, zip_read_const_char_from_ze_t read_char_from_obj_func, int rettype TSRMLS_DC) /* {{{ */
{
zip_prop_handler hnd;
@@ -893,7 +893,7 @@ static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member, const zen
if (obj->prop_handler != NULL) {
if (key) {
ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
- } else {
+ } else {
ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
}
}
@@ -1483,7 +1483,7 @@ static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod)
}
/* }}} */
-#ifdef PHP_ZIP_USE_OO
+#ifdef PHP_ZIP_USE_OO
/* {{{ proto mixed ZipArchive::open(string source [, int flags])
Create new zip using source uri for output, return TRUE on success or the error code */
static ZIPARCHIVE_METHOD(open)
@@ -1590,7 +1590,7 @@ static ZIPARCHIVE_METHOD(getStatusString)
zip_error_get(intern, &zep, &syp);
len = zip_error_to_str(error_string, 128, zep, syp);
- RETVAL_STRINGL(error_string, len, 1);
+ RETVAL_STRINGL(error_string, len, 1);
}
/* }}} */
@@ -1667,12 +1667,12 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
ZIP_FROM_OBJECT(intern, this);
/* 1 == glob, 2==pcre */
if (type == 1) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|la",
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|la",
&pattern, &pattern_len, &flags, &options) == FAILURE) {
return;
}
} else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sa",
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sa",
&pattern, &pattern_len, &path, &path_len, &options) == FAILURE) {
return;
}
@@ -1724,14 +1724,14 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
if (add_path) {
if ((add_path_len + file_stripped_len) > MAXPATHLEN) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Entry name too long (max: %d, %ld given)",
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Entry name too long (max: %d, %ld given)",
MAXPATHLEN - 1, (add_path_len + file_stripped_len));
zval_dtor(return_value);
RETURN_FALSE;
}
snprintf(entry_name_buf, MAXPATHLEN, "%s%s", add_path, file_stripped);
- entry_name = entry_name_buf;
+ entry_name = entry_name_buf;
entry_name_len = strlen(entry_name);
} else {
entry_name = Z_STRVAL_PP(zval_file);
@@ -1741,7 +1741,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
efree(basename);
basename = NULL;
}
- if (php_zip_add_file(intern, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file),
+ if (php_zip_add_file(intern, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file),
entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
zval_dtor(return_value);
RETURN_FALSE;
@@ -1801,7 +1801,7 @@ static ZIPARCHIVE_METHOD(addFile)
entry_name_len = filename_len;
}
- if (php_zip_add_file(intern, filename, filename_len,
+ if (php_zip_add_file(intern, filename, filename_len,
entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
RETURN_FALSE;
} else {
@@ -1865,7 +1865,7 @@ static ZIPARCHIVE_METHOD(addFromString)
}
fail:
zip_source_free(zs);
- RETURN_FALSE;
+ RETURN_FALSE;
}
/* }}} */
@@ -2770,7 +2770,7 @@ static const zend_function_entry zip_class_functions[] = {
/* {{{ PHP_MINIT_FUNCTION */
static PHP_MINIT_FUNCTION(zip)
{
-#ifdef PHP_ZIP_USE_OO
+#ifdef PHP_ZIP_USE_OO
zend_class_entry ce;
memcpy(&zip_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
@@ -2859,7 +2859,7 @@ static PHP_MINIT_FUNCTION(zip)
*/
static PHP_MSHUTDOWN_FUNCTION(zip)
{
-#ifdef PHP_ZIP_USE_OO
+#ifdef PHP_ZIP_USE_OO
zend_hash_destroy(&zip_prop_handlers);
php_unregister_url_stream_wrapper("zip" TSRMLS_CC);
#endif
diff --git a/ext/zip/tests/bug70350.phpt b/ext/zip/tests/bug70350.phpt
new file mode 100644
index 0000000000..d81de65a32
--- /dev/null
+++ b/ext/zip/tests/bug70350.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Bug #70350 (ZipArchive::extractTo allows for directory traversal when creating directories)
+--SKIPIF--
+<?php
+if(!extension_loaded('zip')) die('skip');
+?>
+--FILE--
+<?php
+
+$dir = dirname(__FILE__)."/bug70350";
+mkdir($dir);
+$archive = new ZipArchive();
+$archive->open("$dir/a.zip",ZipArchive::CREATE);
+$archive->addEmptyDir("../down2/");
+$archive->close();
+
+$archive2 = new ZipArchive();
+$archive2->open("$dir/a.zip");
+$archive2->extractTo($dir);
+$archive2->close();
+var_dump(file_exists("$dir/down2/"));
+var_dump(file_exists("../down2/"));
+?>
+--CLEAN--
+<?php
+$dir = dirname(__FILE__)."/bug70350";
+rmdir("$dir/down2");
+unlink("$dir/a.zip");
+rmdir($dir);
+?>
+--EXPECT--
+bool(true)
+bool(false)