{"record":{"id":"29df9f7dd9d02d23","repo":"paragonie/random_compat","slug":"random-bytes-bytes-must-be-an-integer-mcrypt","errorCode":null,"errorMessage":"random_bytes(): $bytes must be an integer","messagePattern":"random_bytes\\(\\): \\$bytes must be an integer","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/random_bytes_mcrypt.php","lineNumber":48,"sourceCode":"    /**\n     * Powered by ext/mcrypt (and thankfully NOT libmcrypt)\n     *\n     * @ref https://bugs.php.net/bug.php?id=55169\n     * @ref https://github.com/php/php-src/blob/c568ffe5171d942161fc8dda066bce844bdef676/ext/mcrypt/mcrypt.c#L1321-L1386\n     *\n     * @param int $bytes\n     *\n     * @throws Exception\n     *\n     * @return string\n     */\n    function random_bytes($bytes)\n    {\n        try {\n            /** @var int $bytes */\n            $bytes = RandomCompat_intval($bytes);\n        } catch (TypeError $ex) {\n            throw new TypeError(\n                'random_bytes(): $bytes must be an integer'\n            );\n        }\n\n        if ($bytes < 1) {\n            throw new Error(\n                'Length must be greater than 0'\n            );\n        }\n\n        /** @var string|bool $buf */\n        $buf = @mcrypt_create_iv((int) $bytes, (int) MCRYPT_DEV_URANDOM);\n        if (\n            is_string($buf)\n                &&\n            RandomCompat_strlen($buf) === $bytes\n        ) {\n            /**","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/paragonie/random_compat/blob/b5d188cc9d5e02f94d2c41da23093f1ef557c5b1/lib/random_bytes_mcrypt.php#L30-L66","documentation":"The mcrypt-backed random_bytes() coerces $bytes with RandomCompat_intval() and rethrows a TypeError when the argument is not integer-representable. This keeps the polyfill's behavior aligned with PHP 7's strict random_bytes() typing even on PHP 5 hosts using mcrypt_create_iv().","triggerScenarios":"Passing a float with a fractional part, numeric string, null, array, or object to random_bytes() on a system where the mcrypt backend is active — RandomCompat_intval() throws and lib/random_bytes_mcrypt.php:48 rethrows TypeError.","commonSituations":"Uncast values from query strings or JSON bodies, float results of arithmetic on PHP 5, or passing a DateTime/other object where a byte count was intended.","solutions":["Cast explicitly: random_bytes((int) $length) after verifying the value is a whole number.","Use is_int() / ctype_digit() validation before the call.","Sanitize user-supplied lengths with filter_var(..., FILTER_VALIDATE_INT).","Audit call sites where the length comes from arithmetic that can produce floats."],"exampleFix":"// before\n$key = random_bytes($payload['size']);\n// after\n$size = (int) $payload['size'];\nif ($size < 1 || (string) $size !== (string) $payload['size']) {\n    throw new InvalidArgumentException('size must be an integer >= 1');\n}\n$key = random_bytes($size);","handlingStrategy":"type-guard","validationCode":"function isValidLength($n): bool {\n    return is_int($n) || (is_string($n) && ctype_digit($n));\n}","typeGuard":"function toIntLen($n): ?int {\n    if (is_int($n)) return $n;\n    if (is_string($n) && preg_match('/^\\d+$/', $n)) return (int) $n;\n    return null;\n}","tryCatchPattern":"try {\n    $buf = random_bytes($size);\n} catch (TypeError $e) {\n    throw new InvalidArgumentException('size must be an integer', 0, $e);\n}","preventionTips":["Cast to (int) at the boundary where the value enters your code.","Avoid float arithmetic when computing byte counts on PHP 5.","Type-check config and JSON-derived values before use.","On PHP 7+, declare parameter types (int $size)."],"tags":["php","typeerror","argument-validation","randomness"],"backgroundTag":"type-mismatch","analyzedSha":"b5d188cc9d5e02f94d2c41da23093f1ef557c5b1","analyzedAt":"2026-09-13T16:12:09.755Z","contentChangedAt":"2026-09-13T16:12:09.755Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}