php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #63792 Bitset::andOp does multiple ANDs between the same octects
Submitted: 2012-12-17 23:56 UTC Modified: 2017-10-24 08:00 UTC
From: harroyo at hangar18 dot cc Assigned:
Status: Open Package: Bitset (PECL)
PHP Version: Irrelevant OS:
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2012-12-17 23:56 UTC] harroyo at hangar18 dot cc
Description:
------------
See https://github.com/php/pecl-numbers-bitset/blob/master/bitset.c#L279 : the 
loop that 
performs the AND looks like this:

for (; i < to_bits; i++) {
	intern->bitset_val[i / CHAR_BIT] &= param->bitset_val[i / CHAR_BIT];
}

so taking, for example, CHAR_BIT=8, it does
 (intern[0] & param[0]),
 1/8=0 -> (intern[0] & param[0])
 2/8=0 -> (intern[0] & param[0])
 ...
 8/8=1 -> (intern[1] & param[1])

ie, it does AND CHAR_BIT times for every char. My suggested fix is to change the 
loop to 
something like this:

for (; i < to_bits; i+= CHAR_BIT) {
	intern->bitset_val[i / CHAR_BIT] &= param->bitset_val[i / CHAR_BIT];
}

//last increment may have set i above the bitset(s) bounds(and made the for loop 
skip 
last bits): operate on the last octect bit by bit

i = (to_bits/CHAR_BIT) * CHAR_BIT; // get the index of the last bit on a char 
boundary

for (unsigned char mask=0x0; i < to_bits; i++) {
        // bitwise and one bit at a time
        // please note the following code is not tested

        mask = ~(1 << (i%CHAR_BITS)); // all bits set to 1 except the current 
index
        mask |= param->bitset_val[i / CHAR_BIT]; // all 1s if the current index 
is set, 
mask unchanged if not

	intern->bitset_val[i / CHAR_BIT] &= mask; //changes only the current bit
}




Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-12-18 00:15 UTC] harroyo at hangar18 dot cc
Note also if bitset_len1 > bitset_len2, then IMO the remaining (len1-len2) bits 
from intern->bitset_val should be set to zero (because semantically it would be 
equivalent to ANDing with NULL, and (anything&NULL)==false).
 [2012-12-18 00:24 UTC] harroyo at hangar18 dot cc
the mask'ing part inside the loop can be condensed, similar to 
https://github.com/php/pecl-numbers-bitset/blob/master/bitset.c#L591
 [2012-12-18 21:12 UTC] willfitch@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: willfitch
 [2017-10-24 08:00 UTC] kalle@php.net
-Status: Assigned +Status: Open -Assigned To: willfitch +Assigned To:
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC