1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Slightly improve error handling in DatePeriod::__construct()

This commit is contained in:
Máté Kocsis
2020-09-14 11:59:51 +02:00
parent 46c0c82a0f
commit 8e8a277b2f
6 changed files with 70 additions and 27 deletions

View File

@@ -24,6 +24,7 @@
#include "ext/standard/php_math.h"
#include "php_date.h"
#include "zend_interfaces.h"
#include "zend_exceptions.h"
#include "lib/timelib.h"
#include "lib/timelib_private.h"
#ifndef PHP_WIN32
@@ -4117,13 +4118,11 @@ PHP_METHOD(DatePeriod, __construct)
timelib_time *clone;
zend_error_handling error_handling;
zend_replace_error_handling(EH_THROW, NULL, &error_handling);
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "OOl|l", &start, date_ce_interface, &interval, date_ce_interval, &recurrences, &options) == FAILURE) {
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "OOO|l", &start, date_ce_interface, &interval, date_ce_interval, &end, date_ce_interface, &options) == FAILURE) {
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "s|l", &isostr, &isostr_len, &options) == FAILURE) {
php_error_docref(NULL, E_WARNING, "This constructor accepts either (DateTimeInterface, DateInterval, int) OR (DateTimeInterface, DateInterval, DateTime) OR (string) as arguments.");
zend_restore_error_handling(&error_handling);
return;
zend_type_error("DatePeriod::__construct() accepts (DateTimeInterface, DateInterval, int [, int]), or (DateTimeInterface, DateInterval, DateTime [, int]), or (string [, int]) as arguments");
RETURN_THROWS();
}
}
}
@@ -4132,15 +4131,30 @@ PHP_METHOD(DatePeriod, __construct)
dpobj->current = NULL;
if (isostr) {
zend_replace_error_handling(EH_THROW, NULL, &error_handling);
date_period_initialize(&(dpobj->start), &(dpobj->end), &(dpobj->interval), &recurrences, isostr, isostr_len);
zend_restore_error_handling(&error_handling);
if (EG(exception)) {
RETURN_THROWS();
}
if (dpobj->start == NULL) {
php_error_docref(NULL, E_WARNING, "The ISO interval '%s' did not contain a start date.", isostr);
zend_string *func = get_active_function_or_method_name();
zend_throw_error(zend_ce_exception, "%s(): ISO interval must contain a start date, \"%s\" given", ZSTR_VAL(func), isostr);
zend_string_release(func);
RETURN_THROWS();
}
if (dpobj->interval == NULL) {
php_error_docref(NULL, E_WARNING, "The ISO interval '%s' did not contain an interval.", isostr);
zend_string *func = get_active_function_or_method_name();
zend_throw_error(zend_ce_exception, "%s(): ISO interval must contain an interval, \"%s\" given", ZSTR_VAL(func), isostr);
zend_string_release(func);
RETURN_THROWS();
}
if (dpobj->end == NULL && recurrences == 0) {
php_error_docref(NULL, E_WARNING, "The ISO interval '%s' did not contain an end date or a recurrence count.", isostr);
zend_string *func = get_active_function_or_method_name();
zend_throw_error(zend_ce_exception, "%s(): ISO interval must contain an end date or a recurrence count, \"%s\" given", ZSTR_VAL(func), isostr);
zend_string_release(func);
RETURN_THROWS();
}
if (dpobj->start) {
@@ -4179,7 +4193,10 @@ PHP_METHOD(DatePeriod, __construct)
}
if (dpobj->end == NULL && recurrences < 1) {
php_error_docref(NULL, E_WARNING, "The recurrence count '%d' is invalid. Needs to be > 0", (int) recurrences);
zend_string *func = get_active_function_or_method_name();
zend_throw_error(zend_ce_exception, "%s(): Recurrence count must be greater than 0", ZSTR_VAL(func));
zend_string_release(func);
RETURN_THROWS();
}
/* options */
@@ -4189,8 +4206,6 @@ PHP_METHOD(DatePeriod, __construct)
dpobj->recurrences = recurrences + dpobj->include_start_date;
dpobj->initialized = 1;
zend_restore_error_handling(&error_handling);
}
/* }}} */

View File

@@ -7,11 +7,12 @@ Havard Eide <nucleuz@gmail.com>
date.timezone=UTC
--FILE--
<?php
new DatePeriod();
try {
new DatePeriod();
} catch (TypeError $exception) {
echo $exception->getMessage() . "\n";
}
?>
--EXPECTF--
Fatal error: Uncaught Exception: DatePeriod::__construct(): This constructor accepts either (DateTimeInterface, DateInterval, int) OR (DateTimeInterface, DateInterval, DateTime) OR (string) as arguments. in %s:%d
Stack trace:
#0 %s(%d): DatePeriod->__construct()
#1 {main}
thrown in %s on line %d
--EXPECT--
DatePeriod::__construct() accepts (DateTimeInterface, DateInterval, int [, int]), or (DateTimeInterface, DateInterval, DateTime [, int]), or (string [, int]) as arguments

View File

@@ -9,11 +9,12 @@ try {
}
try {
new DatePeriod(new DateTime('yesterday'), new DateInterval('P1D'),-1);
new DatePeriod(new DateTime('yesterday'), new DateInterval('P1D'), -1);
} catch (Exception $exception) {
echo $exception->getMessage(), "\n";
}
?>
--EXPECT--
DatePeriod::__construct(): The recurrence count '0' is invalid. Needs to be > 0
DatePeriod::__construct(): The recurrence count '-1' is invalid. Needs to be > 0
DatePeriod::__construct(): Recurrence count must be greater than 0
DatePeriod::__construct(): Recurrence count must be greater than 0

View File

@@ -4,12 +4,9 @@ Bug #44562 (Creating instance of DatePeriod crashes)
<?php
date_default_timezone_set('Europe/Oslo');
try
{
try {
$dp = new DatePeriod('2D');
}
catch ( Exception $e )
{
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}

View File

@@ -4,13 +4,13 @@ DateInterval with bad format should not leak period
<?php
try {
$interval = new DateInterval('P3"D');
new DateInterval('P3"D');
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}
try {
$perid = new DatePeriod('P3"D');
new DatePeriod('P3"D');
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}

View File

@@ -0,0 +1,29 @@
--TEST--
Test bad ISO date formats passed to DatePeriod constructor
--FILE--
<?php
try {
new DatePeriod("R4");
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}
try {
new DatePeriod("R4/2012-07-01T00:00:00Z");
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}
try {
new DatePeriod("2012-07-01T00:00:00Z/P7D");
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
DatePeriod::__construct(): ISO interval must contain a start date, "R4" given
DatePeriod::__construct(): ISO interval must contain an interval, "R4/2012-07-01T00:00:00Z" given
DatePeriod::__construct(): ISO interval must contain an end date or a recurrence count, "2012-07-01T00:00:00Z/P7D" given