Skip to content

Commit 68f47b6

Browse files
committed
Add some ValueErrors to ext/date
1 parent 6d538e8 commit 68f47b6

File tree

5 files changed

+91
-56
lines changed

5 files changed

+91
-56
lines changed

ext/date/php_date.c

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ PHPAPI timelib_tzinfo *get_timezone_info(void)
550550
tz = guess_timezone(DATE_TIMEZONEDB);
551551
tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB);
552552
if (! tzi) {
553-
php_error_docref(NULL, E_ERROR, "Timezone database is corrupt - this should *never* happen!");
553+
zend_throw_error(NULL, "Timezone database is corrupt. Please file a bug report as this should never happen");
554554
}
555555
return tzi;
556556
}
@@ -951,8 +951,8 @@ PHP_FUNCTION(idate)
951951
ZEND_PARSE_PARAMETERS_END();
952952

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

958958
if (ts_is_null) {
@@ -961,8 +961,8 @@ PHP_FUNCTION(idate)
961961

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

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

10271033
now = timelib_time_ctor();
@@ -1034,18 +1040,26 @@ PHP_FUNCTION(strtotime)
10341040
DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
10351041
error1 = error->error_count;
10361042
timelib_error_container_dtor(error);
1043+
if (error1) {
1044+
timelib_time_dtor(now);
1045+
timelib_time_dtor(t);
1046+
RETURN_FALSE;
1047+
}
1048+
10371049
timelib_fill_holes(t, now, TIMELIB_NO_CLONE);
10381050
timelib_update_ts(t, tzi);
10391051
ts = timelib_date_to_int(t, &error2);
10401052

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

1044-
if (error1 || error2) {
1056+
/* Seconds since epoch must fit in a zend_long */
1057+
if (error2) {
1058+
/* TODO Add warning? */
10451059
RETURN_FALSE;
1046-
} else {
1047-
RETURN_LONG(ts);
10481060
}
1061+
1062+
RETURN_LONG(ts);
10491063
}
10501064
/* }}} */
10511065

@@ -1116,14 +1130,18 @@ PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gmt)
11161130

11171131
/* Clean up and return */
11181132
ts = timelib_date_to_int(now, &error);
1119-
ts += adjust_seconds;
1120-
timelib_time_dtor(now);
11211133

1134+
/* Seconds since epoch must fit in a zend_long */
11221135
if (error) {
1136+
timelib_time_dtor(now);
1137+
/* TODO Add warning? */
11231138
RETURN_FALSE;
1124-
} else {
1125-
RETURN_LONG(ts);
11261139
}
1140+
1141+
ts += adjust_seconds;
1142+
timelib_time_dtor(now);
1143+
1144+
RETURN_LONG(ts);
11271145
}
11281146
/* }}} */
11291147

@@ -1180,6 +1198,7 @@ PHPAPI void php_strftime(INTERNAL_FUNCTION_PARAMETERS, int gmt)
11801198
ZEND_PARSE_PARAMETERS_END();
11811199

11821200
if (ZSTR_LEN(format) == 0) {
1201+
/* TODO Add a warning? */
11831202
RETURN_FALSE;
11841203
}
11851204

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

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

@@ -3319,11 +3338,14 @@ PHP_FUNCTION(date_timestamp_get)
33193338
timelib_update_ts(dateobj->time, NULL);
33203339

33213340
timestamp = timelib_date_to_int(dateobj->time, &error);
3341+
3342+
/* Seconds since epoch must fit in a zend_long */
33223343
if (error) {
3344+
/* TODO Add warning? */
33233345
RETURN_FALSE;
3324-
} else {
3325-
RETVAL_LONG(timestamp);
33263346
}
3347+
3348+
RETURN_LONG(timestamp);
33273349
}
33283350
/* }}} */
33293351

@@ -3387,7 +3409,7 @@ PHP_FUNCTION(timezone_open)
33873409
php_timezone_obj *tzobj;
33883410

33893411
ZEND_PARSE_PARAMETERS_START(1, 1)
3390-
Z_PARAM_STR(tz)
3412+
Z_PARAM_PATH_STR(tz) /* To prevent nul bytes */
33913413
ZEND_PARSE_PARAMETERS_END();
33923414

33933415
tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, return_value));
@@ -3406,7 +3428,7 @@ PHP_METHOD(DateTimeZone, __construct)
34063428
zend_error_handling error_handling;
34073429

34083430
ZEND_PARSE_PARAMETERS_START(1, 1)
3409-
Z_PARAM_STR(tz)
3431+
Z_PARAM_PATH_STR(tz) /* To prevent nul bytes */
34103432
ZEND_PARSE_PARAMETERS_END();
34113433

34123434
zend_replace_error_handling(EH_THROW, NULL, &error_handling);
@@ -4336,6 +4358,7 @@ PHP_FUNCTION(timezone_identifiers_list)
43364358

43374359
/* Extra validation */
43384360
if (what == PHP_DATE_TIMEZONE_PER_COUNTRY && option_len != 2) {
4361+
// Promoto to ValueError?
43394362
php_error_docref(NULL, E_NOTICE, "A two-letter ISO 3166-1 compatible country code is expected");
43404363
RETURN_FALSE;
43414364
}

ext/date/php_date.stub.php

Lines changed: 2 additions & 2 deletions
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

Lines changed: 3 additions & 5 deletions
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

Lines changed: 32 additions & 20 deletions
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

Lines changed: 13 additions & 11 deletions
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)