Skip to content

Commit fef9ba0

Browse files
committed
Add some ValueErrors to ext/date
1 parent 0444158 commit fef9ba0

File tree

5 files changed

+91
-56
lines changed

5 files changed

+91
-56
lines changed

ext/date/php_date.c

+41-18
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ PHPAPI timelib_tzinfo *get_timezone_info(void)
549549
tz = guess_timezone(DATE_TIMEZONEDB);
550550
tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB);
551551
if (! tzi) {
552-
php_error_docref(NULL, E_ERROR, "Timezone database is corrupt - this should *never* happen!");
552+
zend_throw_error(NULL, "Timezone database is corrupt. Please file a bug report as this should never happen");
553553
}
554554
return tzi;
555555
}
@@ -950,8 +950,8 @@ PHP_FUNCTION(idate)
950950
ZEND_PARSE_PARAMETERS_END();
951951

952952
if (ZSTR_LEN(format) != 1) {
953-
php_error_docref(NULL, E_WARNING, "idate format is one char");
954-
RETURN_FALSE;
953+
zend_argument_value_error(1, "must be one character");
954+
RETURN_THROWS();
955955
}
956956

957957
if (ts_is_null) {
@@ -960,8 +960,8 @@ PHP_FUNCTION(idate)
960960

961961
ret = php_idate(ZSTR_VAL(format)[0], ts, 0);
962962
if (ret == -1) {
963-
php_error_docref(NULL, E_WARNING, "Unrecognized date format token.");
964-
RETURN_FALSE;
963+
zend_argument_value_error(1, "must be a valid date format token");
964+
RETURN_THROWS();
965965
}
966966
RETURN_LONG(ret);
967967
}
@@ -1021,6 +1021,12 @@ PHP_FUNCTION(strtotime)
10211021
Z_PARAM_LONG_OR_NULL(preset_ts, preset_ts_is_null)
10221022
ZEND_PARSE_PARAMETERS_END();
10231023

1024+
/* timelib_strtotime() expects the string to not be empty */
1025+
if (ZSTR_LEN(times) == 0) {
1026+
/* TODO Add a Warning? */
1027+
RETURN_FALSE;
1028+
}
1029+
10241030
tzi = get_timezone_info();
10251031

10261032
now = timelib_time_ctor();
@@ -1033,18 +1039,26 @@ PHP_FUNCTION(strtotime)
10331039
DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
10341040
error1 = error->error_count;
10351041
timelib_error_container_dtor(error);
1042+
if (error1) {
1043+
timelib_time_dtor(now);
1044+
timelib_time_dtor(t);
1045+
RETURN_FALSE;
1046+
}
1047+
10361048
timelib_fill_holes(t, now, TIMELIB_NO_CLONE);
10371049
timelib_update_ts(t, tzi);
10381050
ts = timelib_date_to_int(t, &error2);
10391051

10401052
timelib_time_dtor(now);
10411053
timelib_time_dtor(t);
10421054

1043-
if (error1 || error2) {
1055+
/* Seconds since epoch must fit in a zend_long */
1056+
if (error2) {
1057+
/* TODO Add warning? */
10441058
RETURN_FALSE;
1045-
} else {
1046-
RETURN_LONG(ts);
10471059
}
1060+
1061+
RETURN_LONG(ts);
10481062
}
10491063
/* }}} */
10501064

@@ -1115,14 +1129,18 @@ PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gmt)
11151129

11161130
/* Clean up and return */
11171131
ts = timelib_date_to_int(now, &error);
1118-
ts += adjust_seconds;
1119-
timelib_time_dtor(now);
11201132

1133+
/* Seconds since epoch must fit in a zend_long */
11211134
if (error) {
1135+
timelib_time_dtor(now);
1136+
/* TODO Add warning? */
11221137
RETURN_FALSE;
1123-
} else {
1124-
RETURN_LONG(ts);
11251138
}
1139+
1140+
ts += adjust_seconds;
1141+
timelib_time_dtor(now);
1142+
1143+
RETURN_LONG(ts);
11261144
}
11271145
/* }}} */
11281146

@@ -1179,6 +1197,7 @@ PHPAPI void php_strftime(INTERNAL_FUNCTION_PARAMETERS, int gmt)
11791197
ZEND_PARSE_PARAMETERS_END();
11801198

11811199
if (ZSTR_LEN(format) == 0) {
1200+
/* TODO Add a warning? */
11821201
RETURN_FALSE;
11831202
}
11841203

@@ -1223,7 +1242,7 @@ PHPAPI void php_strftime(INTERNAL_FUNCTION_PARAMETERS, int gmt)
12231242
ta.tm_zone = offset->abbr;
12241243
#endif
12251244
}
1226-
1245+
// TODO Cleanup as bug is not present anymore? (Need to update link as MS retired connect.microsoft.com)
12271246
/* VS2012 crt has a bug where strftime crash with %z and %Z format when the
12281247
initial buffer is too small. See
12291248
http://connect.microsoft.com/VisualStudio/feedback/details/759720/vs2012-strftime-crash-with-z-formatting-code */
@@ -2780,7 +2799,7 @@ static int php_date_modify(zval *object, char *modify, size_t modify_len) /* {{{
27802799
dateobj = Z_PHPDATE_P(object);
27812800

27822801
if (!(dateobj->time)) {
2783-
php_error_docref(NULL, E_WARNING, "The DateTime object has not been correctly initialized by its constructor");
2802+
zend_throw_error(NULL, "The DateTime object has not been correctly initialized by its constructor");
27842803
return 0;
27852804
}
27862805

@@ -3318,11 +3337,14 @@ PHP_FUNCTION(date_timestamp_get)
33183337
timelib_update_ts(dateobj->time, NULL);
33193338

33203339
timestamp = timelib_date_to_int(dateobj->time, &error);
3340+
3341+
/* Seconds since epoch must fit in a zend_long */
33213342
if (error) {
3343+
/* TODO Add warning? */
33223344
RETURN_FALSE;
3323-
} else {
3324-
RETVAL_LONG(timestamp);
33253345
}
3346+
3347+
RETURN_LONG(timestamp);
33263348
}
33273349
/* }}} */
33283350

@@ -3386,7 +3408,7 @@ PHP_FUNCTION(timezone_open)
33863408
php_timezone_obj *tzobj;
33873409

33883410
ZEND_PARSE_PARAMETERS_START(1, 1)
3389-
Z_PARAM_STR(tz)
3411+
Z_PARAM_PATH_STR(tz) /* To prevent nul bytes */
33903412
ZEND_PARSE_PARAMETERS_END();
33913413

33923414
tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, return_value));
@@ -3405,7 +3427,7 @@ PHP_METHOD(DateTimeZone, __construct)
34053427
zend_error_handling error_handling;
34063428

34073429
ZEND_PARSE_PARAMETERS_START(1, 1)
3408-
Z_PARAM_STR(tz)
3430+
Z_PARAM_PATH_STR(tz) /* To prevent nul bytes */
34093431
ZEND_PARSE_PARAMETERS_END();
34103432

34113433
zend_replace_error_handling(EH_THROW, NULL, &error_handling);
@@ -4321,6 +4343,7 @@ PHP_FUNCTION(timezone_identifiers_list)
43214343

43224344
/* Extra validation */
43234345
if (what == PHP_DATE_TIMEZONE_PER_COUNTRY && option_len != 2) {
4346+
// Promoto to ValueError?
43244347
php_error_docref(NULL, E_NOTICE, "A two-letter ISO 3166-1 compatible country code is expected");
43254348
RETURN_FALSE;
43264349
}

ext/date/php_date.stub.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ function strtotime(string $datetime, ?int $baseTimestamp = null): int|false {}
66

77
function date(string $format, ?int $timestamp = null): string {}
88

9-
function idate(string $format, ?int $timestamp = null): int|false {}
9+
function idate(string $format, ?int $timestamp = null): int {}
1010

1111
function gmdate(string $format, ?int $timestamp = null): string {}
1212

@@ -73,7 +73,7 @@ function date_isodate_set(DateTime $object, int $year, int $week, int $day = 1):
7373

7474
function date_timestamp_set(DateTime $object, int $timestamp): DateTime {}
7575

76-
function date_timestamp_get(DateTimeInterface $object): int|false {}
76+
function date_timestamp_get(DateTimeInterface $object): int {}
7777

7878
function timezone_open(string $timezone): DateTimeZone|false {}
7979

ext/date/php_date_arginfo.h

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: fee95924adec03c89fdd677ec26bb6eea34d4b3c */
2+
* Stub hash: a1b54f5aa27f583fb84953c1aa3f5d901ceb9f9d */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
55
ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0)
@@ -11,7 +11,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_date, 0, 1, IS_STRING, 0)
1111
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timestamp, IS_LONG, 1, "null")
1212
ZEND_END_ARG_INFO()
1313

14-
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_idate, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
14+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_idate, 0, 1, IS_LONG, 0)
1515
ZEND_ARG_TYPE_INFO(0, format, IS_STRING, 0)
1616
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timestamp, IS_LONG, 1, "null")
1717
ZEND_END_ARG_INFO()
@@ -151,9 +151,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_date_timestamp_set, 0, 2, DateTim
151151
ZEND_ARG_TYPE_INFO(0, timestamp, IS_LONG, 0)
152152
ZEND_END_ARG_INFO()
153153

154-
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_date_timestamp_get, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
155-
ZEND_ARG_OBJ_INFO(0, object, DateTimeInterface, 0)
156-
ZEND_END_ARG_INFO()
154+
#define arginfo_date_timestamp_get arginfo_date_offset_get
157155

158156
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_timezone_open, 0, 1, DateTimeZone, MAY_BE_FALSE)
159157
ZEND_ARG_TYPE_INFO(0, timezone, IS_STRING, 0)

ext/date/tests/005.phpt

+32-20
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,42 @@ date_default_timezone_set('UTC');
66

77
$t = mktime(0,0,0, 6, 27, 2006);
88

9-
var_dump(idate(1,1));
10-
var_dump(idate(""));
11-
var_dump(idate(0));
9+
try {
10+
var_dump(idate(1,1));
11+
} catch (\ValueError $e) {
12+
echo $e->getMessage() . \PHP_EOL;
13+
}
14+
try {
15+
var_dump(idate(""));
16+
} catch (\ValueError $e) {
17+
echo $e->getMessage() . \PHP_EOL;
18+
}
19+
try {
20+
var_dump(idate(0));
21+
} catch (\ValueError $e) {
22+
echo $e->getMessage() . \PHP_EOL;
23+
}
1224

1325
var_dump(idate("B", $t));
14-
var_dump(idate("[", $t));
15-
var_dump(idate("'"));
26+
27+
try {
28+
var_dump(idate("[", $t));
29+
} catch (\ValueError $e) {
30+
echo $e->getMessage() . \PHP_EOL;
31+
}
32+
try {
33+
var_dump(idate("'"));
34+
} catch (\ValueError $e) {
35+
echo $e->getMessage() . \PHP_EOL;
36+
}
1637

1738
echo "Done\n";
1839
?>
19-
--EXPECTF--
20-
Warning: idate(): Unrecognized date format token. in %s on line %d
21-
bool(false)
22-
23-
Warning: idate(): idate format is one char in %s on line %d
24-
bool(false)
25-
26-
Warning: idate(): Unrecognized date format token. in %s on line %d
27-
bool(false)
40+
--EXPECT--
41+
idate(): Argument #1 ($format) must be a valid date format token
42+
idate(): Argument #1 ($format) must be one character
43+
idate(): Argument #1 ($format) must be a valid date format token
2844
int(41)
29-
30-
Warning: idate(): Unrecognized date format token. in %s on line %d
31-
bool(false)
32-
33-
Warning: idate(): Unrecognized date format token. in %s on line %d
34-
bool(false)
45+
idate(): Argument #1 ($format) must be a valid date format token
46+
idate(): Argument #1 ($format) must be a valid date format token
3547
Done

ext/date/tests/bug70277.phpt

+13-11
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@ Bug #70277 (new DateTimeZone($foo) is ignoring text after null byte)
33
--FILE--
44
<?php
55
$timezone = "Europe/Zurich\0Foo";
6-
var_dump(timezone_open($timezone));
7-
var_dump(new DateTimeZone($timezone));
6+
try {
7+
var_dump(timezone_open($timezone));
8+
} catch (\ValueError $e) {
9+
echo $e->getMessage() . \PHP_EOL;
10+
}
11+
try {
12+
var_dump(new DateTimeZone($timezone));
13+
} catch (\ValueError $e) {
14+
echo $e->getMessage() . \PHP_EOL;
15+
}
816
?>
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: 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
17+
--EXPECT--
18+
timezone_open(): Argument #1 ($timezone) must not contain any null bytes
19+
DateTimeZone::__construct(): Argument #1 ($timezone) must not contain any null bytes

0 commit comments

Comments
 (0)