Xor bug in all PHP versions

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • DigDug

    Xor bug in all PHP versions

    I get two different results in doing a Xor on a large signed double
    between linux servers.
    working system is kernel 2.4 . bad results server is kernel 2.6.

    PHP version does not matter. I compile PHP from 4.2.2 to latest.

    test code:
    <?PHP echo -4738698913 ^ 43814; ?>

    results:

    Good result from 2.4 kernel system is -443704711
    Bad result from 2.6 kernel systems(tried 5 different systems) is
    -2147439834

    BUG in PHP or kernel?

  • Andy Hassall

    #2
    Re: Xor bug in all PHP versions

    On 18 Jan 2006 13:32:23 -0800, "DigDug" <dougitman@hotm ail.com> wrote:
    [color=blue]
    >I get two different results in doing a Xor on a large signed double
    >between linux servers.
    >working system is kernel 2.4 . bad results server is kernel 2.6.
    >
    > PHP version does not matter. I compile PHP from 4.2.2 to latest.
    >
    >test code:
    ><?PHP echo -4738698913 ^ 43814; ?>
    >
    >results:
    >
    >Good result from 2.4 kernel system is -443704711
    >Bad result from 2.6 kernel systems(tried 5 different systems) is
    >-2147439834
    >
    >BUG in PHP or kernel?[/color]

    32 or 64 bit architecture?

    Have you seen the related user notes on
    http://www.php.net/manual/en/languag...rs.bitwise.php ? (Not all apply to
    XOR but there are several in there that may interest you).

    --
    Andy Hassall :: andy@andyh.co.u k :: http://www.andyh.co.uk
    http://www.andyhsoftware.co.uk/space :: disk and FTP usage analysis tool

    Comment

    • Pedro Graca

      #3
      Re: Xor bug in all PHP versions

      DigDug wrote:[color=blue]
      > I get two different results in doing a Xor on a large signed double
      > between linux servers.[/color]

      The ^ operator takes two integers, all bitwise operator do.
      [color=blue]
      > working system is kernel 2.4 . bad results server is kernel 2.6.
      >
      > PHP version does not matter. I compile PHP from 4.2.2 to latest.
      >
      > test code:
      > <?PHP echo -4738698913 ^ 43814; ?>[/color]

      <?php if (PHP_VERSION>=' 4.4.0') echo PHP_INT_MAX; ?>

      <?php echo var_dump(-4738698913); ?>

      <?php echo -4738698913 | 0; ?>

      <?php echo var_dump(-4738698913 | 0); ?>
      [color=blue]
      > results:
      >
      > Good result from 2.4 kernel system is -443704711[/color]

      64-bit machine?
      [color=blue]
      > Bad result from 2.6 kernel systems(tried 5 different systems) is
      > -2147439834[/color]

      32-bit machine?
      [color=blue]
      > BUG in PHP or kernel?[/color]

      Neither, I think.

      --
      If you're posting through Google read <http://cfaj.freeshell. org/google>

      Comment

      • Chung Leong

        #4
        Re: Xor bug in all PHP versions

        How is -4,738,698,913 ^ 43814 = -443,704,711 correct?

        Comment

        • Tim Roberts

          #5
          Re: Xor bug in all PHP versions

          "Chung Leong" <chernyshevsky@ hotmail.com> wrote:[color=blue]
          >
          >How is -4,738,698,913 ^ 43814 = -443,704,711 correct?[/color]

          First, answer this question: how can you squeeze -4,738,698,913 into a
          32-bit variable?

          4,738,698,913 would be 1_1A72_CEA1 in hex, but that needs 33 bits. If you
          truncate that to 32 bits, you get 1A72_CEA1. Xor that with 43,814, which
          is AB26 in hex, and you get 1A72_6587, which just happens to be
          443,704,711.
          --
          - Tim Roberts, timr@probo.com
          Providenza & Boekelheide, Inc.

          Comment

          • Oli Filth

            #6
            Re: Xor bug in all PHP versions

            Tim Roberts said the following on 20/01/2006 06:59:[color=blue]
            > "Chung Leong" <chernyshevsky@ hotmail.com> wrote:[color=green]
            >> How is -4,738,698,913 ^ 43814 = -443,704,711 correct?[/color]
            >
            > First, answer this question: how can you squeeze -4,738,698,913 into a
            > 32-bit variable?
            >
            > 4,738,698,913 would be 1_1A72_CEA1 in hex, but that needs 33 bits. If you
            > truncate that to 32 bits, you get 1A72_CEA1. Xor that with 43,814, which
            > is AB26 in hex, and you get 1A72_6587, which just happens to be
            > 443,704,711.[/color]

            But that's assuming that PHP performs XOR on the absolute values of the
            operands, and then negates appropriately. i.e.:

            (-4,738,698,913 ^ 43,814) == -(4,738,698,913 ^ 43,814)

            which isn't the case, at least not always. e.g.:

            echo (3 ^ 7) . "\n";
            echo (-3 ^ 7) . "\n";

            i.e. doing XOR directly on the 2's-complement representations of the
            operands.



            As a side-note:
            I don't like the fact that even basic PHP code isn't portable between
            platforms, i.e. it doesn't abstract away differences in platform bitwise
            implementations of signed values.


            --
            Oli

            Comment

            • Jerry Stuckle

              #7
              Re: Xor bug in all PHP versions

              Oli Filth wrote:[color=blue]
              > Tim Roberts said the following on 20/01/2006 06:59:
              >[color=green]
              >> "Chung Leong" <chernyshevsky@ hotmail.com> wrote:
              >>[color=darkred]
              >>> How is -4,738,698,913 ^ 43814 = -443,704,711 correct?[/color]
              >>
              >>
              >> First, answer this question: how can you squeeze -4,738,698,913 into a
              >> 32-bit variable?
              >>
              >> 4,738,698,913 would be 1_1A72_CEA1 in hex, but that needs 33 bits. If
              >> you
              >> truncate that to 32 bits, you get 1A72_CEA1. Xor that with 43,814, which
              >> is AB26 in hex, and you get 1A72_6587, which just happens to be
              >> 443,704,711.[/color]
              >
              >
              > But that's assuming that PHP performs XOR on the absolute values of the
              > operands, and then negates appropriately. i.e.:
              >
              > (-4,738,698,913 ^ 43,814) == -(4,738,698,913 ^ 43,814)
              >
              > which isn't the case, at least not always. e.g.:
              >
              > echo (3 ^ 7) . "\n";
              > echo (-3 ^ 7) . "\n";
              >
              > i.e. doing XOR directly on the 2's-complement representations of the
              > operands.
              >
              >
              >
              > As a side-note:
              > I don't like the fact that even basic PHP code isn't portable between
              > platforms, i.e. it doesn't abstract away differences in platform bitwise
              > implementations of signed values.
              >
              >[/color]

              No, Tim is correct. PHP CAN'T do an XOR on -4,738,698,913 on a 32 bit
              system. The value doesn't fit into 32 bits!

              It has nothing to do with the absolute value. In fact, in bit
              operations other than right shift, there is no "absolute value". There
              are just bits.

              --
              =============== ===
              Remove the "x" from my email address
              Jerry Stuckle
              JDS Computer Training Corp.
              jstucklex@attgl obal.net
              =============== ===

              Comment

              • Oli Filth

                #8
                Re: Xor bug in all PHP versions

                Jerry Stuckle said the following on 20/01/2006 13:22:[color=blue]
                > Oli Filth wrote:[color=green]
                >> Tim Roberts said the following on 20/01/2006 06:59:
                >>[color=darkred]
                >>> "Chung Leong" <chernyshevsky@ hotmail.com> wrote:
                >>>
                >>>> How is -4,738,698,913 ^ 43814 = -443,704,711 correct?
                >>>
                >>>
                >>> First, answer this question: how can you squeeze -4,738,698,913 into a
                >>> 32-bit variable?
                >>>
                >>> 4,738,698,913 would be 1_1A72_CEA1 in hex, but that needs 33 bits.
                >>> If you
                >>> truncate that to 32 bits, you get 1A72_CEA1. Xor that with 43,814,
                >>> which
                >>> is AB26 in hex, and you get 1A72_6587, which just happens to be
                >>> 443,704,711.[/color]
                >>
                >>
                >> But that's assuming that PHP performs XOR on the absolute values of
                >> the operands, and then negates appropriately. i.e.:
                >>
                >> (-4,738,698,913 ^ 43,814) == -(4,738,698,913 ^ 43,814)
                >>
                >> which isn't the case, at least not always. e.g.:
                >>
                >> echo (3 ^ 7) . "\n";
                >> echo (-3 ^ 7) . "\n";
                >>
                >> i.e. doing XOR directly on the 2's-complement representations of the
                >> operands.
                >>[/color]
                >
                > No, Tim is correct. PHP CAN'T do an XOR on -4,738,698,913 on a 32 bit
                > system. The value doesn't fit into 32 bits![/color]

                I'm aware of that.

                However, I now realise that -443,704,711 is the correct answer! Made a
                mistake in my paper calculations! Apologies...




                --
                Oli

                Comment

                • DigDug

                  #9
                  Re: Xor bug in all PHP versions

                  What founded this question is the following script.



                  which works on some machines and not others. All my machines are 32bit.
                  [color=blue]
                  >From my tests I noticed the problem being with 2.6 kernel boxes and[/color]
                  not what bit the kernel/processor is.

                  Comment

                  • Jim Michaels

                    #10
                    Re: Xor bug in all PHP versions

                    How do you know the PHP lexical analyzer or parser is going to lop off a bit
                    for you? what if it does something else?
                    your number in hex is 0xFFFF FFFE E58D 315F ^ 0x0000 0000 0000 AB26=0xFFFF
                    FFFF 8000 AB26
                    2's complement numbers in hex are represented differently in binary...
                    this is from pcalc, a program from analogx.com (64-bit programmer's
                    calculator)

                    "Tim Roberts" <timr@probo.com > wrote in message
                    news:3921t1p8r8 imnqmgnijdrpkme knr1t0ooa@4ax.c om...[color=blue]
                    > "Chung Leong" <chernyshevsky@ hotmail.com> wrote:[color=green]
                    >>
                    >>How is -4,738,698,913 ^ 43814 = -443,704,711 correct?[/color]
                    >
                    > First, answer this question: how can you squeeze -4,738,698,913 into a
                    > 32-bit variable?
                    >
                    > 4,738,698,913 would be 1_1A72_CEA1 in hex, but that needs 33 bits. If you
                    > truncate that to 32 bits, you get 1A72_CEA1. Xor that with 43,814, which
                    > is AB26 in hex, and you get 1A72_6587, which just happens to be
                    > 443,704,711.
                    > --
                    > - Tim Roberts, timr@probo.com
                    > Providenza & Boekelheide, Inc.[/color]


                    Comment

                    • Jim Michaels

                      #11
                      Re: Xor bug in all PHP versions


                      "DigDug" <dougitman@hotm ail.com> wrote in message
                      news:1137619943 .473285.76050@g 44g2000cwa.goog legroups.com...[color=blue]
                      >I get two different results in doing a Xor on a large signed double
                      > between linux servers.
                      > working system is kernel 2.4 . bad results server is kernel 2.6.
                      >
                      > PHP version does not matter. I compile PHP from 4.2.2 to latest.
                      >
                      > test code:
                      > <?PHP echo -4738698913 ^ 43814; ?>
                      >
                      > results:
                      >
                      > Good result from 2.4 kernel system is -443704711
                      > Bad result from 2.6 kernel systems(tried 5 different systems) is
                      > -2147439834
                      >[/color]

                      2.6 kernel system is at least a 64-bit base. it's not a bug.
                      -4738698913=0xFF FF FFFE E58D 315F
                      43814=0x0000 0000 0000 AB26
                      -2147439834=0xFF FF FFFF 8000 AB26
                      that last number is what I get for a result from a 64-bit calculator.

                      When a C or C++ program like PHP is compiled on a 64-bit processor or using
                      flags for 64-bit int's, you will probably get this. The size of an int will
                      become 64 bits, not 32. similarly, if you are compiling on a 16-bit
                      processor and no 32-bit registers are available, you may get 16-bit ints.
                      The manual doesn't seem to take this into account. possibly 64-bit
                      processors were not supported until later versions of gcc and/or kernel? or
                      possibly (more likely) the default settings for the processor are stored in
                      the kernel.
                      [color=blue]
                      > BUG in PHP or kernel?
                      >[/color]


                      Comment

                      • Tim Roberts

                        #12
                        Re: Xor bug in all PHP versions

                        "Jim Michaels" <jmichae3@yahoo .com> wrote:[color=blue]
                        >
                        >How do you know the PHP lexical analyzer or parser is going to lop off a bit
                        >for you? what if it does something else?[/color]

                        PHP does not handle integers larger than "long" on its machine. Thus, on a
                        32-bit machine, I KNOW it's going to lop off a bit.
                        [color=blue]
                        >your number in hex is 0xFFFF FFFE E58D 315F ^ 0x0000 0000 0000 AB26=0xFFFF
                        >FFFF 8000 AB26[/color]

                        No, that would be my number in a 64-bit variable. My description below
                        specifically mentions a 32-bit variable, as the OP was using.
                        [color=blue]
                        >2's complement numbers in hex are represented differently in binary...[/color]

                        No, they aren't. The numbers are ALL binary. Whether I print them in
                        binary or hex or decimal is irrelevant to the way they are processed.
                        However, the SIZE of the variable is important.
                        [color=blue]
                        >this is from pcalc, a program from analogx.com (64-bit programmer's
                        >calculator)[/color]

                        Right. That's the result you'd get from a 64-bit processor. PHP on a
                        32-bit processor will produce the result I described.
                        [color=blue]
                        >"Tim Roberts" <timr@probo.com > wrote in message:[color=green]
                        >> "Chung Leong" <chernyshevsky@ hotmail.com> wrote:[color=darkred]
                        >>>
                        >>>How is -4,738,698,913 ^ 43814 = -443,704,711 correct?[/color]
                        >>
                        >> First, answer this question: how can you squeeze -4,738,698,913 into a
                        >> 32-bit variable?
                        >>
                        >> 4,738,698,913 would be 1_1A72_CEA1 in hex, but that needs 33 bits. If you
                        >> truncate that to 32 bits, you get 1A72_CEA1. Xor that with 43,814, which
                        >> is AB26 in hex, and you get 1A72_6587, which just happens to be
                        >> 443,704,711.[/color][/color]
                        --
                        - Tim Roberts, timr@probo.com
                        Providenza & Boekelheide, Inc.

                        Comment

                        • Chung Leong

                          #13
                          Re: Xor bug in all PHP versions

                          Oli Filth wrote:
                          [color=blue]
                          > As a side-note:
                          > I don't like the fact that even basic PHP code isn't portable between
                          > platforms, i.e. it doesn't abstract away differences in platform bitwise
                          > implementations of signed values.[/color]

                          I don't really see why the operation would be platform dependent. If I
                          remember correctly, a long is defined as 32 bit. Int is the one that
                          varies between architectures. In PHP, a convert from double to integer
                          is done by the DVAL_TO_LVAL macro, which is defined as:

                          (l) = (d) > LONG_MAX ? (unsigned long) (d) : (long) (d)

                          A cast to long should be the same even on a 64 bit OS/CPU.

                          I wonder if it's a difference in the compiler or C library. Typically a
                          cast from a float to a long is handled with a call to ftol(). Maybe the
                          overflow behavior is different.

                          Comment

                          Working...