Skip to content

Commit bb05749

Browse files
committed
Fix #70277: new DateTimeZone($foo) is ignoring text after null byte
The DateTimeZone constructors are not binary safe. They're parsing the timezone as string, but discard the length when calling timezone_initialize(). This patch adds a tz_len parameter and a respective check to timezone_initialize().
1 parent b010a9d commit bb05749

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

ext/date/php_date.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3682,12 +3682,17 @@ PHP_FUNCTION(date_diff)
36823682
}
36833683
/* }}} */
36843684

3685-
static int timezone_initialize(php_timezone_obj *tzobj, /*const*/ char *tz TSRMLS_DC)
3685+
static int timezone_initialize(php_timezone_obj *tzobj, /*const*/ char *tz, size_t tz_len TSRMLS_DC)
36863686
{
36873687
timelib_time *dummy_t = ecalloc(1, sizeof(timelib_time));
36883688
int dst, not_found;
36893689
char *orig_tz = tz;
36903690

3691+
if (strlen(tz) != tz_len) {
3692+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Timezone must not contain null bytes");
3693+
return FAILURE;
3694+
}
3695+
36913696
dummy_t->z = timelib_parse_zone(&tz, &dst, dummy_t, &not_found, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
36923697
if (not_found) {
36933698
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad timezone (%s)", orig_tz);
@@ -3714,7 +3719,7 @@ PHP_FUNCTION(timezone_open)
37143719
RETURN_FALSE;
37153720
}
37163721
tzobj = zend_object_store_get_object(php_date_instantiate(date_ce_timezone, return_value TSRMLS_CC) TSRMLS_CC);
3717-
if (SUCCESS != timezone_initialize(tzobj, tz TSRMLS_CC)) {
3722+
if (SUCCESS != timezone_initialize(tzobj, tz, tz_len TSRMLS_CC)) {
37183723
RETURN_FALSE;
37193724
}
37203725
}
@@ -3733,7 +3738,7 @@ PHP_METHOD(DateTimeZone, __construct)
37333738
zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
37343739
if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &tz, &tz_len)) {
37353740
tzobj = zend_object_store_get_object(getThis() TSRMLS_CC);
3736-
if (FAILURE == timezone_initialize(tzobj, tz TSRMLS_CC)) {
3741+
if (FAILURE == timezone_initialize(tzobj, tz, tz_len TSRMLS_CC)) {
37373742
ZVAL_NULL(getThis());
37383743
}
37393744
}
@@ -3748,7 +3753,7 @@ static int php_date_timezone_initialize_from_hash(zval **return_value, php_timez
37483753

37493754
if (zend_hash_find(myht, "timezone_type", 14, (void**) &z_timezone_type) == SUCCESS && Z_TYPE_PP(z_timezone_type) == IS_LONG) {
37503755
if (zend_hash_find(myht, "timezone", 9, (void**) &z_timezone) == SUCCESS && Z_TYPE_PP(z_timezone) == IS_STRING) {
3751-
if (SUCCESS == timezone_initialize(*tzobj, Z_STRVAL_PP(z_timezone) TSRMLS_CC)) {
3756+
if (SUCCESS == timezone_initialize(*tzobj, Z_STRVAL_PP(z_timezone), Z_STRLEN_PP(z_timezone) TSRMLS_CC)) {
37523757
return SUCCESS;
37533758
}
37543759
}

ext/date/tests/bug70277.phpt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Bug #70277 (new DateTimeZone($foo) is ignoring text after null byte)
3+
--FILE--
4+
<?php
5+
$timezone = "Europe/Zurich\0Foo";
6+
var_dump(timezone_open($timezone));
7+
var_dump(new DateTimeZone($timezone));
8+
?>
9+
--EXPECTF--
10+
Warning: timezone_open(): Timezone must not contain null bytes in %sbug70277.php on line %d
11+
bool(false)
12+
13+
Fatal error: Uncaught exception 'Exception' with message 'DateTimeZone::__construct(): Timezone must not contain null bytes' in %sbug70277.php:%d
14+
Stack trace:
15+
#0 %sbug70277.php(%d): DateTimeZone->__construct('Europe/Zurich\x00F...')
16+
#1 {main}
17+
thrown in %sbug70277.php on line %d

0 commit comments

Comments
 (0)