Skip to content

MT_RAND_PHP causes undefined behavior #9191

Closed

Description

@zeriyoshi

Description

The scaling algorithm used internally by MT_RAND_PHP causes undefined CPU-dependent behavior.

This breaks compatibility of the MT random number sequences generated across platforms. (Its properties as a random number are already broken because it is improperly used.)

The following code:

mt_srand(1234, MT_RAND_PHP);
echo mt_rand(PHP_INT_MIN, PHP_INT_MAX) . PHP_EOL;

Resulted in this output:

  • i386: 0
  • amd64: 0
  • arm32v7: -1
  • arm64v8: -1
  • s390x: -1

Easily reproduced in QEMU's available Docker environment:

$ docker run --rm -it i386/php:7.4-cli -r 'mt_srand(1234, MT_RAND_PHP); echo mt_rand(PHP_INT_MIN, PHP_INT_MAX) . PHP_EOL;'
0
$ docker run --rm -it amd64/php:7.4-cli -r 'mt_srand(1234, MT_RAND_PHP); echo mt_rand(PHP_INT_MIN, PHP_INT_MAX) . PHP_EOL;'
0
$ docker run --rm -it arm32v7/php:7.4-cli -r 'mt_srand(1234, MT_RAND_PHP); echo mt_rand(PHP_INT_MIN, PHP_INT_MAX) . PHP_EOL;'
-1
$ docker run --rm -it arm64v8/php:7.4-cli -r 'mt_srand(1234, MT_RAND_PHP); echo mt_rand(PHP_INT_MIN, PHP_INT_MAX) . PHP_EOL;'
-1
$ docker run --rm -it s390x/php:7.4-cli -r 'mt_srand(1234, MT_RAND_PHP); echo mt_rand(PHP_INT_MIN, PHP_INT_MAX) . PHP_EOL;'
-1

But I expected this output instead:

This should probably be an error since it is beyond the range of getrandmax(), but should be unified to 0 or -1 for compatibility.

PHP Version

PHP 7.4.x (All supported version)

Operating System

Debian 11

Activity

  1. zeriyoshi commented on Jul 29, 2022

    @zeriyoshi
    ContributorAuthor

    We can unify the behavior with a wicked implementation like this:

    static inline zend_long float_to_long_intel(zend_long min, double f)
    {
    	if (f >= ((double) ZEND_LONG_MAX - 1.0)) {
    		return 0;
    	}
    
    	return min + (zend_long) f;
    }
  2. added a commit that references this issue on Aug 3, 2022
    60ace13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions