1 #include "php_snuffleupagus.h"
2 
3 extern ZEND_API zend_class_entry *zend_ce_error;
4 
5 /* This function is needed because `rand` and `mt_rand` parameters
6  * are optional, while the ones from `random_int` aren't. */
random_int_wrapper(INTERNAL_FUNCTION_PARAMETERS)7 static void random_int_wrapper(INTERNAL_FUNCTION_PARAMETERS) {
8   zend_long min = 0;
9   zend_long max = PHP_MT_RAND_MAX;
10   zend_long result;
11 
12   switch (EX_NUM_ARGS()) {
13     case 0:
14       min = 0;
15       max = PHP_MT_RAND_MAX;
16       break;
17     case 1:
18       // LCOV_EXCL_BR_START
19       ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 1, 1);
20       Z_PARAM_LONG(min);
21       /* ZEND_PARSE_PARAMETERS_END call ZEND_PARSE_PARAMETERS_END_EX with
22        * `return` as a callback. As we don't need to strictly parse all
23        * parameters,
24        * we call ZEMD_PARSE_PARAMETERS_END_EX with (void)0 as a callback.
25        * If things go wrong, `php_random_int_throw` will scream anyway.
26        * There might be a better way to do it, please tell us if you know. */
27       ZEND_PARSE_PARAMETERS_END_EX((void)0);
28       // LCOV_EXCL_BR_END
29       max = PHP_MT_RAND_MAX;
30       break;
31     case 2:
32     default:
33       ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 2, 2);
34       Z_PARAM_LONG(min);
35       Z_PARAM_LONG(max);
36       ZEND_PARSE_PARAMETERS_END_EX((void)0);
37   }
38 
39   if (min > max) {
40     if (php_random_int_throw(max, min, &result) == FAILURE) {
41       return;  // LCOV_EXCL_LINE
42     }
43   } else {
44     if (php_random_int_throw(min, max, &result) == FAILURE) {
45       return;  // LCOV_EXCL_LINE
46     }
47   }
48 
49   RETURN_LONG(result);
50 }
51 
PHP_FUNCTION(sp_rand)52 PHP_FUNCTION(sp_rand) {
53   zif_handler orig_handler;
54 
55   /* call the original `rand` function,
56    * since we might no be the only ones to hook it*/
57   orig_handler = zend_hash_str_find_ptr(
58       SNUFFLEUPAGUS_G(sp_internal_functions_hook), "rand", sizeof("rand") - 1);
59   orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
60 
61   random_int_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU);
62 }
63 
PHP_FUNCTION(sp_mt_rand)64 PHP_FUNCTION(sp_mt_rand) {
65   zif_handler orig_handler;
66 
67   /* call the original `mt_rand` function,
68    * since we might no be the only ones to hook it*/
69   orig_handler =
70       zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook),
71                              "mt_rand", sizeof("mt_rand") - 1);
72   orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
73 
74   random_int_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU);
75 }
76 
hook_rand()77 int hook_rand() {
78   TSRMLS_FETCH();
79 
80   HOOK_FUNCTION("rand", sp_internal_functions_hook, PHP_FN(sp_rand));
81   HOOK_FUNCTION("mt_rand", sp_internal_functions_hook, PHP_FN(sp_mt_rand));
82 
83   return SUCCESS;
84 }
85