3232ZEND_DECLARE_MODULE_GLOBALS (bcmath )
3333static PHP_GINIT_FUNCTION (bcmath );
3434static PHP_GSHUTDOWN_FUNCTION (bcmath );
35+ static PHP_MINIT_FUNCTION (bcmath );
36+ static PHP_MSHUTDOWN_FUNCTION (bcmath );
37+ static PHP_MINFO_FUNCTION (bcmath );
3538
3639zend_module_entry bcmath_module_entry = {
3740 STANDARD_MODULE_HEADER ,
@@ -341,15 +344,13 @@ PHP_FUNCTION(bcdiv)
341344 goto cleanup ;
342345 }
343346
344- switch (bc_divide (first , second , & result , scale )) {
345- case 0 : /* OK */
346- RETVAL_STR (bc_num2str_ex (result , scale ));
347- break ;
348- case -1 : /* division by zero */
349- zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Division by zero" );
350- break ;
347+ if (!bc_divide (first , second , & result , scale )) {
348+ zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Division by zero" );
349+ goto cleanup ;
351350 }
352351
352+ RETVAL_STR (bc_num2str_ex (result , scale ));
353+
353354 cleanup : {
354355 bc_free_num (& first );
355356 bc_free_num (& second );
@@ -397,15 +398,13 @@ PHP_FUNCTION(bcmod)
397398 goto cleanup ;
398399 }
399400
400- switch (bc_modulo (first , second , & result , scale )) {
401- case 0 :
402- RETVAL_STR (bc_num2str_ex (result , scale ));
403- break ;
404- case -1 :
405- zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Modulo by zero" );
406- break ;
401+ if (!bc_modulo (first , second , & result , scale )) {
402+ zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Modulo by zero" );
403+ goto cleanup ;
407404 }
408405
406+ RETVAL_STR (bc_num2str_ex (result , scale ));
407+
409408 cleanup : {
410409 bc_free_num (& first );
411410 bc_free_num (& second );
@@ -417,16 +416,16 @@ PHP_FUNCTION(bcmod)
417416/* {{{ Returns the value of an arbitrary precision number raised to the power of another reduced by a modulus */
418417PHP_FUNCTION (bcpowmod )
419418{
420- zend_string * left , * right , * modulus ;
419+ zend_string * base_str , * exponent_str , * modulus_str ;
421420 zend_long scale_param ;
422421 bool scale_param_is_null = 1 ;
423- bc_num first , second , mod , result ;
422+ bc_num bc_base , bc_expo , bc_modulus , result ;
424423 int scale = BCG (bc_precision );
425424
426425 ZEND_PARSE_PARAMETERS_START (3 , 4 )
427- Z_PARAM_STR (left )
428- Z_PARAM_STR (right )
429- Z_PARAM_STR (modulus )
426+ Z_PARAM_STR (base_str )
427+ Z_PARAM_STR (exponent_str )
428+ Z_PARAM_STR (modulus_str )
430429 Z_PARAM_OPTIONAL
431430 Z_PARAM_LONG_OR_NULL (scale_param , scale_param_is_null )
432431 ZEND_PARSE_PARAMETERS_END ();
@@ -440,34 +439,53 @@ PHP_FUNCTION(bcpowmod)
440439 scale = (int ) scale_param ;
441440 }
442441
443- bc_init_num (& first );
444- bc_init_num (& second );
445- bc_init_num (& mod );
442+ bc_init_num (& bc_base );
443+ bc_init_num (& bc_expo );
444+ bc_init_num (& bc_modulus );
446445 bc_init_num (& result );
447446
448- if (php_str2num (& first , ZSTR_VAL (left )) == FAILURE ) {
447+ if (php_str2num (& bc_base , ZSTR_VAL (base_str )) == FAILURE ) {
449448 zend_argument_value_error (1 , "is not well-formed" );
450449 goto cleanup ;
451450 }
452451
453- if (php_str2num (& second , ZSTR_VAL (right )) == FAILURE ) {
452+ if (php_str2num (& bc_expo , ZSTR_VAL (exponent_str )) == FAILURE ) {
454453 zend_argument_value_error (2 , "is not well-formed" );
455454 goto cleanup ;
456455 }
457456
458- if (php_str2num (& mod , ZSTR_VAL (modulus )) == FAILURE ) {
457+ if (php_str2num (& bc_modulus , ZSTR_VAL (modulus_str )) == FAILURE ) {
459458 zend_argument_value_error (3 , "is not well-formed" );
460459 goto cleanup ;
461460 }
462461
463- if (bc_raisemod (first , second , mod , & result , scale ) == SUCCESS ) {
464- RETVAL_STR (bc_num2str_ex (result , scale ));
462+ raise_mod_status status = bc_raisemod (bc_base , bc_expo , bc_modulus , & result , scale );
463+ switch (status ) {
464+ case BASE_HAS_FRACTIONAL :
465+ zend_argument_value_error (1 , "cannot have a fractional part" );
466+ goto cleanup ;
467+ case EXPO_HAS_FRACTIONAL :
468+ zend_argument_value_error (2 , "cannot have a fractional part" );
469+ goto cleanup ;
470+ case EXPO_IS_NEGATIVE :
471+ zend_argument_value_error (2 , "must be greater than or equal to 0" );
472+ goto cleanup ;
473+ case MOD_HAS_FRACTIONAL :
474+ zend_argument_value_error (3 , "cannot have a fractional part" );
475+ goto cleanup ;
476+ case MOD_IS_ZERO :
477+ zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Modulo by zero" );
478+ goto cleanup ;
479+ case OK :
480+ RETVAL_STR (bc_num2str_ex (result , scale ));
481+ break ;
482+ EMPTY_SWITCH_DEFAULT_CASE ();
465483 }
466484
467485 cleanup : {
468- bc_free_num (& first );
469- bc_free_num (& second );
470- bc_free_num (& mod );
486+ bc_free_num (& bc_base );
487+ bc_free_num (& bc_expo );
488+ bc_free_num (& bc_modulus );
471489 bc_free_num (& result );
472490 };
473491}
@@ -476,15 +494,15 @@ PHP_FUNCTION(bcpowmod)
476494/* {{{ Returns the value of an arbitrary precision number raised to the power of another */
477495PHP_FUNCTION (bcpow )
478496{
479- zend_string * left , * right ;
497+ zend_string * base_str , * exponent_str ;
480498 zend_long scale_param ;
481499 bool scale_param_is_null = 1 ;
482- bc_num first , second , result ;
500+ bc_num first , bc_exponent , result ;
483501 int scale = BCG (bc_precision );
484502
485503 ZEND_PARSE_PARAMETERS_START (2 , 3 )
486- Z_PARAM_STR (left )
487- Z_PARAM_STR (right )
504+ Z_PARAM_STR (base_str )
505+ Z_PARAM_STR (exponent_str )
488506 Z_PARAM_OPTIONAL
489507 Z_PARAM_LONG_OR_NULL (scale_param , scale_param_is_null )
490508 ZEND_PARSE_PARAMETERS_END ();
@@ -499,26 +517,37 @@ PHP_FUNCTION(bcpow)
499517 }
500518
501519 bc_init_num (& first );
502- bc_init_num (& second );
520+ bc_init_num (& bc_exponent );
503521 bc_init_num (& result );
504522
505- if (php_str2num (& first , ZSTR_VAL (left )) == FAILURE ) {
523+ if (php_str2num (& first , ZSTR_VAL (base_str )) == FAILURE ) {
506524 zend_argument_value_error (1 , "is not well-formed" );
507525 goto cleanup ;
508526 }
509527
510- if (php_str2num (& second , ZSTR_VAL (right )) == FAILURE ) {
528+ if (php_str2num (& bc_exponent , ZSTR_VAL (exponent_str )) == FAILURE ) {
511529 zend_argument_value_error (2 , "is not well-formed" );
512530 goto cleanup ;
513531 }
514532
515- bc_raise (first , second , & result , scale );
533+ /* Check the exponent for scale digits and convert to a long. */
534+ if (bc_exponent -> n_scale != 0 ) {
535+ zend_argument_value_error (2 , "cannot have a fractional part" );
536+ goto cleanup ;
537+ }
538+ long exponent = bc_num2long (bc_exponent );
539+ if (exponent == 0 && (bc_exponent -> n_len > 1 || bc_exponent -> n_value [0 ] != 0 )) {
540+ zend_argument_value_error (2 , "is too large" );
541+ goto cleanup ;
542+ }
543+
544+ bc_raise (first , exponent , & result , scale );
516545
517546 RETVAL_STR (bc_num2str_ex (result , scale ));
518547
519548 cleanup : {
520549 bc_free_num (& first );
521- bc_free_num (& second );
550+ bc_free_num (& bc_exponent );
522551 bc_free_num (& result );
523552 };
524553}
0 commit comments