summaryrefslogtreecommitdiff
path: root/src/sp_harden_rand.c
blob: e0e35fff68bcb5728c19ba27f29279b62323906e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include "php_snuffleupagus.h"

extern ZEND_API zend_class_entry *zend_ce_error;

ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus)

/* This function is needed because `rand` and `mt_rand` parameters
 * are optional, while the ones from `random_int` aren't. */
static void random_int_wrapper(INTERNAL_FUNCTION_PARAMETERS) {
  zend_long min, max, result;

  switch (EX_NUM_ARGS()) {
  case 0:
    min = 0;
    max = PHP_MT_RAND_MAX;
    break;
  case 1:
    ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 1, 1);
    Z_PARAM_LONG(min);
    ZEND_PARSE_PARAMETERS_END();
    max = PHP_MT_RAND_MAX;
    break;
  case 2:
  default:
    ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 0, 2);
    Z_PARAM_LONG(min);
    Z_PARAM_LONG(max);
    ZEND_PARSE_PARAMETERS_END();
  }

  if (min > max) {
    if (php_random_int_throw(max, min, &result) == FAILURE) {
      return;
    }
  } else {
    if (php_random_int_throw(min, max, &result) == FAILURE) {
      return;
    }
  }

  RETURN_LONG(result);
}

PHP_FUNCTION(sp_rand) {
  void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS);

  if ((orig_handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), "rand",
                                             strlen("rand")))) {
    /* call the original `rand` function,
     * since we might no be the only ones to hook it*/
    orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  }

  random_int_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}

PHP_FUNCTION(sp_mt_rand) {
  void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS);

  if ((orig_handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook),
                                             "mt_rand", strlen("mt_rand")))) {
    /* call the original `mt_rand` function,
     * since we might no be the only ones to hook it*/
    orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  }

  random_int_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}

int hook_rand() {
  TSRMLS_FETCH();

  HOOK_FUNCTION("rand", sp_internal_functions_hook, PHP_FN(sp_rand), false);
  HOOK_FUNCTION("mt_rand", sp_internal_functions_hook, PHP_FN(sp_mt_rand), false);

  return SUCCESS;
}