ID:               42868
 User updated by:  zoe dot slattery at googlemail dot com
-Summary:          Inconsistent return values from strspn()
 Reported By:      zoe dot slattery at googlemail dot com
 Status:           Open
 Bug Type:         Scripting Engine problem
 Operating System: Linux/Windows/OSX
 PHP Version:      5CVS-2007-10-05 (snap)
 New Comment:

Hi - I'm appending a fix for this bug - it's not elegant. The cause
of this bug (and many similar bugs) is in the code in
zend_operators.c which casts doubles to integers. I see that someone
already
tried to fix this code a couple of years ago, but the fix had to be
removed
(see defect 30695).
I suppose it might be possible to special case
0x8000000 - 0xFFFFFFF which might avoid the problem described in
30695.
In the meantime here is a fix to string.c which gets around it
for this particular instance.

If someone commits this - or something like it - the test cases will
need changing, I'm happy to do that.

#P php53_dev
Index: ext/standard/string.c
===================================================================
RCS file: /repository/php-src/ext/standard/string.c,v
retrieving revision 1.445.2.14.2.69.2.5
diff -u -r1.445.2.14.2.69.2.5 string.c
--- ext/standard/string.c       7 Oct 2007 05:22:07 -0000      
1.445.2.14.2.69.2.5
+++ ext/standard/string.c       31 Oct 2007 21:28:35 -0000
@@ -207,14 +207,25 @@
 {
        char *s11, *s22;
        int len1, len2;
+       double startf;
        long start, len;

        start = 0;
        len = 0;
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll",
&s11, &len1,
-                               &s22, &len2, &start, &len) == FAILURE)
{
+       startf = 0;
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|dl",
&s11, &len1,
+                               &s22, &len2, &startf, &len) == FAILURE)
{
                return;
        }
+       // Check to make sure that the start length isn't greater than
the maximum integer
+        // or smaller than the minimum integer
+        if(startf > INT_MAX || startf < INT_MIN) {
+                RETURN_FALSE;
+        } else {
+                start = (long) startf;
+        }
+
+

        if (ZEND_NUM_ARGS() < 4) {
                len = len1;


Previous Comments:
------------------------------------------------------------------------

[2007-10-05 15:26:19] zoe dot slattery at googlemail dot com

Description:
------------
I'm not sure if this is one defect or two (or none:-)) - it would be
good to understand the expected behaviour as there are a number of other
MAC OSX test failures. 

(1) strspn() does not return consistent values on Linux/Windows if
"$start"> PHP_INT_MAX

(2) The values returned on MAC OSX (10.4) are different to the values
returned on Linux & Windows.

It's reasonably easy to see what is happening in the Windows/Linux
case. The double that is passed to strspn() is cast as a long in
zend_parse_parameters, and in some cases this means that the resulting
long happens to be within a reasonable range (see comments in reproduce
code).

>From the users' point of view it would be better if strspn() returned
the same thing for all values of $start which are outside the expected
range.

I'm not sure why the behaviour is different on Mac, it appears that
what comes back from zend_parse_parameters is "-1" in example 3 & 4.

Reproduce code:
---------------
<?php
$str = '2468 who do we appreciate';
$mask = '1234567890';

//Linux result, after zend_parse_parameters start = 2147483647, expect
bool(false)
//Mac result, start = 2147483647, bool(false)
$start = PHP_INT_MAX;
var_dump( strspn($str,$mask,$start) );

//Linux result, after zend_parse_parameters start = -23, expect
bool(false)?, get int(2)
//Mac result, start = -23, int(2)
$start = PHP_INT_MAX * 2 - 21;
var_dump( strspn($str,$mask,$start) );

//Linux result, after zend_parse_parameters start = 0, expect
bool(false)?, get int(4)
//Mac result, start = -1, int(0)
$start = PHP_INT_MAX * 2 + 2;
var_dump( strspn($str,$mask,$start) );

//Linux result, after zend_parse_parameters start = -3, expect
bool(false)?, get int(0)
//Mac result, start = -1, int(0)
$start = PHP_INT_MAX * 4 + 1;
var_dump( strspn($str,$mask,$start) );
?>


Expected result:
----------------
I'd expect to see
(1) the same result for every invalid value of $start on (Win/Lin)
(2) the same result on Mac as I see on Win/Lin

Actual result:
--------------
Lin/Win

bool(false)
int(2)
int(4)
int(0)

Mac
bool(false)
int(2)
int(0)
int(0)


------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=42868&edit=1

Reply via email to