Coverage Report

Created: 2025-06-13 06:43

/src/php-src/ext/random/engine_user.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
   +----------------------------------------------------------------------+
3
   | Copyright (c) The PHP Group                                          |
4
   +----------------------------------------------------------------------+
5
   | This source file is subject to version 3.01 of the PHP license,      |
6
   | that is bundled with this package in the file LICENSE, and is        |
7
   | available through the world-wide-web at the following url:           |
8
   | https://www.php.net/license/3_01.txt                                 |
9
   | If you did not receive a copy of the PHP license and are unable to   |
10
   | obtain it through the world-wide-web, please send a note to          |
11
   | license@php.net so we can mail you a copy immediately.               |
12
   +----------------------------------------------------------------------+
13
   | Author: Go Kudo <zeriyoshi@php.net>                                  |
14
   +----------------------------------------------------------------------+
15
*/
16
17
#ifdef HAVE_CONFIG_H
18
# include "config.h"
19
#endif
20
21
#include "php.h"
22
#include "php_random.h"
23
24
static php_random_result generate(void *state)
25
0
{
26
0
  php_random_status_state_user *s = state;
27
0
  uint64_t result = 0;
28
0
  size_t size;
29
0
  zval retval;
30
0
  zend_string *zstr;
31
32
0
  zend_call_known_instance_method_with_0_params(s->generate_method, s->object, &retval);
33
34
0
  if (EG(exception)) {
35
0
    return (php_random_result){
36
0
      .size = sizeof(uint64_t),
37
0
      .result = 0,
38
0
    };
39
0
  }
40
41
0
  if (UNEXPECTED(Z_ISREF(retval))) {
42
0
    zstr = Z_STR_P(Z_REFVAL(retval));
43
0
  } else {
44
0
    zstr = Z_STR(retval);
45
0
  }
46
47
  /* Store generated size in a state */
48
0
  size = ZSTR_LEN(zstr);
49
50
  /* Guard for over 64-bit results */
51
0
  if (size > sizeof(uint64_t)) {
52
0
    size = sizeof(uint64_t);
53
0
  }
54
55
0
  if (size > 0) {
56
    /* Endianness safe copy */
57
0
    for (size_t i = 0; i < size; i++) {
58
0
      result += ((uint64_t) (unsigned char) ZSTR_VAL(zstr)[i]) << (8 * i);
59
0
    }
60
0
  } else {
61
0
    zend_throw_error(random_ce_Random_BrokenRandomEngineError, "A random engine must return a non-empty string");
62
0
    zval_ptr_dtor(&retval);
63
0
    return (php_random_result){
64
0
      .size = sizeof(uint64_t),
65
0
      .result = 0,
66
0
    };
67
0
  }
68
69
0
  zval_ptr_dtor(&retval);
70
71
0
  return (php_random_result){
72
0
    .size = size,
73
0
    .result = result,
74
0
  };
75
0
}
76
77
static zend_long range(void *state, zend_long min, zend_long max)
78
0
{
79
0
  return php_random_range((php_random_algo_with_state){
80
0
    .algo = &php_random_algo_user,
81
0
    .state = state,
82
0
  }, min, max);
83
0
}
84
85
PHPAPI const php_random_algo php_random_algo_user = {
86
  sizeof(php_random_status_state_user),
87
  generate,
88
  range,
89
  NULL,
90
  NULL,
91
};