summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-08-09 14:33:59 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-08-09 14:51:25 +0200
commit3b2f2ce4748328fc696cd3d27887bf61e22ca023 (patch)
tree349c1673fafd88f006afc123d46cd78f003d87fd
parent33886f710cd45fd883d85558197e2df4eaba9ea1 (diff)
downloadphp-git-3b2f2ce4748328fc696cd3d27887bf61e22ca023.tar.gz
Make uninitialized DateTime an Error
This avoids many spurious false return values.
-rw-r--r--ext/date/php_date.c4
-rw-r--r--ext/date/php_date.stub.php76
-rw-r--r--ext/date/php_date_arginfo.h34
-rw-r--r--ext/date/tests/bug48476.phpt32
-rw-r--r--ext/date/tests/bug67118.phpt8
-rw-r--r--ext/date/tests/oo_001.phpt24
-rw-r--r--ext/intl/tests/dateformat_formatObject_error.phpt10
-rwxr-xr-xscripts/dev/gen_stub.php10
8 files changed, 106 insertions, 92 deletions
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index aa457065d4..c3ffeba725 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -303,8 +303,8 @@ static zend_object_handlers date_object_handlers_period;
#define DATE_CHECK_INITIALIZED(member, class_name) \
if (!(member)) { \
- php_error_docref(NULL, E_WARNING, "The " #class_name " object has not been correctly initialized by its constructor"); \
- RETURN_FALSE; \
+ zend_throw_error(NULL, "The " #class_name " object has not been correctly initialized by its constructor"); \
+ return; \
}
static void date_object_free_storage_date(zend_object *object);
diff --git a/ext/date/php_date.stub.php b/ext/date/php_date.stub.php
index 1d448b9102..667cbc1b91 100644
--- a/ext/date/php_date.stub.php
+++ b/ext/date/php_date.stub.php
@@ -57,42 +57,33 @@ function date_parse_from_format(string $format, string $date): array {}
/** @return array|false */
function date_get_last_errors() {}
-/** @return string|false */
-function date_format(DateTimeInterface $object, string $format) {}
+function date_format(DateTimeInterface $object, string $format): string {}
/** @return DateTime|false */
function date_modify(DateTime $object, string $modify) {}
-/** @return DateTime|false */
-function date_add(DateTime $object, DateInterval $interval) {}
+function date_add(DateTime $object, DateInterval $interval): DateTime {}
-/** @return DateTime|false */
-function date_sub(DateTime $object, DateInterval $interval) {}
+function date_sub(DateTime $object, DateInterval $interval): DateTime {}
/** @return DateTimeZone|false */
function date_timezone_get(DateTimeInterface $object) {}
-/** @return DateTime|false */
-function date_timezone_set(DateTimeInterface $object, DateTimeZone $timezone) {}
+function date_timezone_set(DateTimeInterface $object, DateTimeZone $timezone): DateTime {}
-/** @return int|false */
-function date_offset_get(DateTimeInterface $object) {}
+function date_offset_get(DateTimeInterface $object): int {}
-/** @return DateInterval|false */
-function date_diff(DateTimeInterface $object, DateTimeInterface $object2, bool $absolute = false) {}
+function date_diff(
+ DateTimeInterface $object, DateTimeInterface $object2, bool $absolute = false): DateInterval {}
-/** @return DateTime|false */
function date_time_set(
- DateTime $object, int $hour, int $minute, int $second = 0, int $microseconds = 0) {}
+ DateTime $object, int $hour, int $minute, int $second = 0, int $microseconds = 0): DateTime {}
-/** @return DateTime|false */
-function date_date_set(DateTime $object, int $year, int $month, int $day) {}
+function date_date_set(DateTime $object, int $year, int $month, int $day): DateTime {}
-/** @return DateTime|false */
-function date_isodate_set(DateTime $object, int $year, int $week, int $day = 1) {}
+function date_isodate_set(DateTime $object, int $year, int $week, int $day = 1): DateTime {}
-/** @return DateTime|false */
-function date_timestamp_set(DateTime $object, int $timestamp) {}
+function date_timestamp_set(DateTime $object, int $timestamp): DateTime {}
/** @return int|false */
function date_timestamp_get(DateTimeInterface $object) {}
@@ -100,14 +91,12 @@ function date_timestamp_get(DateTimeInterface $object) {}
/** @return DateTimeZone|false */
function timezone_open(string $timezone) {}
-/** @return string|false */
-function timezone_name_get(DateTimeZone $object) {}
+function timezone_name_get(DateTimeZone $object): string {}
/** @return string|false */
function timezone_name_from_abbr(string $abbr, int $gmtoffset = -1, int $isdst = -1) {}
-/** @return int|false */
-function timezone_offset_get(DateTimeZone $object, DateTimeInterface $datetime) {}
+function timezone_offset_get(DateTimeZone $object, DateTimeInterface $datetime): int {}
/** @return array|false */
function timezone_transitions_get(
@@ -126,8 +115,7 @@ function timezone_version_get(): string {}
/** @return DateInterval|false */
function date_interval_create_from_date_string(string $time) {}
-/** @return string|false */
-function date_interval_format(DateInterval $object, string $format) {}
+function date_interval_format(DateInterval $object, string $format): string {}
function date_default_timezone_set(string $timezone_identifier): bool {}
@@ -188,25 +176,25 @@ class DateTime implements DateTimeInterface {
/** @return DateTime|false */
public function modify(string $modify);
- /** @return DateTime|false */
+ /** @return DateTime */
public function add(DateInterval $interval);
- /** @return DateTime|false */
+ /** @return DateTime */
public function sub(DateInterval $interval);
- /** @return DateTime|false */
+ /** @return DateTime */
public function setTimezone(DateTimeZone $timezone);
- /** @return DateTime|false */
+ /** @return DateTime */
public function setTime(int $hour, int $minute, int $second = 0, int $microseconds = 0);
- /** @return DateTime|false */
+ /** @return DateTime */
public function setDate(int $year, int $month, int $day);
- /** @return DateTime|false */
+ /** @return DateTime */
public function setISODate(int $year, int $week, int $day = 1);
- /** @return DateTime|false */
+ /** @return DateTime */
public function setTimestamp(int $timestampt);
}
@@ -222,35 +210,35 @@ class DateTimeImmutable implements DateTimeInterface {
/** @return DateTimeImmutable|false */
public function modify(string $modify);
- /** @return DateTimeImmutable|false */
+ /** @return DateTimeImmutable */
public function add(DateInterval $interval);
- /** @return DateTimeImmutable|false */
+ /** @return DateTimeImmutable */
public function sub(DateInterval $interval);
- /** @return DateTimeImmutable|false */
+ /** @return DateTimeImmutable */
public function setTimezone(DateTimeZone $timezone);
- /** @return DateTimeImmutable|false */
+ /** @return DateTimeImmutable */
public function setTime(int $hour, int $minute, int $second = 0, int $microseconds = 0);
- /** @return DateTimeImmutable|false */
+ /** @return DateTimeImmutable */
public function setDate(int $year, int $month, int $day);
- /** @return DateTimeImmutable|false */
+ /** @return DateTimeImmutable */
public function setISODate(int $year, int $week, int $day = 1);
- /** @return DateTimeImmutable|false */
- public function setTimestamp(int $timestampt);
+ /** @return DateTimeImmutable */
+ public function setTimestamp(int $timestamp);
}
class DateTimeZone {
public function __construct(string $timezone);
- /** @return string|false */
+ /** @return string */
public function getName();
- /** @return int|false */
+ /** @return int */
public function getOffset(DateTimeInterface $datetime);
/** @return array|false */
@@ -278,7 +266,7 @@ class DateInterval {
/** @return DateInterval|false */
public static function createFromDateString(string $time);
- /** @return string|false */
+ /** @return string */
public function format(string $format);
public function __wakeup();
diff --git a/ext/date/php_date_arginfo.h b/ext/date/php_date_arginfo.h
index 70381437c7..841ff28a6e 100644
--- a/ext/date/php_date_arginfo.h
+++ b/ext/date/php_date_arginfo.h
@@ -77,7 +77,7 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_date_get_last_errors, 0, 0, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_date_format, 0, 0, 2)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_date_format, 0, 2, IS_STRING, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTimeInterface, 0)
ZEND_ARG_TYPE_INFO(0, format, IS_STRING, 0)
ZEND_END_ARG_INFO()
@@ -87,7 +87,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_date_modify, 0, 0, 2)
ZEND_ARG_TYPE_INFO(0, modify, IS_STRING, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_date_add, 0, 0, 2)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_date_add, 0, 2, DateTime, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTime, 0)
ZEND_ARG_OBJ_INFO(0, interval, DateInterval, 0)
ZEND_END_ARG_INFO()
@@ -98,20 +98,22 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_date_timezone_get, 0, 0, 1)
ZEND_ARG_OBJ_INFO(0, object, DateTimeInterface, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_date_timezone_set, 0, 0, 2)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_date_timezone_set, 0, 2, DateTime, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTimeInterface, 0)
ZEND_ARG_OBJ_INFO(0, timezone, DateTimeZone, 0)
ZEND_END_ARG_INFO()
-#define arginfo_date_offset_get arginfo_date_timezone_get
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_date_offset_get, 0, 1, IS_LONG, 0)
+ ZEND_ARG_OBJ_INFO(0, object, DateTimeInterface, 0)
+ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_date_diff, 0, 0, 2)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_date_diff, 0, 2, DateInterval, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTimeInterface, 0)
ZEND_ARG_OBJ_INFO(0, object2, DateTimeInterface, 0)
ZEND_ARG_TYPE_INFO(0, absolute, _IS_BOOL, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_date_time_set, 0, 0, 3)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_date_time_set, 0, 3, DateTime, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTime, 0)
ZEND_ARG_TYPE_INFO(0, hour, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, minute, IS_LONG, 0)
@@ -119,21 +121,21 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_date_time_set, 0, 0, 3)
ZEND_ARG_TYPE_INFO(0, microseconds, IS_LONG, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_date_date_set, 0, 0, 4)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_date_date_set, 0, 4, DateTime, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTime, 0)
ZEND_ARG_TYPE_INFO(0, year, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, month, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, day, IS_LONG, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_date_isodate_set, 0, 0, 3)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_date_isodate_set, 0, 3, DateTime, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTime, 0)
ZEND_ARG_TYPE_INFO(0, year, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, week, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, day, IS_LONG, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_date_timestamp_set, 0, 0, 2)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_date_timestamp_set, 0, 2, DateTime, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTime, 0)
ZEND_ARG_TYPE_INFO(0, timestamp, IS_LONG, 0)
ZEND_END_ARG_INFO()
@@ -144,7 +146,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_open, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, timezone, IS_STRING, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_name_get, 0, 0, 1)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_timezone_name_get, 0, 1, IS_STRING, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTimeZone, 0)
ZEND_END_ARG_INFO()
@@ -154,7 +156,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_name_from_abbr, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, isdst, IS_LONG, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_offset_get, 0, 0, 2)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_timezone_offset_get, 0, 2, IS_LONG, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTimeZone, 0)
ZEND_ARG_OBJ_INFO(0, datetime, DateTimeInterface, 0)
ZEND_END_ARG_INFO()
@@ -165,7 +167,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_transitions_get, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, timestamp_end, IS_LONG, 0)
ZEND_END_ARG_INFO()
-#define arginfo_timezone_location_get arginfo_timezone_name_get
+ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_location_get, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, object, DateTimeZone, 0)
+ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_identifiers_list, 0, 0, 0)
ZEND_ARG_TYPE_INFO(0, what, IS_LONG, 0)
@@ -182,7 +186,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_date_interval_create_from_date_string, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, time, IS_STRING, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_date_interval_format, 0, 0, 2)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_date_interval_format, 0, 2, IS_STRING, 0)
ZEND_ARG_OBJ_INFO(0, object, DateInterval, 0)
ZEND_ARG_TYPE_INFO(0, format, IS_STRING, 0)
ZEND_END_ARG_INFO()
@@ -300,7 +304,9 @@ ZEND_END_ARG_INFO()
#define arginfo_DateTimeImmutable_setISODate arginfo_DateTime_setISODate
-#define arginfo_DateTimeImmutable_setTimestamp arginfo_DateTime_setTimestamp
+ZEND_BEGIN_ARG_INFO_EX(arginfo_DateTimeImmutable_setTimestamp, 0, 0, 1)
+ ZEND_ARG_TYPE_INFO(0, timestamp, IS_LONG, 0)
+ZEND_END_ARG_INFO()
#define arginfo_DateTimeZone___construct arginfo_timezone_open
diff --git a/ext/date/tests/bug48476.phpt b/ext/date/tests/bug48476.phpt
index 1335025c76..02086e0e56 100644
--- a/ext/date/tests/bug48476.phpt
+++ b/ext/date/tests/bug48476.phpt
@@ -10,22 +10,28 @@ class MyDateTimeZone extends DateTimeZone {
}
$o = new MyDateTime;
-var_dump($o->format("d"));
+try {
+ var_dump($o->format("d"));
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
$x = clone $o;
-var_dump($x->format("d"));
+try {
+ var_dump($x->format("d"));
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
clone $o;
-
-var_dump(timezone_location_get(clone new MyDateTimezone));
+try {
+ var_dump(timezone_location_get(clone new MyDateTimezone));
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
?>
---EXPECTF--
-Warning: DateTime::format(): The DateTime object has not been correctly initialized by its constructor in %sbug48476.php on line 10
-bool(false)
-
-Warning: DateTime::format(): The DateTime object has not been correctly initialized by its constructor in %sbug48476.php on line 13
-bool(false)
-
-Warning: timezone_location_get(): The DateTimeZone object has not been correctly initialized by its constructor in %sbug48476.php on line 18
-bool(false)
+--EXPECT--
+The DateTime object has not been correctly initialized by its constructor
+The DateTime object has not been correctly initialized by its constructor
+The DateTimeZone object has not been correctly initialized by its constructor
diff --git a/ext/date/tests/bug67118.phpt b/ext/date/tests/bug67118.phpt
index 332142856e..5a7d2d1d07 100644
--- a/ext/date/tests/bug67118.phpt
+++ b/ext/date/tests/bug67118.phpt
@@ -23,5 +23,9 @@ class mydt extends datetime
new mydt("Funktionsansvarig rÄdgivning och juridik", "UTC");
?>
--EXPECTF--
-Warning: DateTime::format(): The DateTime object has not been correctly initialized by its constructor in %s on line %d
-Bad date
+Fatal error: Uncaught Error: The DateTime object has not been correctly initialized by its constructor in %s:%d
+Stack trace:
+#0 %s(%d): DateTime->format('Y')
+#1 %s(%d): mydt->__construct(%s)
+#2 {main}
+ thrown in %s on line %d
diff --git a/ext/date/tests/oo_001.phpt b/ext/date/tests/oo_001.phpt
index 7cbf847c52..111364ec83 100644
--- a/ext/date/tests/oo_001.phpt
+++ b/ext/date/tests/oo_001.phpt
@@ -15,8 +15,12 @@ class _t extends DateTimeZone {
$d = new DateTime;
var_dump($d->format("Y-m-d H:i:s"));
-$d = new _d;
-var_dump($d->format("Y-m-d H:i:s"));
+try {
+ $d = new _d;
+ var_dump($d->format("Y-m-d H:i:s"));
+} catch (Error $e) {
+ echo $e->getMessage(),"\n";
+}
try {
new DateTime("1am todax");
@@ -27,8 +31,12 @@ try {
$t = new DateTimeZone("UTC");
var_dump($t->getName());
-$t = new _t;
-var_dump($t->getName());
+try {
+ $t = new _t;
+ var_dump($t->getName());
+} catch (Error $e) {
+ echo $e->getMessage(),"\n";
+}
try {
new DateTimeZone("GottaFindThisOne");
@@ -40,13 +48,9 @@ echo "DONE\n";
?>
--EXPECTF--
string(19) "%d-%d-%d %d:%d:%d"
-
-Warning: DateTime::format(): The DateTime object has not been correctly initialized by its constructor in %soo_001.php on line %d
-bool(false)
+The DateTime object has not been correctly initialized by its constructor
DateTime::__construct(): Failed to parse time string (1am todax) at position 4 (t): The timezone could not be found in the database
string(3) "UTC"
-
-Warning: DateTimeZone::getName(): The DateTimeZone object has not been correctly initialized by its constructor in %soo_001.php on line %d
-bool(false)
+The DateTimeZone object has not been correctly initialized by its constructor
DateTimeZone::__construct(): Unknown or bad timezone (GottaFindThisOne)
DONE
diff --git a/ext/intl/tests/dateformat_formatObject_error.phpt b/ext/intl/tests/dateformat_formatObject_error.phpt
index 24be090035..7c1140c09d 100644
--- a/ext/intl/tests/dateformat_formatObject_error.phpt
+++ b/ext/intl/tests/dateformat_formatObject_error.phpt
@@ -15,7 +15,11 @@ var_dump(IntlDateFormatter::formatObject(new stdclass));
class A extends IntlCalendar {function __construct(){}}
var_dump(IntlDateFormatter::formatObject(new A));
class B extends DateTime {function __construct(){}}
-var_dump(IntlDateFormatter::formatObject(new B));
+try {
+ var_dump(IntlDateFormatter::formatObject(new B));
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
$cal = IntlCalendar::createInstance();
var_dump(IntlDateFormatter::formatObject($cal, -2));
@@ -34,10 +38,8 @@ bool(false)
Warning: IntlDateFormatter::formatObject(): datefmt_format_object: bad IntlCalendar instance: not initialized properly in %s on line %d
bool(false)
-Warning: DateTime::getTimestamp(): The DateTime object has not been correctly initialized by its constructor in %s on line %d
-
Warning: IntlDateFormatter::formatObject(): datefmt_format_object: error calling ::getTimeStamp() on the object in %s on line %d
-bool(false)
+The DateTime object has not been correctly initialized by its constructor
Warning: IntlDateFormatter::formatObject(): datefmt_format_object: the date/time format type is invalid in %s on line %d
bool(false)
diff --git a/scripts/dev/gen_stub.php b/scripts/dev/gen_stub.php
index 9a71e7db82..59b7d448f6 100755
--- a/scripts/dev/gen_stub.php
+++ b/scripts/dev/gen_stub.php
@@ -199,7 +199,7 @@ function parseClass(Stmt\Class_ $class): ClassInfo {
$className = $class->name->toString();
foreach ($class as $stmt) {
if (!$stmt instanceof Stmt\ClassMethod) {
- throw new Exception("Not implemented");
+ throw new Exception("Not implemented class statement");
}
$funcs[] = parseFunctionLike($className . '_' . $stmt->name->toString(), $stmt);
@@ -230,7 +230,7 @@ function parseStubFile(string $fileName) {
$text = trim($comment->getText());
if (preg_match('/^#if\s+(.+)$/', $text, $matches)) {
if ($cond !== null) {
- throw new Exception("Not implemented");
+ throw new Exception("Not implemented preprocessor directive");
}
$cond = $matches[1];
} else if ($text === '#endif') {
@@ -284,7 +284,11 @@ function funcInfoToCode(FuncInfo $funcInfo): string {
$returnType->toTypeCode(), $returnType->isNullable
);
} else {
- throw new Exception("Not implemented");
+ $code .= sprintf(
+ "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_%s, %d, %d, %s, %d)\n",
+ $funcInfo->name, $funcInfo->return->byRef, $funcInfo->numRequiredArgs,
+ $returnType->name, $returnType->isNullable
+ );
}
} else {
$code .= sprintf(