Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect behavior of literal value of PHP_INT_MIN #2400

Open
SerafimArts opened this issue Apr 3, 2023 · 2 comments
Open

Incorrect behavior of literal value of PHP_INT_MIN #2400

SerafimArts opened this issue Apr 3, 2023 · 2 comments
Labels
bug Documentation contains incorrect information Status: Needs Triage

Comments

@SerafimArts
Copy link

SerafimArts commented Apr 3, 2023

Description

PHP literal value of the minimal int64 overflows min bound value.

The following code:

<?php

echo 'value:   ' . \PHP_INT_MIN . "\n"
   . 'literal: ' . -9223372036854775808 . "\n"
   . 'eq:      ' . (-9223372036854775808 === \PHP_INT_MIN ? 'eq' : 'neq') . "\n";
   
echo 'value:   ' . \PHP_INT_MAX . "\n"
   . 'literal: ' . 9223372036854775807 . "\n"
   . 'eq:      ' . (9223372036854775807 === \PHP_INT_MAX ? 'eq' : 'neq') . "\n";

See https://3v4l.org/QpWHc

Resulted in this output:

value:   -9223372036854775808
literal: -9.2233720368548E+18
eq:      neq
value:   9223372036854775807
literal: 9223372036854775807
eq:      eq

# Exactly the same behavior with int32 (if rewrite assertions and run on x86 environment):

value:   -2147483648
literal: -2147483648 # <<< Note that in this case, the literal is displayed "as is", 
                     # however, the equivalence with the PHP_INT_MIN is still violated
eq:      neq
value:   2147483647
literal: 2147483647
eq:      eq

But I expected this output instead:

value:   -9223372036854775808
literal: -9223372036854775808
eq:      eq
value:   9223372036854775807
literal: 9223372036854775807
eq:      eq
  1. -9223372036854775808 is valid int64 min value on x64 platform.
  2. -2147483648 is valid int32 min value on x86 platform.

All versions of PHP (checked since php 7.0) are affected by this bug. This error is reproduced both on Debian linux and on Windows (checked for win11).

PHP Version

7.0.0 ... 8.2.4 (Any)

Operating System

No response

@SerafimArts SerafimArts added bug Documentation contains incorrect information Status: Needs Triage labels Apr 3, 2023
@SerafimArts SerafimArts changed the title Incorrect behavior of lateral value of PHP_INT_MIN Incorrect behavior of literal value of PHP_INT_MIN Apr 3, 2023
@damianwadley
Copy link
Member

Multiple programming languages, including PHP, parse negative numbers written in code not as simple negative numbers but as positive numbers negated. For example, "-123" is not the number -123 but the number 123 negated. Or 123 * -1 if you want to think of it that way.
This works fine - except for the case of PHP_INT_MIN, as -9223372036854775808 will be understood as 9223372036854775808 negated, and 9...808 is too large for a positive integer and thus forced to a float before the negation can happen.

If you really want that large (small?) of a number written in code then use PHP_INT_MIN instead.

I'd like to see this documented and don't see it in the integers page, which hints at this by saying that negative numbers can be written with the "negation operator", so...

@damianwadley damianwadley transferred this issue from php/php-src Apr 3, 2023
@SerafimArts
Copy link
Author

SerafimArts commented Apr 3, 2023

Simply put, the positive literal number 9223372036854775808 is read first as T_DEC, which overflows to become a floating point number, and then the unary negation operator is applied to it.

Understand, thanks!

Perhaps then an alternative definition of such a literal should be added to the documentation:

$int64min = -9223372036854775807-1;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Documentation contains incorrect information Status: Needs Triage
Projects
None yet
Development

No branches or pull requests

2 participants