summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanley Sufficool <ssufficool@php.net>2013-07-14 11:10:36 -0700
committerStanley Sufficool <ssufficool@php.net>2013-07-14 11:10:36 -0700
commit6e32a871a4a08c4c95ff61fb2be0d3f158882aea (patch)
tree805ef320254a391d5d03d1a3617c1b23042d7f2a
parent598e2690b81a145589f6dfe06f77d9e3b66a7853 (diff)
parente2e002d4ea7618039cabe925133760966c70b2a7 (diff)
downloadphp-git-6e32a871a4a08c4c95ff61fb2be0d3f158882aea.tar.gz
Merge branch 'PHP-5.3' of https://git.php.net/push/php-src into PHP-5.3
* 'PHP-5.3' of https://git.php.net/push/php-src: (23 commits) Merge PHP 5.3.27 NEWS add test for bug #65236 truncate results at depth of 255 to prevent corruption fix assembly of safe_address() for x86 and x86_64 Add bison 2.6.4 to the list of supported versions Update git rules (5.5 is stable, 5.3 sec only) This will be PHP 5.3.28 Fixed bug #63186 (compile failure on netbsd) ensure the error_reporting level to get expected notice fixed tests missing tests for bug #53437 missing colon Backported the fix for bug #53437 Fixed test script Fixed bug #64997 (Segfault while using RecursiveIteratorIterator on 64-bits systems) Fixed bug #64966 (segfault in zend_do_fcall_common_helper_SPEC) Fixed bug #64934 Apache2 TS crash with get_browser() Add NEWS for PHP 5.3.26 Fixed bug #64960 (Segfault in gc_zval_possible_root) fix CVE-2013-2110 - use correct formula to calculate string size ...
-rw-r--r--NEWS30
-rw-r--r--README.GIT-RULES13
-rw-r--r--Zend/acinclude.m42
-rw-r--r--Zend/tests/bug64960.phpt40
-rw-r--r--Zend/tests/bug64966.phpt30
-rw-r--r--Zend/zend_alloc.c4
-rw-r--r--Zend/zend_execute_API.c6
-rw-r--r--Zend/zend_vm_def.h2
-rw-r--r--Zend/zend_vm_execute.h2
-rw-r--r--configure.in2
-rw-r--r--ext/date/php_date.c307
-rw-r--r--ext/date/php_date.h2
-rw-r--r--ext/date/tests/bug45682.phpt18
-rw-r--r--ext/date/tests/bug48678.phpt18
-rw-r--r--ext/date/tests/bug49081.phpt7
-rw-r--r--ext/date/tests/bug49778.phpt16
-rw-r--r--ext/date/tests/bug52113.phpt161
-rw-r--r--ext/date/tests/bug52738.phpt7
-rw-r--r--ext/date/tests/bug52808.phpt48
-rw-r--r--ext/date/tests/bug53437.phpt134
-rw-r--r--ext/date/tests/bug53437_var1.phpt13
-rw-r--r--ext/date/tests/bug53437_var2.phpt80
-rw-r--r--ext/date/tests/bug53437_var3.phpt47
-rw-r--r--ext/date/tests/bug53437_var4.phpt64
-rw-r--r--ext/date/tests/bug53437_var5.phpt47
-rw-r--r--ext/date/tests/date_diff1.phpt16
-rw-r--r--ext/pdo_pgsql/tests/copy_from.phpt8
-rw-r--r--ext/pgsql/pgsql.c41
-rw-r--r--ext/pgsql/tests/10pg_convert_85.phpt1
-rw-r--r--ext/pgsql/tests/12pg_insert_85.phpt2
-rw-r--r--ext/pgsql/tests/14pg_update_85.phpt2
-rw-r--r--ext/pgsql/tests/18pg_escape_bytea.phpt3
-rw-r--r--ext/pgsql/tests/bug64609.phpt30
-rw-r--r--ext/spl/spl_iterators.c19
-rw-r--r--ext/standard/browscap.c21
-rw-r--r--ext/standard/quot_print.c2
-rw-r--r--ext/standard/tests/array/bug31158.phpt2
-rw-r--r--ext/standard/tests/strings/bug64879.phpt12
-rw-r--r--ext/xml/tests/bug65236.phpt15
-rw-r--r--ext/xml/xml.c90
-rw-r--r--main/php_version.h6
-rw-r--r--main/streams/cast.c14
42 files changed, 1262 insertions, 122 deletions
diff --git a/NEWS b/NEWS
index 7889832ab6..0e498b0b41 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,18 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
-?? ??? 2013, PHP 5.3.27
+?? ??? 2013, PHP 5.3.28
+
+11 Jul 2013, PHP 5.3.27
+
+- Core:
+ . Fixed bug #64966 (segfault in zend_do_fcall_common_helper_SPEC). (Laruence)
+ . Fixed bug #64960 (Segfault in gc_zval_possible_root). (Laruence)
+ . Fixed bug #64934 (Apache2 TS crash with get_browser()). (Anatol)
+ . Fixed bug #63186 (compile failure on netbsd). (Matteo)
+
+- DateTime:
+ . Fixed bug #53437 (Crash when using unserialized DatePeriod instance).
+ (Gustavo, Derick, Anatol)
- PDO_firebird:
. Fixed bug #64037 (Firebird return wrong value for numeric field).
@@ -11,9 +23,21 @@ PHP NEWS
- PDO_pgsql:
. Fixed bug #64949 (Buffer overflow in _pdo_pgsql_error). (Remi)
-?? ??? 2013, PHP 5.3.26
+- pgsql:
+ . Fixed bug #64609 (pg_convert enum type support). (Matteo)
-### DO NOT ADD ENTRIES HERE, ADD THEM ABOVE FOR 5.3.27 ###
+- SPL:
+ . Fixed bug #64997 (Segfault while using RecursiveIteratorIterator on
+ 64-bits systems). (Laruence)
+
+- XML:
+ . Fixed bug #65236 (heap corruption in xml parser). (Rob)
+
+06 Jun 2013, PHP 5.3.26
+
+- Core:
+ . Fixed bug #64879 (Heap based buffer overflow in quoted_printable_encode,
+ CVE 2013-2110). (Stas)
- Calendar:
. Fixed bug #64895 (Integer overflow in SndToJewish). (Remi)
diff --git a/README.GIT-RULES b/README.GIT-RULES
index 289a4e743f..6e90aa97b6 100644
--- a/README.GIT-RULES
+++ b/README.GIT-RULES
@@ -45,14 +45,17 @@ Currently we have the following branches in use::
master The active development branch.
- PHP-5.4 Is used to release the PHP 5.4.x series. It still allows for
- larger enhancements.
+ PHP-5.5 Is used to release the PHP 5.5.x series. This is a current
+ stable version and is open for bugfixes only.
- PHP-5.3 Is used to release the PHP 5.3.x series. This is current
+ PHP-5.4 Is used to release the PHP 5.4.x series. This is a current
stable version and is open for bugfixes only.
- PHP-5.2 Is used to release the PHP 5.2.x series. It is closed for
- changes now.
+ PHP-5.3 Is used to release the PHP 5.3.x series. This is currently
+ in extended support and open forsecurity fixes only. Triaged
+ via security@php.net
+
+ PHP-5.2 This branch is closed.
PHP-5.1 This branch is closed.
diff --git a/Zend/acinclude.m4 b/Zend/acinclude.m4
index 136d2d8bef..77430aba79 100644
--- a/Zend/acinclude.m4
+++ b/Zend/acinclude.m4
@@ -4,7 +4,7 @@ dnl This file contains local autoconf functions.
AC_DEFUN([LIBZEND_BISON_CHECK],[
# we only support certain bison versions
- bison_version_list="1.28 1.35 1.75 1.875 2.0 2.1 2.2 2.3 2.4 2.4.1 2.4.2 2.4.3 2.5 2.5.1 2.6 2.6.1 2.6.2"
+ bison_version_list="1.28 1.35 1.75 1.875 2.0 2.1 2.2 2.3 2.4 2.4.1 2.4.2 2.4.3 2.5 2.5.1 2.6 2.6.1 2.6.2 2.6.4"
# for standalone build of Zend Engine
test -z "$SED" && SED=sed
diff --git a/Zend/tests/bug64960.phpt b/Zend/tests/bug64960.phpt
new file mode 100644
index 0000000000..b31cca3dc6
--- /dev/null
+++ b/Zend/tests/bug64960.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Bug #64960 (Segfault in gc_zval_possible_root)
+--FILE--
+<?php
+// this makes ob_end_clean raise an error
+ob_end_flush();
+
+class ExceptionHandler {
+ public function __invoke (Exception $e)
+ {
+ // this triggers the custom error handler
+ ob_end_clean();
+ }
+}
+
+// this must be a class, closure does not trigger segfault
+set_exception_handler(new ExceptionHandler());
+
+// exception must be throwed from error handler.
+set_error_handler(function()
+{
+ $e = new Exception;
+ $e->_trace = debug_backtrace();
+
+ throw $e;
+});
+
+// trigger error handler
+$a['waa'];
+?>
+--EXPECTF--
+Notice: ob_end_flush(): failed to delete and flush buffer. No buffer to delete or flush in %sbug64960.php on line 3
+
+Fatal error: Uncaught exception 'Exception' in %sbug64960.php:19
+Stack trace:
+#0 [internal function]: {closure}(8, 'ob_end_clean():...', '%s', 9, Array)
+#1 %sbug64960.php(9): ob_end_clean()
+#2 [internal function]: ExceptionHandler->__invoke(Object(Exception))
+#3 {main}
+ thrown in %sbug64960.php on line 19
diff --git a/Zend/tests/bug64966.phpt b/Zend/tests/bug64966.phpt
new file mode 100644
index 0000000000..c1cdbbf812
--- /dev/null
+++ b/Zend/tests/bug64966.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #64966 (segfault in zend_do_fcall_common_helper_SPEC)
+--FILE--
+<?php
+error_reporting(E_ALL);
+set_error_handler(function($error) { throw new Exception(); }, E_RECOVERABLE_ERROR);
+
+function test($func) {
+ $a = $func("");
+ return true;
+}
+class A {
+ public function b() {
+ test("strlen");
+ test("iterator_apply");
+ }
+}
+
+$a = new A();
+$a->b();
+?>
+--EXPECTF--
+Fatal error: Uncaught exception 'Exception' in %sbug64966.php:3
+Stack trace:
+#0 [internal function]: {closure}(4096, 'Argument 1 pass...', '%s', 6, Array)
+#1 %sbug64966.php(6): iterator_apply('')
+#2 %sbug64966.php(12): test('iterator_apply')
+#3 %sbug64966.php(17): A->b()
+#4 {main}
+ thrown in %sbug64966.php on line 3
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index 02e84ee1e6..e86b3e7c58 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -2386,7 +2386,7 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
size_t res = nmemb;
unsigned long overflow = 0;
- __asm__ ("mull %3\n\taddl %4,%0\n\tadcl %1,%1"
+ __asm__ ("mull %3\n\taddl %4,%0\n\tadcl $0,%1"
: "=&a"(res), "=&d" (overflow)
: "%0"(res),
"rm"(size),
@@ -2406,7 +2406,7 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
size_t res = nmemb;
unsigned long overflow = 0;
- __asm__ ("mulq %3\n\taddq %4,%0\n\tadcq %1,%1"
+ __asm__ ("mulq %3\n\taddq %4,%0\n\tadcq $0,%1"
: "=&a"(res), "=&d" (overflow)
: "%0"(res),
"rm"(size),
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 97818895ef..687520d1a4 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -263,15 +263,13 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
if (EG(user_error_handler)) {
zeh = EG(user_error_handler);
EG(user_error_handler) = NULL;
- zval_dtor(zeh);
- FREE_ZVAL(zeh);
+ zval_ptr_dtor(&zeh);
}
if (EG(user_exception_handler)) {
zeh = EG(user_exception_handler);
EG(user_exception_handler) = NULL;
- zval_dtor(zeh);
- FREE_ZVAL(zeh);
+ zval_ptr_dtor(&zeh);
}
zend_stack_destroy(&EG(user_error_handlers_error_reporting));
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 02566f365d..d471f399e0 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -2327,6 +2327,8 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
}
+ } else if (RETURN_VALUE_USED(opline)) {
+ EX_T(opline->result.u.var).var.ptr = NULL;
}
} else if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
EX(original_return_value) = EG(return_value_ptr_ptr);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index f6220b0f53..993b822aa7 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -327,6 +327,8 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
}
+ } else if (RETURN_VALUE_USED(opline)) {
+ EX_T(opline->result.u.var).var.ptr = NULL;
}
} else if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
EX(original_return_value) = EG(return_value_ptr_ptr);
diff --git a/configure.in b/configure.in
index 0d9eff8339..8a0aa45a9d 100644
--- a/configure.in
+++ b/configure.in
@@ -41,7 +41,7 @@ AC_CONFIG_HEADER(main/php_config.h)
PHP_MAJOR_VERSION=5
PHP_MINOR_VERSION=3
-PHP_RELEASE_VERSION=27
+PHP_RELEASE_VERSION=28
PHP_EXTRA_VERSION="-dev"
PHP_VERSION="$PHP_MAJOR_VERSION.$PHP_MINOR_VERSION.$PHP_RELEASE_VERSION$PHP_EXTRA_VERSION"
PHP_VERSION_ID=`expr [$]PHP_MAJOR_VERSION \* 10000 + [$]PHP_MINOR_VERSION \* 100 + [$]PHP_RELEASE_VERSION`
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index e27be7d81e..75bdf33121 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -39,6 +39,20 @@ static __inline __int64_t php_date_llabs( __int64_t i ) { return i >= 0 ? i : -i
static inline long long php_date_llabs( long long i ) { return i >= 0 ? i : -i; }
#endif
+#ifdef PHP_WIN32
+#define DATE_I64_BUF_LEN 65
+# define DATE_I64A(i, s, len) _i64toa_s(i, s, len, 10)
+# define DATE_A64I(i, s) i = _atoi64(s)
+#else
+#define DATE_I64_BUF_LEN 65
+# define DATE_I64A(i, s, len) \
+ do { \
+ int st = snprintf(s, len, "%lld", i); \
+ s[st] = '\0'; \
+ } while (0);
+# define DATE_A64I(i, s) i = atoll(s)
+#endif
+
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_date, 0, 0, 1)
ZEND_ARG_INFO(0, format)
@@ -472,6 +486,8 @@ const zend_function_entry date_funcs_interval[] = {
const zend_function_entry date_funcs_period[] = {
PHP_ME(DatePeriod, __construct, arginfo_date_period_construct, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
+ PHP_ME(DatePeriod, __wakeup, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(DatePeriod, __set_state, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_FE_END
};
@@ -565,9 +581,12 @@ static zend_object_value date_object_clone_period(zval *this_ptr TSRMLS_DC);
static int date_object_compare_date(zval *d1, zval *d2 TSRMLS_DC);
static HashTable *date_object_get_properties(zval *object TSRMLS_DC);
static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC);
+static HashTable *date_object_get_properties_period(zval *object TSRMLS_DC);
zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC);
void date_interval_write_property(zval *object, zval *member, zval *value TSRMLS_DC);
+static zval *date_period_read_property(zval *object, zval *member, int type TSRMLS_DC);
+static void date_period_write_property(zval *object, zval *member, zval *value TSRMLS_DC);
/* {{{ Module struct */
zend_module_entry date_module_entry = {
@@ -2015,6 +2034,10 @@ static void date_register_classes(TSRMLS_D)
zend_class_implements(date_ce_period TSRMLS_CC, 1, zend_ce_traversable);
memcpy(&date_object_handlers_period, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
date_object_handlers_period.clone_obj = date_object_clone_period;
+ date_object_handlers_period.get_properties = date_object_get_properties_period;
+ date_object_handlers_period.get_property_ptr_ptr = NULL;
+ date_object_handlers_period.read_property = date_period_read_property;
+ date_object_handlers_period.write_property = date_period_write_property;
#define REGISTER_PERIOD_CLASS_CONST_STRING(const_name, value) \
zend_declare_class_constant_long(date_ce_period, const_name, sizeof(const_name)-1, value TSRMLS_CC);
@@ -2250,7 +2273,6 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC)
zval *zv;
php_interval_obj *intervalobj;
-
intervalobj = (php_interval_obj *) zend_object_store_get_object(object TSRMLS_CC);
props = zend_std_get_properties(object TSRMLS_CC);
@@ -2261,7 +2283,7 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC)
#define PHP_DATE_INTERVAL_ADD_PROPERTY(n,f) \
MAKE_STD_ZVAL(zv); \
- ZVAL_LONG(zv, intervalobj->diff->f); \
+ ZVAL_LONG(zv, (long)intervalobj->diff->f); \
zend_hash_update(props, n, strlen(n) + 1, &zv, sizeof(zval), NULL);
PHP_DATE_INTERVAL_ADD_PROPERTY("y", y);
@@ -2270,6 +2292,9 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC)
PHP_DATE_INTERVAL_ADD_PROPERTY("h", h);
PHP_DATE_INTERVAL_ADD_PROPERTY("i", i);
PHP_DATE_INTERVAL_ADD_PROPERTY("s", s);
+ PHP_DATE_INTERVAL_ADD_PROPERTY("weekday", weekday);
+ PHP_DATE_INTERVAL_ADD_PROPERTY("weekday_behavior", weekday_behavior);
+ PHP_DATE_INTERVAL_ADD_PROPERTY("first_last_day_of", first_last_day_of);
PHP_DATE_INTERVAL_ADD_PROPERTY("invert", invert);
if (intervalobj->diff->days != -99999) {
PHP_DATE_INTERVAL_ADD_PROPERTY("days", days);
@@ -2278,6 +2303,10 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC)
ZVAL_FALSE(zv);
zend_hash_update(props, "days", 5, &zv, sizeof(zval), NULL);
}
+ PHP_DATE_INTERVAL_ADD_PROPERTY("special_type", special.type);
+ PHP_DATE_INTERVAL_ADD_PROPERTY("special_amount", special.amount);
+ PHP_DATE_INTERVAL_ADD_PROPERTY("have_weekday_relative", have_weekday_relative);
+ PHP_DATE_INTERVAL_ADD_PROPERTY("have_special_relative", have_special_relative);
return props;
}
@@ -2380,6 +2409,7 @@ PHPAPI zval *php_date_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC)
object_init_ex(object, pce);
Z_SET_REFCOUNT_P(object, 1);
Z_UNSET_ISREF_P(object);
+
return object;
}
@@ -3649,30 +3679,48 @@ PHP_METHOD(DateInterval, __construct)
}
/* }}} */
-static long php_date_long_from_hash_element(HashTable *myht, char *element, size_t size)
-{
- zval **z_arg = NULL;
-
- if (zend_hash_find(myht, element, size + 1, (void**) &z_arg) == SUCCESS) {
- convert_to_long(*z_arg);
- return Z_LVAL_PP(z_arg);
- } else {
- return -1;
- }
-}
static int php_date_interval_initialize_from_hash(zval **return_value, php_interval_obj **intobj, HashTable *myht TSRMLS_DC)
{
(*intobj)->diff = timelib_rel_time_ctor();
- (*intobj)->diff->y = php_date_long_from_hash_element(myht, "y", 1);
- (*intobj)->diff->m = php_date_long_from_hash_element(myht, "m", 1);
- (*intobj)->diff->d = php_date_long_from_hash_element(myht, "d", 1);
- (*intobj)->diff->h = php_date_long_from_hash_element(myht, "h", 1);
- (*intobj)->diff->i = php_date_long_from_hash_element(myht, "i", 1);
- (*intobj)->diff->s = php_date_long_from_hash_element(myht, "s", 1);
- (*intobj)->diff->invert = php_date_long_from_hash_element(myht, "invert", 6);
- (*intobj)->diff->days = php_date_long_from_hash_element(myht, "days", 4);
+#define PHP_DATE_INTERVAL_READ_PROPERTY(element, member, itype, def) \
+ do { \
+ zval **z_arg = NULL; \
+ if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \
+ convert_to_long(*z_arg); \
+ (*intobj)->diff->member = (itype)Z_LVAL_PP(z_arg); \
+ } else { \
+ (*intobj)->diff->member = (itype)def; \
+ } \
+ } while (0);
+
+#define PHP_DATE_INTERVAL_READ_PROPERTY_I64(element, member) \
+ do { \
+ zval **z_arg = NULL; \
+ if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \
+ convert_to_string(*z_arg); \
+ DATE_A64I((*intobj)->diff->member, Z_STRVAL_PP(z_arg)); \
+ } else { \
+ (*intobj)->diff->member = -1LL; \
+ } \
+ } while (0);
+
+ PHP_DATE_INTERVAL_READ_PROPERTY("y", y, timelib_sll, -1)
+ PHP_DATE_INTERVAL_READ_PROPERTY("m", m, timelib_sll, -1)
+ PHP_DATE_INTERVAL_READ_PROPERTY("d", d, timelib_sll, -1)
+ PHP_DATE_INTERVAL_READ_PROPERTY("h", h, timelib_sll, -1)
+ PHP_DATE_INTERVAL_READ_PROPERTY("i", i, timelib_sll, -1)
+ PHP_DATE_INTERVAL_READ_PROPERTY("s", s, timelib_sll, -1)
+ PHP_DATE_INTERVAL_READ_PROPERTY("weekday", weekday, int, -1)
+ PHP_DATE_INTERVAL_READ_PROPERTY("weekday_behavior", weekday_behavior, int, -1)
+ PHP_DATE_INTERVAL_READ_PROPERTY("first_last_day_of", first_last_day_of, int, -1)
+ PHP_DATE_INTERVAL_READ_PROPERTY("invert", invert, int, 0);
+ PHP_DATE_INTERVAL_READ_PROPERTY_I64("days", days);
+ PHP_DATE_INTERVAL_READ_PROPERTY("special_type", special.type, unsigned int, 0);
+ PHP_DATE_INTERVAL_READ_PROPERTY_I64("special_amount", special.amount);
+ PHP_DATE_INTERVAL_READ_PROPERTY("have_weekday_relative", have_weekday_relative, unsigned int, 0);
+ PHP_DATE_INTERVAL_READ_PROPERTY("have_special_relative", have_special_relative, unsigned int, 0);
(*intobj)->initialized = 1;
return 0;
@@ -4276,6 +4324,223 @@ PHP_FUNCTION(date_sun_info)
timelib_time_dtor(t2);
}
/* }}} */
+
+
+static HashTable *date_object_get_properties_period(zval *object TSRMLS_DC)
+{
+ HashTable *props;
+ zval *zv;
+ php_period_obj *period_obj;
+
+ period_obj = zend_object_store_get_object(object TSRMLS_CC);
+
+ props = zend_std_get_properties(object TSRMLS_CC);
+
+ if (!period_obj->start) {
+ return props;
+ }
+
+ MAKE_STD_ZVAL(zv);
+ if (period_obj->start) {
+ php_date_obj *date_obj;
+ object_init_ex(zv, date_ce_date);
+ date_obj = zend_object_store_get_object(zv TSRMLS_CC);
+ date_obj->time = timelib_time_clone(period_obj->start);
+ } else {
+ ZVAL_NULL(zv);
+ }
+ zend_hash_update(props, "start", sizeof("start"), &zv, sizeof(zv), NULL);
+
+ MAKE_STD_ZVAL(zv);
+ if (period_obj->current) {
+ php_date_obj *date_obj;
+ object_init_ex(zv, date_ce_date);
+ date_obj = zend_object_store_get_object(zv TSRMLS_CC);
+ date_obj->time = timelib_time_clone(period_obj->current);
+ } else {
+ ZVAL_NULL(zv);
+ }
+ zend_hash_update(props, "current", sizeof("current"), &zv, sizeof(zv), NULL);
+
+ MAKE_STD_ZVAL(zv);
+ if (period_obj->end) {
+ php_date_obj *date_obj;
+ object_init_ex(zv, date_ce_date);
+ date_obj = zend_object_store_get_object(zv TSRMLS_CC);
+ date_obj->time = timelib_time_clone(period_obj->end);
+ } else {
+ ZVAL_NULL(zv);
+ }
+ zend_hash_update(props, "end", sizeof("end"), &zv, sizeof(zv), NULL);
+
+ MAKE_STD_ZVAL(zv);
+ if (period_obj->interval) {
+ php_interval_obj *interval_obj;
+ object_init_ex(zv, date_ce_interval);
+ interval_obj = zend_object_store_get_object(zv TSRMLS_CC);
+ interval_obj->diff = timelib_rel_time_clone(period_obj->interval);
+ interval_obj->initialized = 1;
+ } else {
+ ZVAL_NULL(zv);
+ }
+ zend_hash_update(props, "interval", sizeof("interval"), &zv, sizeof(zv), NULL);
+
+ /* converted to larger type (int->long); must check when unserializing */
+ MAKE_STD_ZVAL(zv);
+ ZVAL_LONG(zv, (long) period_obj->recurrences);
+ zend_hash_update(props, "recurrences", sizeof("recurrences"), &zv, sizeof(zv), NULL);
+
+ MAKE_STD_ZVAL(zv);
+ ZVAL_BOOL(zv, period_obj->include_start_date);
+ zend_hash_update(props, "include_start_date", sizeof("include_start_date"), &zv, sizeof(zv), NULL);
+
+ return props;
+}
+
+static int php_date_period_initialize_from_hash(php_period_obj *period_obj, HashTable *myht TSRMLS_DC)
+{
+ zval **ht_entry;
+
+ /* this function does no rollback on error */
+
+ if (zend_hash_find(myht, "start", sizeof("start"), (void**) &ht_entry) == SUCCESS) {
+ if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_date) {
+ php_date_obj *date_obj;
+ date_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC);
+ period_obj->start = timelib_time_clone(date_obj->time);
+ } else if (Z_TYPE_PP(ht_entry) != IS_NULL) {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ if (zend_hash_find(myht, "end", sizeof("end"), (void**) &ht_entry) == SUCCESS) {
+ if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_date) {
+ php_date_obj *date_obj;
+ date_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC);
+ period_obj->end = timelib_time_clone(date_obj->time);
+ } else if (Z_TYPE_PP(ht_entry) != IS_NULL) {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ if (zend_hash_find(myht, "current", sizeof("current"), (void**) &ht_entry) == SUCCESS) {
+ if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_date) {
+ php_date_obj *date_obj;
+ date_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC);
+ period_obj->current = timelib_time_clone(date_obj->time);
+ } else if (Z_TYPE_PP(ht_entry) != IS_NULL) {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ if (zend_hash_find(myht, "interval", sizeof("interval"), (void**) &ht_entry) == SUCCESS) {
+ if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_interval) {
+ php_interval_obj *interval_obj;
+ interval_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC);
+ period_obj->interval = timelib_rel_time_clone(interval_obj->diff);
+ } else { /* interval is required */
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ if (zend_hash_find(myht, "recurrences", sizeof("recurrences"), (void**) &ht_entry) == SUCCESS &&
+ Z_TYPE_PP(ht_entry) == IS_LONG && Z_LVAL_PP(ht_entry) >= 0 && Z_LVAL_PP(ht_entry) <= INT_MAX) {
+ period_obj->recurrences = Z_LVAL_PP(ht_entry);
+ } else {
+ return 0;
+ }
+
+ if (zend_hash_find(myht, "include_start_date", sizeof("include_start_date"), (void**) &ht_entry) == SUCCESS &&
+ Z_TYPE_PP(ht_entry) == IS_BOOL) {
+ period_obj->include_start_date = Z_BVAL_PP(ht_entry);
+ } else {
+ return 0;
+ }
+
+ period_obj->initialized = 1;
+
+ return 1;
+}
+
+/* {{{ proto DatePeriod::__set_state()
+*/
+PHP_METHOD(DatePeriod, __set_state)
+{
+ php_period_obj *period_obj;
+ zval *array;
+ HashTable *myht;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ myht = Z_ARRVAL_P(array);
+
+ object_init_ex(return_value, date_ce_period);
+ period_obj = zend_object_store_get_object(return_value TSRMLS_CC);
+ if (!php_date_period_initialize_from_hash(period_obj, myht TSRMLS_CC)) {
+ php_error(E_ERROR, "Invalid serialization data for DatePeriod object");
+ }
+}
+/* }}} */
+
+/* {{{ proto DatePeriod::__wakeup()
+*/
+PHP_METHOD(DatePeriod, __wakeup)
+{
+ zval *object = getThis();
+ php_period_obj *period_obj;
+ HashTable *myht;
+
+ period_obj = zend_object_store_get_object(object TSRMLS_CC);
+
+ myht = Z_OBJPROP_P(object);
+
+ if (!php_date_period_initialize_from_hash(period_obj, myht TSRMLS_CC)) {
+ php_error(E_ERROR, "Invalid serialization data for DatePeriod object");
+ }
+}
+/* }}} */
+
+/* {{{ date_period_read_property */
+static zval *date_period_read_property(zval *object, zval *member, int type TSRMLS_DC)
+{
+ zval *zv;
+ if (type != BP_VAR_IS && type != BP_VAR_R) {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Retrieval of DatePeriod properties for modification is unsupported");
+ }
+
+ Z_OBJPROP_P(object); /* build properties hash table */
+
+ zv = std_object_handlers.read_property(object, member, type TSRMLS_CC);
+ if (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJ_HANDLER_P(zv, clone_obj)) {
+ /* defensive copy */
+ zend_object_value zov = Z_OBJ_HANDLER_P(zv, clone_obj)(zv TSRMLS_CC);
+ MAKE_STD_ZVAL(zv);
+ Z_TYPE_P(zv) = IS_OBJECT;
+ Z_OBJVAL_P(zv) = zov;
+ }
+
+ return zv;
+}
+/* }}} */
+
+/* {{{ date_period_write_property */
+static void date_period_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
+{
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Writing to DatePeriod properties is unsupported");
+}
+/* }}} */
+
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/date/php_date.h b/ext/date/php_date.h
index a86d6c7e70..16837df2a9 100644
--- a/ext/date/php_date.h
+++ b/ext/date/php_date.h
@@ -88,6 +88,8 @@ PHP_FUNCTION(date_interval_format);
PHP_FUNCTION(date_interval_create_from_date_string);
PHP_METHOD(DatePeriod, __construct);
+PHP_METHOD(DatePeriod, __wakeup);
+PHP_METHOD(DatePeriod, __set_state);
/* Options and Configuration */
PHP_FUNCTION(date_default_timezone_set);
diff --git a/ext/date/tests/bug45682.phpt b/ext/date/tests/bug45682.phpt
index d8bbfc5a04..ea8fa94706 100644
--- a/ext/date/tests/bug45682.phpt
+++ b/ext/date/tests/bug45682.phpt
@@ -11,8 +11,8 @@ $other = new DateTime("31-July-2008");
$diff = date_diff($date, $other);
var_dump($diff);
---EXPECT--
-object(DateInterval)#3 (8) {
+--EXPECTF--
+object(DateInterval)#%d (15) {
["y"]=>
int(0)
["m"]=>
@@ -25,8 +25,22 @@ object(DateInterval)#3 (8) {
int(0)
["s"]=>
int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
["invert"]=>
int(0)
["days"]=>
int(3)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
}
diff --git a/ext/date/tests/bug48678.phpt b/ext/date/tests/bug48678.phpt
index e2cb724f76..253cb84ce6 100644
--- a/ext/date/tests/bug48678.phpt
+++ b/ext/date/tests/bug48678.phpt
@@ -15,8 +15,15 @@ DateInterval Object
[h] => 12
[i] => 30
[s] => 5
+ [weekday] => 0
+ [weekday_behavior] => 0
+ [first_last_day_of] => 0
[invert] => 0
- [days] =>%s
+ [days] =>
+ [special_type] => 0
+ [special_amount] => 0
+ [have_weekday_relative] => 0
+ [have_special_relative] => 0
)
DateInterval Object
(
@@ -26,6 +33,13 @@ DateInterval Object
[h] => 12
[i] => 30
[s] => 5
+ [weekday] => 0
+ [weekday_behavior] => 0
+ [first_last_day_of] => 0
[invert] => 0
- [days] =>%s
+ [days] => 0
+ [special_type] => 0
+ [special_amount] => 0
+ [have_weekday_relative] => 0
+ [have_special_relative] => 0
)
diff --git a/ext/date/tests/bug49081.phpt b/ext/date/tests/bug49081.phpt
index f4f02903d1..31f7351481 100644
--- a/ext/date/tests/bug49081.phpt
+++ b/ext/date/tests/bug49081.phpt
@@ -17,6 +17,13 @@ DateInterval Object
[h] => 4
[i] => 0
[s] => 0
+ [weekday] => 0
+ [weekday_behavior] => 0
+ [first_last_day_of] => 0
[invert] => 0
[days] => 30
+ [special_type] => 0
+ [special_amount] => 0
+ [have_weekday_relative] => 0
+ [have_special_relative] => 0
)
diff --git a/ext/date/tests/bug49778.phpt b/ext/date/tests/bug49778.phpt
index 67c8e27f91..2062d69168 100644
--- a/ext/date/tests/bug49778.phpt
+++ b/ext/date/tests/bug49778.phpt
@@ -8,7 +8,7 @@ echo $i->format("%d"), "\n";
echo $i->format("%a"), "\n";
?>
--EXPECT--
-object(DateInterval)#1 (8) {
+object(DateInterval)#1 (15) {
["y"]=>
int(0)
["m"]=>
@@ -21,10 +21,24 @@ object(DateInterval)#1 (8) {
int(0)
["s"]=>
int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
["invert"]=>
int(0)
["days"]=>
bool(false)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
}
7
(unknown)
diff --git a/ext/date/tests/bug52113.phpt b/ext/date/tests/bug52113.phpt
index a7d9339d13..f4730c6a44 100644
--- a/ext/date/tests/bug52113.phpt
+++ b/ext/date/tests/bug52113.phpt
@@ -32,7 +32,7 @@ var_dump($unser, $p);
?>
--EXPECT--
-object(DateInterval)#3 (8) {
+object(DateInterval)#3 (15) {
["y"]=>
int(0)
["m"]=>
@@ -45,12 +45,26 @@ object(DateInterval)#3 (8) {
int(0)
["s"]=>
int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
["invert"]=>
int(0)
["days"]=>
int(0)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
}
-string(128) "O:12:"DateInterval":8:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:0;s:1:"h";i:4;s:1:"i";i:0;s:1:"s";i:0;s:6:"invert";i:0;s:4:"days";i:0;}"
+string(320) "O:12:"DateInterval":15:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:0;s:1:"h";i:4;s:1:"i";i:0;s:1:"s";i:0;s:7:"weekday";i:0;s:16:"weekday_behavior";i:0;s:17:"first_last_day_of";i:0;s:6:"invert";i:0;s:4:"days";i:0;s:12:"special_type";i:0;s:14:"special_amount";i:0;s:21:"have_weekday_relative";i:0;s:21:"have_special_relative";i:0;}"
DateInterval::__set_state(array(
'y' => 0,
'm' => 0,
@@ -58,9 +72,16 @@ DateInterval::__set_state(array(
'h' => 4,
'i' => 0,
's' => 0,
+ 'weekday' => 0,
+ 'weekday_behavior' => 0,
+ 'first_last_day_of' => 0,
'invert' => 0,
'days' => 0,
-))object(DateInterval)#5 (8) {
+ 'special_type' => 0,
+ 'special_amount' => 0,
+ 'have_weekday_relative' => 0,
+ 'have_special_relative' => 0,
+))object(DateInterval)#5 (15) {
["y"]=>
int(0)
["m"]=>
@@ -73,14 +94,78 @@ DateInterval::__set_state(array(
int(0)
["s"]=>
int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
["invert"]=>
int(0)
["days"]=>
int(0)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
}
-object(DatePeriod)#6 (0) {
+object(DatePeriod)#6 (6) {
+ ["start"]=>
+ object(DateTime)#4 (3) {
+ ["date"]=>
+ string(19) "2003-01-02 08:00:00"
+ ["timezone_type"]=>
+ int(3)
+ ["timezone"]=>
+ string(3) "UTC"
+ }
+ ["current"]=>
+ NULL
+ ["end"]=>
+ NULL
+ ["interval"]=>
+ object(DateInterval)#7 (15) {
+ ["y"]=>
+ int(0)
+ ["m"]=>
+ int(0)
+ ["d"]=>
+ int(0)
+ ["h"]=>
+ int(4)
+ ["i"]=>
+ int(0)
+ ["s"]=>
+ int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
+ ["invert"]=>
+ int(0)
+ ["days"]=>
+ int(0)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
+ }
+ ["recurrences"]=>
+ int(3)
+ ["include_start_date"]=>
+ bool(true)
}
-object(DateInterval)#4 (8) {
+object(DateInterval)#8 (15) {
["y"]=>
int(7)
["m"]=>
@@ -93,10 +178,74 @@ object(DateInterval)#4 (8) {
int(3)
["s"]=>
int(2)
+ ["weekday"]=>
+ int(-1)
+ ["weekday_behavior"]=>
+ int(-1)
+ ["first_last_day_of"]=>
+ int(-1)
["invert"]=>
int(1)
["days"]=>
int(2400)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(-1)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
}
-object(DatePeriod)#7 (0) {
+object(DatePeriod)#9 (6) {
+ ["start"]=>
+ object(DateTime)#6 (3) {
+ ["date"]=>
+ string(19) "2003-01-02 08:00:00"
+ ["timezone_type"]=>
+ int(3)
+ ["timezone"]=>
+ string(3) "UTC"
+ }
+ ["current"]=>
+ NULL
+ ["end"]=>
+ NULL
+ ["interval"]=>
+ object(DateInterval)#7 (15) {
+ ["y"]=>
+ int(0)
+ ["m"]=>
+ int(0)
+ ["d"]=>
+ int(0)
+ ["h"]=>
+ int(4)
+ ["i"]=>
+ int(0)
+ ["s"]=>
+ int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
+ ["invert"]=>
+ int(0)
+ ["days"]=>
+ int(0)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
+ }
+ ["recurrences"]=>
+ int(3)
+ ["include_start_date"]=>
+ bool(true)
}
diff --git a/ext/date/tests/bug52738.phpt b/ext/date/tests/bug52738.phpt
index fc1b6029e9..ea219f7c7c 100644
--- a/ext/date/tests/bug52738.phpt
+++ b/ext/date/tests/bug52738.phpt
@@ -27,6 +27,13 @@ di Object
[h] => 0
[i] => 0
[s] => 0
+ [weekday] => 0
+ [weekday_behavior] => 0
+ [first_last_day_of] => 0
[invert] => 0
[days] =>
+ [special_type] => 0
+ [special_amount] => 0
+ [have_weekday_relative] => 0
+ [have_special_relative] => 0
)
diff --git a/ext/date/tests/bug52808.phpt b/ext/date/tests/bug52808.phpt
index e031ac6ee3..1f0fc84cd7 100644
--- a/ext/date/tests/bug52808.phpt
+++ b/ext/date/tests/bug52808.phpt
@@ -25,7 +25,7 @@ foreach($intervals as $iv) {
echo "==DONE==\n";
?>
--EXPECTF--
-object(DateInterval)#%d (8) {
+object(DateInterval)#%d (15) {
["y"]=>
int(1)
["m"]=>
@@ -38,12 +38,26 @@ object(DateInterval)#%d (8) {
int(30)
["s"]=>
int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
["invert"]=>
int(1)
["days"]=>
int(437)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
}
-object(DateInterval)#%d (8) {
+object(DateInterval)#%d (15) {
["y"]=>
int(0)
["m"]=>
@@ -56,12 +70,26 @@ object(DateInterval)#%d (8) {
int(30)
["s"]=>
int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
["invert"]=>
int(0)
["days"]=>
int(294)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
}
-object(DateInterval)#%d (8) {
+object(DateInterval)#%d (15) {
["y"]=>
int(0)
["m"]=>
@@ -74,10 +102,24 @@ object(DateInterval)#%d (8) {
int(30)
["s"]=>
int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
["invert"]=>
int(0)
["days"]=>
int(294)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
}
DateInterval::__construct(): Failed to parse interval (2007-05-11T15:30:00Z/)
DateInterval::__construct(): Failed to parse interval (2007-05-11T15:30:00Z)
diff --git a/ext/date/tests/bug53437.phpt b/ext/date/tests/bug53437.phpt
index f089866538..2ea091453f 100644
--- a/ext/date/tests/bug53437.phpt
+++ b/ext/date/tests/bug53437.phpt
@@ -1,7 +1,5 @@
--TEST--
-Bug #53437 (Crash when using unserialized DatePeriod instance)
---XFAIL--
-Bug #53437 Not fixed yet
+Bug #53437 (Crash when using unserialized DatePeriod instance), variation 1
--FILE--
<?php
$dp = new DatePeriod(new DateTime('2010-01-01 UTC'), new DateInterval('P1D'), 2);
@@ -20,9 +18,137 @@ $dpu = unserialize($ser); // $dpu has invalid values???
var_dump($dpu);
echo "Unserialized:\r\n";
-// ???which leads to CRASH:
foreach($dpu as $dt) {
echo $dt->format('Y-m-d H:i:s')."\r\n";
}
?>
+==DONE==
--EXPECT--
+Original:
+2010-01-01 00:00:00
+2010-01-02 00:00:00
+2010-01-03 00:00:00
+
+object(DatePeriod)#1 (6) {
+ ["start"]=>
+ object(DateTime)#2 (3) {
+ ["date"]=>
+ string(19) "2010-01-01 00:00:00"
+ ["timezone_type"]=>
+ int(3)
+ ["timezone"]=>
+ string(3) "UTC"
+ }
+ ["current"]=>
+ object(DateTime)#4 (3) {
+ ["date"]=>
+ string(19) "2010-01-04 00:00:00"
+ ["timezone_type"]=>
+ int(3)
+ ["timezone"]=>
+ string(3) "UTC"
+ }
+ ["end"]=>
+ NULL
+ ["interval"]=>
+ object(DateInterval)#5 (15) {
+ ["y"]=>
+ int(0)
+ ["m"]=>
+ int(0)
+ ["d"]=>
+ int(1)
+ ["h"]=>
+ int(0)
+ ["i"]=>
+ int(0)
+ ["s"]=>
+ int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
+ ["invert"]=>
+ int(0)
+ ["days"]=>
+ bool(false)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
+ }
+ ["recurrences"]=>
+ int(3)
+ ["include_start_date"]=>
+ bool(true)
+}
+object(DatePeriod)#5 (6) {
+ ["start"]=>
+ object(DateTime)#10 (3) {
+ ["date"]=>
+ string(19) "2010-01-01 00:00:00"
+ ["timezone_type"]=>
+ int(3)
+ ["timezone"]=>
+ string(3) "UTC"
+ }
+ ["current"]=>
+ object(DateTime)#7 (3) {
+ ["date"]=>
+ string(19) "2010-01-04 00:00:00"
+ ["timezone_type"]=>
+ int(3)
+ ["timezone"]=>
+ string(3) "UTC"
+ }
+ ["end"]=>
+ NULL
+ ["interval"]=>
+ object(DateInterval)#8 (15) {
+ ["y"]=>
+ int(0)
+ ["m"]=>
+ int(0)
+ ["d"]=>
+ int(1)
+ ["h"]=>
+ int(0)
+ ["i"]=>
+ int(0)
+ ["s"]=>
+ int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
+ ["invert"]=>
+ int(0)
+ ["days"]=>
+ int(0)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
+ }
+ ["recurrences"]=>
+ int(3)
+ ["include_start_date"]=>
+ bool(true)
+}
+Unserialized:
+2010-01-01 00:00:00
+2010-01-02 00:00:00
+2010-01-03 00:00:00
+==DONE==
diff --git a/ext/date/tests/bug53437_var1.phpt b/ext/date/tests/bug53437_var1.phpt
new file mode 100644
index 0000000000..f1f9843d5e
--- /dev/null
+++ b/ext/date/tests/bug53437_var1.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Bug #53437 (Crash when using unserialized DatePeriod instance), variation 2
+--FILE--
+<?php
+$s = 'O:10:"DatePeriod":0:{}';
+
+$dp = unserialize($s);
+
+var_dump($dp);
+?>
+==DONE==
+--EXPECTF--
+Fatal error: Invalid serialization data for DatePeriod object in %sbug53437_var1.php on line %d
diff --git a/ext/date/tests/bug53437_var2.phpt b/ext/date/tests/bug53437_var2.phpt
new file mode 100644
index 0000000000..50aebda57c
--- /dev/null
+++ b/ext/date/tests/bug53437_var2.phpt
@@ -0,0 +1,80 @@
+--TEST--
+Bug #53437 DateInterval basic serialization
+--FILE--
+<?php
+$di0 = new DateInterval('P2Y4DT6H8M');
+
+$s = serialize($di0);
+
+$di1 = unserialize($s);
+
+var_dump($di0, $di1);
+
+?>
+==DONE==
+--EXPECT--
+object(DateInterval)#1 (15) {
+ ["y"]=>
+ int(2)
+ ["m"]=>
+ int(0)
+ ["d"]=>
+ int(4)
+ ["h"]=>
+ int(6)
+ ["i"]=>
+ int(8)
+ ["s"]=>
+ int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
+ ["invert"]=>
+ int(0)
+ ["days"]=>
+ bool(false)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
+}
+object(DateInterval)#2 (15) {
+ ["y"]=>
+ int(2)
+ ["m"]=>
+ int(0)
+ ["d"]=>
+ int(4)
+ ["h"]=>
+ int(6)
+ ["i"]=>
+ int(8)
+ ["s"]=>
+ int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
+ ["invert"]=>
+ int(0)
+ ["days"]=>
+ int(0)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
+}
+==DONE==
diff --git a/ext/date/tests/bug53437_var3.phpt b/ext/date/tests/bug53437_var3.phpt
new file mode 100644
index 0000000000..82b90f559b
--- /dev/null
+++ b/ext/date/tests/bug53437_var3.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Bug #53437 DateInterval unserialize bad data, 32 bit
+--SKIPIF--
+<?php if (PHP_INT_SIZE != 4) { die('skip 32 bit only'); } ?>
+--FILE--
+<?php
+$s = 'O:12:"DateInterval":15:{s:1:"y";s:1:"2";s:1:"m";s:1:"0";s:1:"d";s:3:"bla";s:1:"h";s:1:"6";s:1:"i";s:1:"8";s:1:"s";s:1:"0";s:7:"weekday";i:10;s:16:"weekday_behavior";i:10;s:17:"first_last_day_of";i:0;s:6:"invert";i:0;s:4:"days";s:4:"aoeu";s:12:"special_type";i:0;s:14:"special_amount";s:21:"234523452345234532455";s:21:"have_weekday_relative";i:21474836489;s:21:"have_special_relative";s:3:"bla";}';
+
+$di = unserialize($s);
+var_dump($di);
+
+?>
+==DONE==
+--EXPECTF--
+object(DateInterval)#%d (15) {
+ ["y"]=>
+ int(2)
+ ["m"]=>
+ int(0)
+ ["d"]=>
+ int(0)
+ ["h"]=>
+ int(6)
+ ["i"]=>
+ int(8)
+ ["s"]=>
+ int(0)
+ ["weekday"]=>
+ int(10)
+ ["weekday_behavior"]=>
+ int(10)
+ ["first_last_day_of"]=>
+ int(0)
+ ["invert"]=>
+ int(0)
+ ["days"]=>
+ int(0)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(-1)
+ ["have_weekday_relative"]=>
+ int(9)
+ ["have_special_relative"]=>
+ int(0)
+}
+==DONE==
diff --git a/ext/date/tests/bug53437_var4.phpt b/ext/date/tests/bug53437_var4.phpt
new file mode 100644
index 0000000000..88fd81c9db
--- /dev/null
+++ b/ext/date/tests/bug53437_var4.phpt
@@ -0,0 +1,64 @@
+--TEST--
+Bug #53437 (Check that var_dump out is the same using the whole object or it's single properties), variation 4
+--INI--
+date.timezone = Europe/Berlin
+--FILE--
+<?php
+$dt = new DateTime('2009-10-11');
+
+$df = $dt->diff(new DateTime('2009-10-13'));
+
+var_dump($df,
+ $df->y,
+ $df->m,
+ $df->d,
+ $df->h,
+ $df->i,
+ $df->s,
+ $df->invert,
+ $df->days);
+
+?>
+==DONE==
+--EXPECTF--
+object(DateInterval)#%d (15) {
+ ["y"]=>
+ int(0)
+ ["m"]=>
+ int(0)
+ ["d"]=>
+ int(2)
+ ["h"]=>
+ int(0)
+ ["i"]=>
+ int(0)
+ ["s"]=>
+ int(0)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
+ ["invert"]=>
+ int(0)
+ ["days"]=>
+ int(2)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
+}
+int(0)
+int(0)
+int(2)
+int(0)
+int(0)
+int(0)
+int(0)
+int(2)
+==DONE==
diff --git a/ext/date/tests/bug53437_var5.phpt b/ext/date/tests/bug53437_var5.phpt
new file mode 100644
index 0000000000..e95fcdae96
--- /dev/null
+++ b/ext/date/tests/bug53437_var5.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Bug #53437 DateInterval unserialize bad data, 64 bit
+--SKIPIF--
+<?php if (PHP_INT_SIZE != 8) { die('skip true 64 bit only'); } ?>
+--FILE--
+<?php
+$s = 'O:12:"DateInterval":15:{s:1:"y";s:1:"2";s:1:"m";s:1:"0";s:1:"d";s:3:"bla";s:1:"h";s:1:"6";s:1:"i";s:1:"8";s:1:"s";s:1:"0";s:7:"weekday";i:10;s:16:"weekday_behavior";i:10;s:17:"first_last_day_of";i:0;s:6:"invert";i:0;s:4:"days";s:4:"aoeu";s:12:"special_type";i:0;s:14:"special_amount";s:21:"234523452345234532455";s:21:"have_weekday_relative";i:21474836489;s:21:"have_special_relative";s:3:"bla";}';
+
+$di = unserialize($s);
+var_dump($di);
+
+?>
+==DONE==
+--EXPECTF--
+object(DateInterval)#%d (15) {
+ ["y"]=>
+ int(2)
+ ["m"]=>
+ int(0)
+ ["d"]=>
+ int(0)
+ ["h"]=>
+ int(6)
+ ["i"]=>
+ int(8)
+ ["s"]=>
+ int(0)
+ ["weekday"]=>
+ int(10)
+ ["weekday_behavior"]=>
+ int(10)
+ ["first_last_day_of"]=>
+ int(0)
+ ["invert"]=>
+ int(0)
+ ["days"]=>
+ int(0)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(9223372036854775807)
+ ["have_weekday_relative"]=>
+ int(9)
+ ["have_special_relative"]=>
+ int(0)
+}
+==DONE==
diff --git a/ext/date/tests/date_diff1.phpt b/ext/date/tests/date_diff1.phpt
index cf32fcbf3b..a908cdba75 100644
--- a/ext/date/tests/date_diff1.phpt
+++ b/ext/date/tests/date_diff1.phpt
@@ -28,7 +28,7 @@ object(DateTime)#2 (3) {
["timezone"]=>
string(3) "EDT"
}
-object(DateInterval)#3 (8) {
+object(DateInterval)#3 (15) {
["y"]=>
int(0)
["m"]=>
@@ -41,8 +41,22 @@ object(DateInterval)#3 (8) {
int(19)
["s"]=>
int(40)
+ ["weekday"]=>
+ int(0)
+ ["weekday_behavior"]=>
+ int(0)
+ ["first_last_day_of"]=>
+ int(0)
["invert"]=>
int(0)
["days"]=>
int(33)
+ ["special_type"]=>
+ int(0)
+ ["special_amount"]=>
+ int(0)
+ ["have_weekday_relative"]=>
+ int(0)
+ ["have_special_relative"]=>
+ int(0)
}
diff --git a/ext/pdo_pgsql/tests/copy_from.phpt b/ext/pdo_pgsql/tests/copy_from.phpt
index 2858905d0c..10967b0fe9 100644
--- a/ext/pdo_pgsql/tests/copy_from.phpt
+++ b/ext/pdo_pgsql/tests/copy_from.phpt
@@ -110,8 +110,10 @@ $db->rollback();
echo "Exception! at line ", $e->getLine(), "\n";
var_dump($e->getMessage());
}
-if(isset($filename)) {
- @unlink($filename);
+
+// Clean up
+foreach (array($filename, $filenameWithDifferentNullValues, $filenameWithDifferentNullValuesAndSelectedFields) as $f) {
+ @unlink($f);
}
?>
--EXPECT--
@@ -383,4 +385,4 @@ array(6) {
NULL
}
Testing pgsqlCopyFromFile() with error
-bool(false) \ No newline at end of file
+bool(false)
diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
index a0faed1424..c5d9a4ab1c 100644
--- a/ext/pgsql/pgsql.c
+++ b/ext/pgsql/pgsql.c
@@ -4875,7 +4875,7 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z
}
smart_str_appends(&querystr,
- "SELECT a.attname, a.attnum, t.typname, a.attlen, a.attnotNULL, a.atthasdef, a.attndims "
+ "SELECT a.attname, a.attnum, t.typname, a.attlen, a.attnotnull, a.atthasdef, a.attndims, t.typtype = 'e' "
"FROM pg_class as c, pg_attribute a, pg_type t, pg_namespace n "
"WHERE a.attnum > 0 AND a.attrelid = c.oid AND c.relname = '");
tmp_name2 = php_addslashes(tmp_name2, strlen(tmp_name2), &new_len, 0 TSRMLS_CC);
@@ -4921,6 +4921,12 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z
add_assoc_bool(elem, "has default", 0);
}
add_assoc_long(elem, "array dims", atoi(PQgetvalue(pg_result,i,6)));
+ if (!strcmp(PQgetvalue(pg_result,i,7), "t")) {
+ add_assoc_bool(elem, "is enum", 1);
+ }
+ else {
+ add_assoc_bool(elem, "is enum", 0);
+ }
name = PQgetvalue(pg_result,i,0);
add_assoc_zval(meta, name, elem);
}
@@ -4954,7 +4960,18 @@ PHP_FUNCTION(pg_meta_data)
zval_dtor(return_value); /* destroy array */
RETURN_FALSE;
}
-}
+ else {
+ HashPosition pos;
+ zval **val;
+
+ for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(return_value), &pos);
+ zend_hash_get_current_data_ex(Z_ARRVAL_P(return_value), (void **)&val, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(Z_ARRVAL_P(return_value), &pos)) {
+ /* delete newly added entry, in order to keep BC */
+ zend_hash_del_key_or_index(Z_ARRVAL_PP(val), "is enum", sizeof("is enum"), 0, HASH_DEL_KEY);
+ }
+ }
+}
/* }}} */
/* {{{ php_pgsql_get_data_type
@@ -5136,8 +5153,9 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con
char *field = NULL;
uint field_len = -1;
ulong num_idx = -1;
- zval *meta, **def, **type, **not_null, **has_default, **val, *new_val;
+ zval *meta, **def, **type, **not_null, **has_default, **is_enum, **val, *new_val;
int new_len, key_type, err = 0, skip_field;
+ php_pgsql_data_type data_type;
assert(pg_link != NULL);
assert(Z_TYPE_P(values) == IS_ARRAY);
@@ -5188,17 +5206,30 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'has default'");
err = 1;
}
+ if (!err && zend_hash_find(Z_ARRVAL_PP(def), "is enum", sizeof("is enum"), (void **)&is_enum) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'is enum'");
+ err = 1;
+ }
if (!err && (Z_TYPE_PP(val) == IS_ARRAY ||
Z_TYPE_PP(val) == IS_OBJECT ||
Z_TYPE_PP(val) == IS_CONSTANT_ARRAY)) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scaler values as field values");
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scalar values as field values");
err = 1;
}
if (err) {
break; /* break out for() */
}
ALLOC_INIT_ZVAL(new_val);
- switch(php_pgsql_get_data_type(Z_STRVAL_PP(type), Z_STRLEN_PP(type)))
+
+ if (Z_BVAL_PP(is_enum)) {
+ /* enums need to be treated like strings */
+ data_type = PG_TEXT;
+ }
+ else {
+ data_type = php_pgsql_get_data_type(Z_STRVAL_PP(type), Z_STRLEN_PP(type));
+ }
+
+ switch(data_type)
{
case PG_BOOL:
switch (Z_TYPE_PP(val)) {
diff --git a/ext/pgsql/tests/10pg_convert_85.phpt b/ext/pgsql/tests/10pg_convert_85.phpt
index 4f1c92bf1a..8b1cc8f538 100644
--- a/ext/pgsql/tests/10pg_convert_85.phpt
+++ b/ext/pgsql/tests/10pg_convert_85.phpt
@@ -12,6 +12,7 @@ error_reporting(E_ALL);
include 'config.inc';
$db = pg_connect($conn_str);
+pg_query($db, "SET standard_conforming_strings = 0");
$fields = array('num'=>'1234', 'str'=>'AAA', 'bin'=>'BBB');
$converted = pg_convert($db, $table_name, $fields);
diff --git a/ext/pgsql/tests/12pg_insert_85.phpt b/ext/pgsql/tests/12pg_insert_85.phpt
index a85dea0363..5fbbe4b7af 100644
--- a/ext/pgsql/tests/12pg_insert_85.phpt
+++ b/ext/pgsql/tests/12pg_insert_85.phpt
@@ -12,6 +12,8 @@ error_reporting(E_ALL);
include 'config.inc';
$db = pg_connect($conn_str);
+pg_query($db, "SET standard_conforming_strings = 0");
+
$fields = array('num'=>'1234', 'str'=>'AAA', 'bin'=>'BBB');
pg_insert($db, $table_name, $fields) or print "Error in test 1\n";
diff --git a/ext/pgsql/tests/14pg_update_85.phpt b/ext/pgsql/tests/14pg_update_85.phpt
index f1c77eac1d..06ca8c3de9 100644
--- a/ext/pgsql/tests/14pg_update_85.phpt
+++ b/ext/pgsql/tests/14pg_update_85.phpt
@@ -12,6 +12,8 @@ error_reporting(E_ALL);
include 'config.inc';
$db = pg_connect($conn_str);
+pg_query($db, "SET standard_conforming_strings = 0");
+
$fields = array('num'=>'1234', 'str'=>'ABC', 'bin'=>'XYZ');
$ids = array('num'=>'1234');
diff --git a/ext/pgsql/tests/18pg_escape_bytea.phpt b/ext/pgsql/tests/18pg_escape_bytea.phpt
index 43f98c4467..5f52a17d97 100644
--- a/ext/pgsql/tests/18pg_escape_bytea.phpt
+++ b/ext/pgsql/tests/18pg_escape_bytea.phpt
@@ -8,10 +8,11 @@ PostgreSQL pg_escape_bytea() functions
include('config.inc');
+$db = pg_connect($conn_str);
+
$image = file_get_contents(dirname(__FILE__) . '/php.gif');
$esc_image = pg_escape_bytea($image);
-$db = pg_connect($conn_str);
pg_query($db, 'INSERT INTO '.$table_name.' (num, bin) VALUES (9876, \''.$esc_image.'\');');
$result = pg_query($db, 'SELECT * FROM '.$table_name.' WHERE num = 9876');
$rows = pg_fetch_all($result);
diff --git a/ext/pgsql/tests/bug64609.phpt b/ext/pgsql/tests/bug64609.phpt
new file mode 100644
index 0000000000..0df63012da
--- /dev/null
+++ b/ext/pgsql/tests/bug64609.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #64609 (pg_convert enum type support)
+--SKIPIF--
+<?php
+include("skipif.inc");
+skip_server_version('8.3', '<');
+?>
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+include 'config.inc';
+
+$db = pg_connect($conn_str);
+pg_query("BEGIN");
+pg_query("CREATE TYPE t_enum AS ENUM ('ok', 'ko')");
+pg_query("CREATE TABLE test_enum (a t_enum)");
+
+$fields = array('a' => 'ok');
+$converted = pg_convert($db, 'test_enum', $fields);
+
+pg_query("ROLLBACK");
+
+var_dump($converted);
+?>
+--EXPECT--
+array(1) {
+ ["a"]=>
+ string(4) "'ok'"
+}
diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c
index 91f7c8eb7b..cd0af8fbc5 100644
--- a/ext/spl/spl_iterators.c
+++ b/ext/spl/spl_iterators.c
@@ -1025,12 +1025,12 @@ static void spl_recursive_tree_iterator_get_entry(spl_recursive_it_object * obje
zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling TSRMLS_CC);
if (data && *data) {
RETVAL_ZVAL(*data, 1, 0);
- }
- if (Z_TYPE_P(return_value) == IS_ARRAY) {
- zval_dtor(return_value);
- ZVAL_STRINGL(return_value, "Array", sizeof("Array")-1, 1);
- } else {
- convert_to_string(return_value);
+ if (Z_TYPE_P(return_value) == IS_ARRAY) {
+ zval_dtor(return_value);
+ ZVAL_STRINGL(return_value, "Array", sizeof("Array")-1, 1);
+ } else {
+ convert_to_string(return_value);
+ }
}
zend_restore_error_handling(&error_handling TSRMLS_CC);
}
@@ -1131,8 +1131,15 @@ SPL_METHOD(RecursiveTreeIterator, current)
}
}
+ INIT_ZVAL(prefix);
+ INIT_ZVAL(entry);
spl_recursive_tree_iterator_get_prefix(object, &prefix TSRMLS_CC);
spl_recursive_tree_iterator_get_entry(object, &entry TSRMLS_CC);
+ if (Z_TYPE(entry) != IS_STRING) {
+ zval_dtor(&prefix);
+ zval_dtor(&entry);
+ RETURN_NULL();
+ }
spl_recursive_tree_iterator_get_postfix(object, &postfix TSRMLS_CC);
str_len = Z_STRLEN(prefix) + Z_STRLEN(entry) + Z_STRLEN(postfix);
diff --git a/ext/standard/browscap.c b/ext/standard/browscap.c
index 60949fc352..343ad2051c 100644
--- a/ext/standard/browscap.c
+++ b/ext/standard/browscap.c
@@ -451,6 +451,19 @@ static int browser_reg_compare(zval **browser TSRMLS_DC, int num_args, va_list a
}
/* }}} */
+static void browscap_zval_copy_ctor(zval **p) /* {{{ */
+{
+ zval *new;
+
+ ALLOC_ZVAL(new);
+ *new = **p;
+
+ zval_copy_ctor(new);
+
+ INIT_PZVAL(new);
+ *p = new;
+} /* }}} */
+
/* {{{ proto mixed get_browser([string browser_name [, bool return_array]])
Get information about the capabilities of a browser. If browser_name is omitted or null, HTTP_USER_AGENT is used. Returns an object by default; if return_array is true, returns an array. */
PHP_FUNCTION(get_browser)
@@ -511,11 +524,11 @@ PHP_FUNCTION(get_browser)
if (return_array) {
array_init(return_value);
- zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *));
+ zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) browscap_zval_copy_ctor, (void *) &tmp_copy, sizeof(zval *));
}
else {
object_init(return_value);
- zend_hash_copy(Z_OBJPROP_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *));
+ zend_hash_copy(Z_OBJPROP_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) browscap_zval_copy_ctor, (void *) &tmp_copy, sizeof(zval *));
}
while (zend_hash_find(Z_ARRVAL_PP(agent), "parent", sizeof("parent"), (void **) &z_agent_name) == SUCCESS) {
@@ -524,10 +537,10 @@ PHP_FUNCTION(get_browser)
}
if (return_array) {
- zend_hash_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *), 0);
+ zend_hash_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) browscap_zval_copy_ctor, (void *) &tmp_copy, sizeof(zval *), 0);
}
else {
- zend_hash_merge(Z_OBJPROP_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *), 0);
+ zend_hash_merge(Z_OBJPROP_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) browscap_zval_copy_ctor, (void *) &tmp_copy, sizeof(zval *), 0);
}
}
diff --git a/ext/standard/quot_print.c b/ext/standard/quot_print.c
index 280b86a9a2..6627858989 100644
--- a/ext/standard/quot_print.c
+++ b/ext/standard/quot_print.c
@@ -151,7 +151,7 @@ PHPAPI unsigned char *php_quot_print_encode(const unsigned char *str, size_t len
unsigned char c, *ret, *d;
char *hex = "0123456789ABCDEF";
- ret = safe_emalloc(1, 3 * length + 3 * (((3 * length)/PHP_QPRINT_MAXL) + 1), 0);
+ ret = safe_emalloc(3, length + (((3 * length)/(PHP_QPRINT_MAXL-9)) + 1), 1);
d = ret;
while (length--) {
diff --git a/ext/standard/tests/array/bug31158.phpt b/ext/standard/tests/array/bug31158.phpt
index e672a10b28..da7a9ec907 100644
--- a/ext/standard/tests/array/bug31158.phpt
+++ b/ext/standard/tests/array/bug31158.phpt
@@ -1,5 +1,7 @@
--TEST--
Bug #31158 (array_splice on $GLOBALS crashes)
+--INI--
+error_reporting = E_ALL
--FILE--
<?php
function __(){
diff --git a/ext/standard/tests/strings/bug64879.phpt b/ext/standard/tests/strings/bug64879.phpt
new file mode 100644
index 0000000000..1df90c6d85
--- /dev/null
+++ b/ext/standard/tests/strings/bug64879.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Bug #64879: quoted_printable_encode() wrong size calculation (CVE-2013-2110)
+--FILE--
+<?php
+
+quoted_printable_encode(str_repeat("\xf4", 1000));
+quoted_printable_encode(str_repeat("\xf4", 100000));
+
+echo "Done\n";
+?>
+--EXPECTF--
+Done
diff --git a/ext/xml/tests/bug65236.phpt b/ext/xml/tests/bug65236.phpt
new file mode 100644
index 0000000000..67b26d663f
--- /dev/null
+++ b/ext/xml/tests/bug65236.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #65236 (heap corruption in xml parser)
+--SKIPIF--
+<?php
+require_once("skipif.inc");
+?>
+--FILE--
+<?php
+xml_parse_into_struct(xml_parser_create_ns(), str_repeat("<blah>", 1000), $a);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: xml_parse_into_struct(): Maximum depth exceeded - Results truncated in %s on line %d
+Done
diff --git a/ext/xml/xml.c b/ext/xml/xml.c
index 1f0480b6c7..9f0bc30d98 100644
--- a/ext/xml/xml.c
+++ b/ext/xml/xml.c
@@ -427,7 +427,7 @@ static void xml_parser_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
}
if (parser->ltags) {
int inx;
- for (inx = 0; inx < parser->level; inx++)
+ for (inx = 0; ((inx < parser->level) && (inx < XML_MAXLEVEL)); inx++)
efree(parser->ltags[ inx ]);
efree(parser->ltags);
}
@@ -905,45 +905,50 @@ void _xml_startElementHandler(void *userData, const XML_Char *name, const XML_Ch
}
if (parser->data) {
- zval *tag, *atr;
- int atcnt = 0;
+ if (parser->level <= XML_MAXLEVEL) {
+ zval *tag, *atr;
+ int atcnt = 0;
- MAKE_STD_ZVAL(tag);
- MAKE_STD_ZVAL(atr);
+ MAKE_STD_ZVAL(tag);
+ MAKE_STD_ZVAL(atr);
- array_init(tag);
- array_init(atr);
+ array_init(tag);
+ array_init(atr);
- _xml_add_to_info(parser,((char *) tag_name) + parser->toffset);
+ _xml_add_to_info(parser,((char *) tag_name) + parser->toffset);
- add_assoc_string(tag,"tag",((char *) tag_name) + parser->toffset,1); /* cast to avoid gcc-warning */
- add_assoc_string(tag,"type","open",1);
- add_assoc_long(tag,"level",parser->level);
+ add_assoc_string(tag,"tag",((char *) tag_name) + parser->toffset,1); /* cast to avoid gcc-warning */
+ add_assoc_string(tag,"type","open",1);
+ add_assoc_long(tag,"level",parser->level);
- parser->ltags[parser->level-1] = estrdup(tag_name);
- parser->lastwasopen = 1;
+ parser->ltags[parser->level-1] = estrdup(tag_name);
+ parser->lastwasopen = 1;
- attributes = (const XML_Char **) attrs;
+ attributes = (const XML_Char **) attrs;
- while (attributes && *attributes) {
- att = _xml_decode_tag(parser, attributes[0]);
- val = xml_utf8_decode(attributes[1], strlen(attributes[1]), &val_len, parser->target_encoding);
-
- add_assoc_stringl(atr,att,val,val_len,0);
+ while (attributes && *attributes) {
+ att = _xml_decode_tag(parser, attributes[0]);
+ val = xml_utf8_decode(attributes[1], strlen(attributes[1]), &val_len, parser->target_encoding);
- atcnt++;
- attributes += 2;
+ add_assoc_stringl(atr,att,val,val_len,0);
- efree(att);
- }
+ atcnt++;
+ attributes += 2;
- if (atcnt) {
- zend_hash_add(Z_ARRVAL_P(tag),"attributes",sizeof("attributes"),&atr,sizeof(zval*),NULL);
- } else {
- zval_ptr_dtor(&atr);
- }
+ efree(att);
+ }
+
+ if (atcnt) {
+ zend_hash_add(Z_ARRVAL_P(tag),"attributes",sizeof("attributes"),&atr,sizeof(zval*),NULL);
+ } else {
+ zval_ptr_dtor(&atr);
+ }
- zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),(void *) &parser->ctag);
+ zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),(void *) &parser->ctag);
+ } else if (parser->level == (XML_MAXLEVEL + 1)) {
+ TSRMLS_FETCH();
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Maximum depth exceeded - Results truncated");
+ }
}
efree(tag_name);
@@ -995,7 +1000,7 @@ void _xml_endElementHandler(void *userData, const XML_Char *name)
efree(tag_name);
- if (parser->ltags) {
+ if ((parser->ltags) && (parser->level <= XML_MAXLEVEL)) {
efree(parser->ltags[parser->level-1]);
}
@@ -1079,18 +1084,23 @@ void _xml_characterDataHandler(void *userData, const XML_Char *s, int len)
}
}
- MAKE_STD_ZVAL(tag);
-
- array_init(tag);
-
- _xml_add_to_info(parser,parser->ltags[parser->level-1] + parser->toffset);
+ if (parser->level <= XML_MAXLEVEL) {
+ MAKE_STD_ZVAL(tag);
- add_assoc_string(tag,"tag",parser->ltags[parser->level-1] + parser->toffset,1);
- add_assoc_string(tag,"value",decoded_value,0);
- add_assoc_string(tag,"type","cdata",1);
- add_assoc_long(tag,"level",parser->level);
+ array_init(tag);
- zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),NULL);
+ _xml_add_to_info(parser,parser->ltags[parser->level-1] + parser->toffset);
+
+ add_assoc_string(tag,"tag",parser->ltags[parser->level-1] + parser->toffset,1);
+ add_assoc_string(tag,"value",decoded_value,0);
+ add_assoc_string(tag,"type","cdata",1);
+ add_assoc_long(tag,"level",parser->level);
+
+ zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),NULL);
+ } else if (parser->level == (XML_MAXLEVEL + 1)) {
+ TSRMLS_FETCH();
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Maximum depth exceeded - Results truncated");
+ }
}
} else {
efree(decoded_value);
diff --git a/main/php_version.h b/main/php_version.h
index 1903611f29..bddf0bc12f 100644
--- a/main/php_version.h
+++ b/main/php_version.h
@@ -2,7 +2,7 @@
/* edit configure.in to change version number */
#define PHP_MAJOR_VERSION 5
#define PHP_MINOR_VERSION 3
-#define PHP_RELEASE_VERSION 27
+#define PHP_RELEASE_VERSION 28
#define PHP_EXTRA_VERSION "-dev"
-#define PHP_VERSION "5.3.27-dev"
-#define PHP_VERSION_ID 50327
+#define PHP_VERSION "5.3.28-dev"
+#define PHP_VERSION_ID 50328
diff --git a/main/streams/cast.c b/main/streams/cast.c
index 4063930436..6f79a24e30 100644
--- a/main/streams/cast.c
+++ b/main/streams/cast.c
@@ -31,10 +31,18 @@
/* Under BSD, emulate fopencookie using funopen */
#if defined(HAVE_FUNOPEN) && !defined(HAVE_FOPENCOOKIE)
+
+/* NetBSD 6.0+ uses off_t instead of fpos_t in funopen */
+# if defined(__NetBSD__) && (__NetBSD_Version__ > 600000000)
+# define PHP_FPOS_T off_t
+# else
+# define PHP_FPOS_T fpos_t
+# endif
+
typedef struct {
int (*reader)(void *, char *, int);
int (*writer)(void *, const char *, int);
- fpos_t (*seeker)(void *, fpos_t, int);
+ PHP_FPOS_T (*seeker)(void *, PHP_FPOS_T, int);
int (*closer)(void *);
} COOKIE_IO_FUNCTIONS_T;
@@ -68,11 +76,11 @@ static int stream_cookie_writer(void *cookie, const char *buffer, int size)
return php_stream_write((php_stream *)cookie, (char *)buffer, size);
}
-static fpos_t stream_cookie_seeker(void *cookie, off_t position, int whence)
+static PHP_FPOS_T stream_cookie_seeker(void *cookie, off_t position, int whence)
{
TSRMLS_FETCH();
- return (fpos_t)php_stream_seek((php_stream *)cookie, position, whence);
+ return (PHP_FPOS_T)php_stream_seek((php_stream *)cookie, position, whence);
}
static int stream_cookie_closer(void *cookie)