php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #30263 bitwise operators return different lengths
Submitted: 2004-09-28 16:13 UTC Modified: 2004-09-30 03:36 UTC
From: tomas_matousek at hotmail dot com Assigned:
Status: Not a bug Package: Variables related
PHP Version: 5.0.2 OS: WinXP
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
18 + 33 = ?
Subscribe to this entry?

 
 [2004-09-28 16:13 UTC] tomas_matousek at hotmail dot com
Description:
------------
If a biwise operator is applied on strings with different lengths one would expect that all such operators would return a string which length is a maximum of the lengths of the operands. Or at least that OR and XOR would do that.
But neither is true since OR returns string having the maximum of both lengths and AND, XOR the minimum.

That's why I think there is a bug in ^ operator.
& operator may behave in both ways, although I would prefer the same behavior as in the case of | and ^.

Reproduce code:
---------------
  echo bin2hex("\x01\x02" & "\x01\x00\x01\x02"),"\n";
  echo bin2hex("\x01\x02" | "\x10\x20\x10\x00"),"\n";
  echo bin2hex("\x01\x02" ^ "\x00\x00\x00\x01"),"\n";


Expected result:
----------------
01000000
11221000
01020001

-- or -- 

0100
11221000
01020001


Actual result:
--------------
0100
11221000
0102



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-09-29 10:24 UTC] php at botimer dot net
Tomas,

I'm not ready to say that the XOR operator is bugged.  I will say that the AND and XOR definitely behave differently than OR.  All three of these operators pad the shorter string ``on the right'', making the bits more significant.  The difference between your expected and actual is due to taking only the overlap and shifting it right by the number of pad bits (bytes/characters, dealing with strings).

I've broken your examples down into full binary form, separated the nibbles, and blocked the words.  In the AND and XOR, the high word is taken as the result, while the padded section is discarded.  I've also included a little c program and its results to give the breakdown.  The a variable is padded left, b is padded right.  You can see that the results PHP is giving you are the shifted values listed last.  As for reasoning for the shift, while the OR is allowed to ``make bits'', I would say that it is for masking purposes, but I can't say exactly what.  I'm sure some guru would be more than happy to chime in.

I know this is probably a more mathematical treatment than necessary.  Simply put, the strings are truncated right of the overlap for AND and XOR, but not for OR.  I don't consider it a bug, but can't give the deliberate intention.


00 00 01 02 -> 0000 0000 0000 0000 0000 0001 0000 0010 = 258
01 02 00 00 -> 0000 0001 0000 0010 0000 0000 0000 0000 = 16908288

01 00 01 02 -> 0000 0011 0000 0001 0000 0000 0000 0001 = 16777474
10 20 10 00 -> 0000 0000 0001 0000 0010 0000 0001 0000 = 270536704
00 00 00 01 -> 0000 0001 0000 0000 0000 0000 0000 0000 = 1

--

01 02 00 00 -> [0000 0001 0000 0010] [0000 0000 0000 0000]
01 00 01 02 -> [0000 0001 0000 0000] [0000 0001 0000 0010]
            &  [0000 0001 0000 0000] [0000 0000 0000 0000] = 256 = 0100

01 02 00 00 -> [0000 0001 0000 0010] [0000 0000 0000 0000]
10 20 10 00 -> [0001 0000 0010 0000] [0001 0000 0000 0000]
            |  [0001 0001 0010 0010] [0001 0000 0000 0000] = 287444992 = 11221000

01 02 00 00 -> [0000 0001 0000 0010] [0000 0000 0000 0000]
00 00 00 01 -> [0000 0000 0000 0000] [0000 0000 0000 0001]
            ^  [0000 0001 0000 0010] [0000 0000 0000 0001] = 258 = 0102



=====<%======<%=====
#include <stdio.h>

int main() {
  unsigned long a = 258;
  unsigned long b = 16908288;

  unsigned long c = 16777474;
  unsigned long d = 270536704;
  unsigned long e = 1;

  printf("a & c: %d\n", a & c);
  printf("a | d: %d\n", a | d);
  printf("a ^ e: %d\n", a ^ e);

  printf("----\n");

  printf("b & c: %d\n", b & c);
  printf("b | d: %d\n", b | d);
  printf("b ^ e: %d\n", b ^ e);
  printf("(b & c) >> 16: %d\n", (b & c) >> 16);
  printf("(b ^ e) >> 16: %d\n", (b ^ e) >> 16);

  return 0;
}
=====<%======<%=====

a & c: 258
a | d: 270536962
a ^ e: 259
----
b & c: 16777216
b | d: 287444992
b ^ e: 16908289
(b & c) >> 16: 256
(b ^ e) >> 16: 258

Thanks,
-Noah
 [2004-09-30 03:36 UTC] iliaa@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

Not a bug.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 18 08:02:42 2024 UTC