@@ -52,7 +52,7 @@ PHONGO_API zend_class_entry *php_phongo_utcdatetime_ce;
52
52
53
53
zend_object_handlers php_phongo_handler_utcdatetime ;
54
54
55
- /* Initialize the object from an integer and return whether it was successful. */
55
+ /* Initialize the object and return whether it was successful. */
56
56
static bool php_phongo_utcdatetime_init (php_phongo_utcdatetime_t * intern , int64_t milliseconds )
57
57
{
58
58
intern -> milliseconds = milliseconds ;
@@ -61,8 +61,39 @@ static bool php_phongo_utcdatetime_init(php_phongo_utcdatetime_t *intern, int64_
61
61
return true;
62
62
}
63
63
64
- /* Initialize the object from a HashTable and return whether it was successful. */
65
- static bool php_phongo_utcdatetime_init_from_hash (php_phongo_utcdatetime_t * intern , HashTable * props )
64
+ /* Initialize the object from a numeric string and return whether it was
65
+ * successful. An exception will be thrown on error. */
66
+ static bool php_phongo_utcdatetime_init_from_string (php_phongo_utcdatetime_t * intern , const char * s_milliseconds , phongo_zpp_char_len s_milliseconds_len TSRMLS_DC )
67
+ {
68
+ int64_t milliseconds ;
69
+ char * endptr = NULL ;
70
+
71
+ errno = 0 ;
72
+
73
+ #if defined(PHP_WIN32 )
74
+ milliseconds = _atoi64 (s );
75
+ #else
76
+ milliseconds = bson_ascii_strtoll (s_milliseconds , & endptr , 10 );
77
+ #endif
78
+
79
+ /* errno will set errno if conversion fails; however, we do not need to
80
+ * specify the type of error.
81
+ *
82
+ * Note: bson_ascii_strtoll() does not properly detect out-of-range values
83
+ * (see: CDRIVER-1377). strtoll() would be preferable, but it is not
84
+ * available on all platforms (e.g. HP-UX), and atoll() provides no error
85
+ * reporting at all. */
86
+ if (errno || (endptr && endptr != ((const char * )s_milliseconds + s_milliseconds_len ))) {
87
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Error parsing \"%s\" as 64-bit integer for %s initialization" , s_milliseconds , ZSTR_VAL (php_phongo_utcdatetime_ce -> name ));
88
+ return false;
89
+ }
90
+
91
+ return php_phongo_utcdatetime_init (intern , milliseconds );
92
+ }
93
+
94
+ /* Initialize the object from a HashTable and return whether it was successful.
95
+ * An exception will be thrown on error. */
96
+ static bool php_phongo_utcdatetime_init_from_hash (php_phongo_utcdatetime_t * intern , HashTable * props TSRMLS_DC )
66
97
{
67
98
#if PHP_VERSION_ID >= 70000
68
99
zval * milliseconds ;
@@ -72,7 +103,7 @@ static bool php_phongo_utcdatetime_init_from_hash(php_phongo_utcdatetime_t *inte
72
103
}
73
104
74
105
if ((milliseconds = zend_hash_str_find (props , "milliseconds" , sizeof ("milliseconds" )- 1 )) && Z_TYPE_P (milliseconds ) == IS_STRING ) {
75
- return php_phongo_utcdatetime_init (intern , STRTOLL ( Z_STRVAL_P (milliseconds )) );
106
+ return php_phongo_utcdatetime_init_from_string (intern , Z_STRVAL_P (milliseconds ), Z_STRLEN_P ( milliseconds ) TSRMLS_CC );
76
107
}
77
108
#else
78
109
zval * * milliseconds ;
@@ -82,13 +113,16 @@ static bool php_phongo_utcdatetime_init_from_hash(php_phongo_utcdatetime_t *inte
82
113
}
83
114
84
115
if (zend_hash_find (props , "milliseconds" , sizeof ("milliseconds" ), (void * * ) & milliseconds ) == SUCCESS && Z_TYPE_PP (milliseconds ) == IS_STRING ) {
85
- return php_phongo_utcdatetime_init (intern , STRTOLL ( Z_STRVAL_PP (milliseconds )) );
116
+ return php_phongo_utcdatetime_init_from_string (intern , Z_STRVAL_PP (milliseconds ), Z_STRLEN_PP ( milliseconds ) TSRMLS_CC );
86
117
}
87
118
#endif
119
+
120
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "%s initialization requires \"milliseconds\" integer or numeric string field" , ZSTR_VAL (php_phongo_utcdatetime_ce -> name ));
88
121
return false;
89
122
}
90
123
91
- /* Initialize the object from the current time and return whether it was successful. */
124
+ /* Initialize the object from the current time and return whether it was
125
+ * successful. */
92
126
static bool php_phongo_utcdatetime_init_from_current_time (php_phongo_utcdatetime_t * intern )
93
127
{
94
128
int64_t sec , usec ;
@@ -104,7 +138,8 @@ static bool php_phongo_utcdatetime_init_from_current_time(php_phongo_utcdatetime
104
138
return true;
105
139
}
106
140
107
- /* Initialize the object from a DateTime object and return whether it was successful. */
141
+ /* Initialize the object from a DateTime object and return whether it was
142
+ * successful. */
108
143
static bool php_phongo_utcdatetime_init_from_date (php_phongo_utcdatetime_t * intern , php_date_obj * datetime_obj )
109
144
{
110
145
int64_t sec , usec ;
@@ -168,7 +203,7 @@ PHP_METHOD(UTCDateTime, __construct)
168
203
return ;
169
204
}
170
205
171
- php_phongo_utcdatetime_init (intern , STRTOLL ( s_milliseconds ) );
206
+ php_phongo_utcdatetime_init_from_string (intern , s_milliseconds , s_milliseconds_len );
172
207
}
173
208
#else
174
209
# error Unsupported architecture (integers are neither 32-bit nor 64-bit)
@@ -196,9 +231,7 @@ PHP_METHOD(UTCDateTime, __set_state)
196
231
intern = Z_UTCDATETIME_OBJ_P (return_value );
197
232
props = Z_ARRVAL_P (array );
198
233
199
- if (!php_phongo_utcdatetime_init_from_hash (intern , props )) {
200
- php_error (E_ERROR , "Invalid serialization data for UTCDateTime object" );
201
- }
234
+ php_phongo_utcdatetime_init_from_hash (intern , props TSRMLS_CC );
202
235
}
203
236
/* }}} */
204
237
@@ -237,9 +270,7 @@ PHP_METHOD(UTCDateTime, __wakeup)
237
270
intern = Z_UTCDATETIME_OBJ_P (getThis ());
238
271
props = zend_std_get_properties (getThis () TSRMLS_CC );
239
272
240
- if (!php_phongo_utcdatetime_init_from_hash (intern , props )) {
241
- php_error (E_ERROR , "Invalid serialization data for UTCDateTime object" );
242
- }
273
+ php_phongo_utcdatetime_init_from_hash (intern , props TSRMLS_CC );
243
274
}
244
275
/* }}} */
245
276
0 commit comments