@@ -258,6 +258,49 @@ ZEND_API int zend_get_object_classname(const zval *object, const char **class_na
258258}
259259/* }}} */
260260
261+ static int parse_arg_object_to_string (zval * * arg , char * * p , int * pl , int type TSRMLS_DC ) /* {{{ */
262+ {
263+ if (Z_OBJ_HANDLER_PP (arg , cast_object )) {
264+ zval * obj ;
265+ MAKE_STD_ZVAL (obj );
266+ if (Z_OBJ_HANDLER_P (* arg , cast_object )(* arg , obj , type TSRMLS_CC ) == SUCCESS ) {
267+ zval_ptr_dtor (arg );
268+ * arg = obj ;
269+ * pl = Z_STRLEN_PP (arg );
270+ * p = Z_STRVAL_PP (arg );
271+ return SUCCESS ;
272+ }
273+ efree (obj );
274+ }
275+ /* Standard PHP objects */
276+ if (Z_OBJ_HT_PP (arg ) == & std_object_handlers || !Z_OBJ_HANDLER_PP (arg , cast_object )) {
277+ SEPARATE_ZVAL_IF_NOT_REF (arg );
278+ if (zend_std_cast_object_tostring (* arg , * arg , type TSRMLS_CC ) == SUCCESS ) {
279+ * pl = Z_STRLEN_PP (arg );
280+ * p = Z_STRVAL_PP (arg );
281+ return SUCCESS ;
282+ }
283+ }
284+ if (!Z_OBJ_HANDLER_PP (arg , cast_object ) && Z_OBJ_HANDLER_PP (arg , get )) {
285+ int use_copy ;
286+ zval * z = Z_OBJ_HANDLER_PP (arg , get )(* arg TSRMLS_CC );
287+ Z_ADDREF_P (z );
288+ if (Z_TYPE_P (z ) != IS_OBJECT ) {
289+ zval_dtor (* arg );
290+ Z_TYPE_P (* arg ) = IS_NULL ;
291+ zend_make_printable_zval (z , * arg , & use_copy );
292+ if (!use_copy ) {
293+ ZVAL_ZVAL (* arg , z , 1 , 1 );
294+ }
295+ * pl = Z_STRLEN_PP (arg );
296+ * p = Z_STRVAL_PP (arg );
297+ return SUCCESS ;
298+ }
299+ zval_ptr_dtor (& z );
300+ }
301+ return FAILURE ;
302+ }
303+ /* }}} */
261304
262305static const char * zend_parse_arg_impl (int arg_num , zval * * arg , va_list * va , const char * * spec , char * * error , int * severity TSRMLS_DC ) /* {{{ */
263306{
@@ -284,45 +327,160 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
284327 case 'L' :
285328 {
286329 long * p = va_arg (* va , long * );
287- if (FAILURE == convert_to_long_safe_ex (arg )) {
288- return "long" ;
330+ switch (Z_TYPE_PP (arg )) {
331+ case IS_STRING :
332+ {
333+ double d ;
334+ int type ;
335+
336+ if ((type = is_numeric_string (Z_STRVAL_PP (arg ), Z_STRLEN_PP (arg ), p , & d , -1 )) == 0 ) {
337+ return "long" ;
338+ } else if (type == IS_DOUBLE ) {
339+ if (c == 'L' ) {
340+ if (d > LONG_MAX ) {
341+ * p = LONG_MAX ;
342+ break ;
343+ } else if (d < LONG_MIN ) {
344+ * p = LONG_MIN ;
345+ break ;
346+ }
347+ }
348+
349+ * p = zend_dval_to_lval (d );
350+ }
351+ }
352+ break ;
353+
354+ case IS_DOUBLE :
355+ if (c == 'L' ) {
356+ if (Z_DVAL_PP (arg ) > LONG_MAX ) {
357+ * p = LONG_MAX ;
358+ break ;
359+ } else if (Z_DVAL_PP (arg ) < LONG_MIN ) {
360+ * p = LONG_MIN ;
361+ break ;
362+ }
363+ }
364+ case IS_NULL :
365+ case IS_LONG :
366+ case IS_BOOL :
367+ convert_to_long_ex (arg );
368+ * p = Z_LVAL_PP (arg );
369+ break ;
370+
371+ case IS_ARRAY :
372+ case IS_OBJECT :
373+ case IS_RESOURCE :
374+ default :
375+ return "long" ;
289376 }
290- * p = Z_LVAL_PP (arg );
291- break ;
292377 }
378+ break ;
379+
293380 case 'd' :
294381 {
295382 double * p = va_arg (* va , double * );
296- if (FAILURE == convert_to_double_safe_ex (arg )) {
297- return "double" ;
383+ switch (Z_TYPE_PP (arg )) {
384+ case IS_STRING :
385+ {
386+ long l ;
387+ int type ;
388+
389+ if ((type = is_numeric_string (Z_STRVAL_PP (arg ), Z_STRLEN_PP (arg ), & l , p , -1 )) == 0 ) {
390+ return "double" ;
391+ } else if (type == IS_LONG ) {
392+ * p = (double ) l ;
393+ }
394+ }
395+ break ;
396+
397+ case IS_NULL :
398+ case IS_LONG :
399+ case IS_DOUBLE :
400+ case IS_BOOL :
401+ convert_to_double_ex (arg );
402+ * p = Z_DVAL_PP (arg );
403+ break ;
404+
405+ case IS_ARRAY :
406+ case IS_OBJECT :
407+ case IS_RESOURCE :
408+ default :
409+ return "double" ;
298410 }
299- * p = Z_DVAL_PP (arg );
300- break ;
301411 }
412+ break ;
413+
302414 case 'p' :
303415 case 's' :
304416 {
305417 char * * p = va_arg (* va , char * * );
306418 int * pl = va_arg (* va , int * );
307- if (FAILURE == convert_to_string_safe_ex (arg )) {
308- return c == 's' ? "string" : "a valid path" ;
309- }
310- if (c == 'p' && CHECK_ZVAL_NULL_PATH (* arg )) {
311- return "a valid path" ;
419+ switch (Z_TYPE_PP (arg )) {
420+ case IS_NULL :
421+ if (return_null ) {
422+ * p = NULL ;
423+ * pl = 0 ;
424+ break ;
425+ }
426+ /* break omitted intentionally */
427+
428+ case IS_STRING :
429+ case IS_LONG :
430+ case IS_DOUBLE :
431+ case IS_BOOL :
432+ convert_to_string_ex (arg );
433+ if (UNEXPECTED (Z_ISREF_PP (arg ) != 0 )) {
434+ /* it's dangerous to return pointers to string
435+ buffer of referenced variable, because it can
436+ be clobbered throug magic callbacks */
437+ SEPARATE_ZVAL (arg );
438+ }
439+ * p = Z_STRVAL_PP (arg );
440+ * pl = Z_STRLEN_PP (arg );
441+ if (c == 'p' && CHECK_ZVAL_NULL_PATH (* arg )) {
442+ return "a valid path" ;
443+ }
444+ break ;
445+
446+ case IS_OBJECT :
447+ if (parse_arg_object_to_string (arg , p , pl , IS_STRING TSRMLS_CC ) == SUCCESS ) {
448+ if (c == 'p' && CHECK_ZVAL_NULL_PATH (* arg )) {
449+ return "a valid path" ;
450+ }
451+ break ;
452+ }
453+
454+ case IS_ARRAY :
455+ case IS_RESOURCE :
456+ default :
457+ return c == 's' ? "string" : "a valid path" ;
312458 }
313- * p = Z_STRVAL_PP (arg );
314- * pl = Z_STRLEN_PP (arg );
315- break ;
316459 }
460+ break ;
461+
317462 case 'b' :
318463 {
319464 zend_bool * p = va_arg (* va , zend_bool * );
320- if (FAILURE == convert_to_boolean_safe_ex (arg )) {
321- return "boolean" ;
465+ switch (Z_TYPE_PP (arg )) {
466+ case IS_NULL :
467+ case IS_STRING :
468+ case IS_LONG :
469+ case IS_DOUBLE :
470+ case IS_BOOL :
471+ convert_to_boolean_ex (arg );
472+ * p = Z_BVAL_PP (arg );
473+ break ;
474+
475+ case IS_ARRAY :
476+ case IS_OBJECT :
477+ case IS_RESOURCE :
478+ default :
479+ return "boolean" ;
322480 }
323- * p = Z_BVAL_PP (arg );
324- break ;
325481 }
482+ break ;
483+
326484 case 'r' :
327485 {
328486 zval * * p = va_arg (* va , zval * * );
0 commit comments