]> granicus.if.org Git - php/commitdiff
Make uninitialized DateTime an Error
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 9 Aug 2019 12:33:59 +0000 (14:33 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 9 Aug 2019 12:51:25 +0000 (14:51 +0200)
This avoids many spurious false return values.

ext/date/php_date.c
ext/date/php_date.stub.php
ext/date/php_date_arginfo.h
ext/date/tests/bug48476.phpt
ext/date/tests/bug67118.phpt
ext/date/tests/oo_001.phpt
ext/intl/tests/dateformat_formatObject_error.phpt
scripts/dev/gen_stub.php

index aa457065d404c69fe7c37e44111e84802e765df4..c3ffeba725a127c093f289df3d7a6cf8dd892405 100644 (file)
@@ -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);
index 1d448b91029c94620522b593b8c3f72a4f6928ea..667cbc1b91fa45408f2bca8dd76da18b5e3adf96 100644 (file)
@@ -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();
index 70381437c7591eb4d7176f50091620eb45f09e26..841ff28a6e05cad5834ab73b5e5bfac032bc4bad 100644 (file)
@@ -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
 
index 1335025c76b447053381e8e5a408a55169d30b89..02086e0e56f94fc1b2a505a8f11ac0ba0f0aedf7 100644 (file)
@@ -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
index 332142856e42b707fd106fc165f9c294c52a30ef..5a7d2d1d076f6ea8464cc65a1a0fb0f67a0d2714 100644 (file)
@@ -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
index 7cbf847c528b6cea6eed176b31ae94f4e6f270d3..111364ec833624be82d958b58f30c07259ed69bf 100644 (file)
@@ -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
index 24be090035841c06b84a4e041afb3ec53a790b07..7c1140c09d5eba4e13017bbe347bff367efd932b 100644 (file)
@@ -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)
index 9a71e7db82ac5394210a08c279feaf4869291ba2..59b7d448f6769235e1334110e2a2b97c9cbbaa5b 100755 (executable)
@@ -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(