@@ -387,16 +387,20 @@ php_sprintf_getnumber(char **buffer, size_t *len)
387
387
* "x" integer argument is printed as lowercase hexadecimal
388
388
* "X" integer argument is printed as uppercase hexadecimal
389
389
*
390
+ * nb_additional_parameters is used for throwing errors:
391
+ * - -1: ValueError is thrown (for vsprintf where args originates from an array)
392
+ * - 0 or more: ArgumentCountError is thrown
390
393
*/
391
394
static zend_string *
392
- php_formatted_print (zval * z_format , zval * args , int argc )
395
+ php_formatted_print (zval * z_format , zval * args , int argc , int nb_additional_parameters )
393
396
{
394
397
size_t size = 240 , outpos = 0 ;
395
398
int alignment , currarg , adjusting , argnum , width , precision ;
396
399
char * format , * temppos , padding ;
397
400
zend_string * result ;
398
401
int always_sign ;
399
402
size_t format_len ;
403
+ int bad_arg_number = 0 ;
400
404
401
405
if (!try_convert_to_string (z_format )) {
402
406
return NULL ;
@@ -407,6 +411,7 @@ php_formatted_print(zval *z_format, zval *args, int argc)
407
411
result = zend_string_alloc (size , 0 );
408
412
409
413
currarg = 0 ;
414
+ argnum = 0 ;
410
415
411
416
while (format_len ) {
412
417
int expprec ;
@@ -450,7 +455,7 @@ php_formatted_print(zval *z_format, zval *args, int argc)
450
455
451
456
if (argnum <= 0 ) {
452
457
zend_string_efree (result );
453
- php_error_docref ( NULL , E_WARNING , "Argument number must be greater than zero" );
458
+ zend_value_error ( "Argument number must be greater than zero" );
454
459
return NULL ;
455
460
}
456
461
argnum -- ;
@@ -491,7 +496,7 @@ php_formatted_print(zval *z_format, zval *args, int argc)
491
496
PRINTF_DEBUG (("sprintf: getting width\n" ));
492
497
if ((width = php_sprintf_getnumber (& format , & format_len )) < 0 ) {
493
498
efree (result );
494
- php_error_docref ( NULL , E_WARNING , "Width must be greater than zero and less than %d" , INT_MAX );
499
+ zend_value_error ( "Width must be greater than zero and less than %d" , INT_MAX );
495
500
return NULL ;
496
501
}
497
502
adjusting |= ADJ_WIDTH ;
@@ -508,7 +513,7 @@ php_formatted_print(zval *z_format, zval *args, int argc)
508
513
if (isdigit ((int )* format )) {
509
514
if ((precision = php_sprintf_getnumber (& format , & format_len )) < 0 ) {
510
515
efree (result );
511
- php_error_docref ( NULL , E_WARNING , "Precision must be greater than zero and less than %d" , INT_MAX );
516
+ zend_value_error ( "Precision must be greater than zero and less than %d" , INT_MAX );
512
517
return NULL ;
513
518
}
514
519
adjusting |= ADJ_PRECISION ;
@@ -522,17 +527,17 @@ php_formatted_print(zval *z_format, zval *args, int argc)
522
527
PRINTF_DEBUG (("sprintf: precision=%d\n" , precision ));
523
528
}
524
529
525
- if (argnum >= argc ) {
526
- efree (result );
527
- php_error_docref (NULL , E_WARNING , "Too few arguments" );
528
- return NULL ;
529
- }
530
-
531
530
if (* format == 'l' ) {
532
531
format ++ ;
533
532
format_len -- ;
534
533
}
535
534
PRINTF_DEBUG (("sprintf: format character='%c'\n" , * format ));
535
+
536
+ if (argnum >= argc ) {
537
+ bad_arg_number = 1 ;
538
+ continue ;
539
+ }
540
+
536
541
/* now we expect to find a type specifier */
537
542
tmp = & args [argnum ];
538
543
switch (* format ) {
@@ -628,6 +633,16 @@ php_formatted_print(zval *z_format, zval *args, int argc)
628
633
}
629
634
}
630
635
636
+ if (bad_arg_number == 1 ) {
637
+ efree (result );
638
+ if (nb_additional_parameters == -1 ) {
639
+ zend_value_error ("The arguments array must contain %d items, %d given" , argnum + 1 , argc );
640
+ } else {
641
+ zend_argument_count_error ("%d parameters are required, %d given" , argnum + nb_additional_parameters + 1 , argc + nb_additional_parameters );
642
+ }
643
+ return NULL ;
644
+ }
645
+
631
646
exit :
632
647
/* possibly, we have to make sure we have room for the terminating null? */
633
648
ZSTR_VAL (result )[outpos ]= 0 ;
@@ -660,7 +675,7 @@ php_formatted_print_get_array(zval *array, int *argc)
660
675
}
661
676
/* }}} */
662
677
663
- /* {{{ proto string|false sprintf(string format [, mixed arg1 [, mixed ...]])
678
+ /* {{{ proto string sprintf(string format [, mixed arg1 [, mixed ...]])
664
679
Return a formatted string */
665
680
PHP_FUNCTION (user_sprintf )
666
681
{
@@ -673,15 +688,15 @@ PHP_FUNCTION(user_sprintf)
673
688
Z_PARAM_VARIADIC ('*' , args , argc )
674
689
ZEND_PARSE_PARAMETERS_END ();
675
690
676
- result = php_formatted_print (format , args , argc );
691
+ result = php_formatted_print (format , args , argc , 1 );
677
692
if (result == NULL ) {
678
- RETURN_FALSE ;
693
+ return ;
679
694
}
680
695
RETVAL_STR (result );
681
696
}
682
697
/* }}} */
683
698
684
- /* {{{ proto string|false vsprintf(string format, array args)
699
+ /* {{{ proto string vsprintf(string format, array args)
685
700
Return a formatted string */
686
701
PHP_FUNCTION (vsprintf )
687
702
{
@@ -696,16 +711,16 @@ PHP_FUNCTION(vsprintf)
696
711
697
712
args = php_formatted_print_get_array (array , & argc );
698
713
699
- result = php_formatted_print (format , args , argc );
714
+ result = php_formatted_print (format , args , argc , -1 );
700
715
efree (args );
701
716
if (result == NULL ) {
702
- RETURN_FALSE ;
717
+ return ;
703
718
}
704
719
RETVAL_STR (result );
705
720
}
706
721
/* }}} */
707
722
708
- /* {{{ proto int|false printf(string format [, mixed arg1 [, mixed ...]])
723
+ /* {{{ proto int printf(string format [, mixed arg1 [, mixed ...]])
709
724
Output a formatted string */
710
725
PHP_FUNCTION (user_printf )
711
726
{
@@ -719,17 +734,17 @@ PHP_FUNCTION(user_printf)
719
734
Z_PARAM_VARIADIC ('*' , args , argc )
720
735
ZEND_PARSE_PARAMETERS_END ();
721
736
722
- result = php_formatted_print (format , args , argc );
737
+ result = php_formatted_print (format , args , argc , 1 );
723
738
if (result == NULL ) {
724
- RETURN_FALSE ;
739
+ return ;
725
740
}
726
741
rlen = PHPWRITE (ZSTR_VAL (result ), ZSTR_LEN (result ));
727
742
zend_string_efree (result );
728
743
RETURN_LONG (rlen );
729
744
}
730
745
/* }}} */
731
746
732
- /* {{{ proto int|false vprintf(string format, array args)
747
+ /* {{{ proto int vprintf(string format, array args)
733
748
Output a formatted string */
734
749
PHP_FUNCTION (vprintf )
735
750
{
@@ -745,18 +760,18 @@ PHP_FUNCTION(vprintf)
745
760
746
761
args = php_formatted_print_get_array (array , & argc );
747
762
748
- result = php_formatted_print (format , args , argc );
763
+ result = php_formatted_print (format , args , argc , -1 );
749
764
efree (args );
750
765
if (result == NULL ) {
751
- RETURN_FALSE ;
766
+ return ;
752
767
}
753
768
rlen = PHPWRITE (ZSTR_VAL (result ), ZSTR_LEN (result ));
754
769
zend_string_efree (result );
755
770
RETURN_LONG (rlen );
756
771
}
757
772
/* }}} */
758
773
759
- /* {{{ proto int|false fprintf(resource stream, string format [, mixed arg1 [, mixed ...]])
774
+ /* {{{ proto int fprintf(resource stream, string format [, mixed arg1 [, mixed ...]])
760
775
Output a formatted string into a stream */
761
776
PHP_FUNCTION (fprintf )
762
777
{
@@ -777,9 +792,9 @@ PHP_FUNCTION(fprintf)
777
792
778
793
php_stream_from_zval (stream , arg1 );
779
794
780
- result = php_formatted_print (format , args , argc );
795
+ result = php_formatted_print (format , args , argc , 2 );
781
796
if (result == NULL ) {
782
- RETURN_FALSE ;
797
+ return ;
783
798
}
784
799
785
800
php_stream_write (stream , ZSTR_VAL (result ), ZSTR_LEN (result ));
@@ -789,7 +804,7 @@ PHP_FUNCTION(fprintf)
789
804
}
790
805
/* }}} */
791
806
792
- /* {{{ proto int|false vfprintf(resource stream, string format, array args)
807
+ /* {{{ proto int vfprintf(resource stream, string format, array args)
793
808
Output a formatted string into a stream */
794
809
PHP_FUNCTION (vfprintf )
795
810
{
@@ -812,10 +827,10 @@ PHP_FUNCTION(vfprintf)
812
827
813
828
args = php_formatted_print_get_array (array , & argc );
814
829
815
- result = php_formatted_print (format , args , argc );
830
+ result = php_formatted_print (format , args , argc , -1 );
816
831
efree (args );
817
832
if (result == NULL) {
818
- RETURN_FALSE ;
833
+ return ;
819
834
}
820
835
821
836
php_stream_write (stream , ZSTR_VAL (result ), ZSTR_LEN (result ));
0 commit comments