Mantis Bugtracker
  

Viewing Issue Advanced Details Jump to Notes ] View Simple ] Issue History ] Print ]
ID Category Severity Reproducibility Date Submitted Last Update
0004059 [Quercus] block always 06-01-10 09:13 06-08-10 08:26
Reporter sblommers View Status public  
Assigned To
Priority normal Resolution open Platform Linux
Status new   OS Ubuntu
Projection none   OS Version 10.04
ETA none Fixed in Version Product Version 4.0.8
  Product Build SVN
Summary 0004059: PHP Type comparison not the same
Description Differences in type comparison between Quercus and PHP that are possibly causing most incompatibilities in existing PHP applications running on Quercus.

Some of the type checks that are different on Quercus are causing major inconsistencies in data (I filed some bugs for Drupal).
Steps To Reproduce Run this script on both PHP and Quercus and see the difference (or download from https://streamconsulting.nl/drop/php-type-comparison.php) [^]

<?php

$tests = array();

/* Testing equalty */
$tests['=='] = create_function('$a, $b', 'return $a==$b;');
$tests['!='] = create_function('$a, $b', 'return $a!=$b;');
$tests['<>'] = create_function('$a, $b', 'return $a<>$b;');
$tests['<'] = create_function('$a, $b', 'return $a<$b;');
$tests['>'] = create_function('$a, $b', 'return $a>$b;');
$tests['<='] = create_function('$a, $b', 'return $a<=$b;');
$tests['>='] = create_function('$a, $b', 'return $a>=$b;');
/* Testing identity */
$tests['==='] = create_function('$a, $b', 'return $a===$b;');
$tests['!=='] = create_function('$a, $b', 'return $a!==$b;');

$comparison = array();
$comparison['TRUE'] = true;
$comparison['FALSE'] = false;
$comparison['1'] = 1;
$comparison['0'] = 0;
$comparison['-1'] = -1;
$comparison['3,14'] = pi();
$comparison['"1"'] = '1';
$comparison['"0"'] = '0';
$comparison['"-1"'] = '-1';
$comparison['NULL'] = null;
$comparison['array()'] = array();
$comparison['"php"'] = 'php';
        
print '<h1>PHP version '.PHP_VERSION.' type comparison tables</h1>';

foreach ($tests as $test=>$function) {
    print "<h2>Comparisons with $test</h2>";
    print "<table border='1'>";
    print "<tr>";
    print "<th>&nbsp;</th>";
    foreach (array_keys($comparison) as $name) {
        print "<th>$name</th>";
    }
    print "</tr>";
    foreach ($comparison as $arg_1_name => $arg_1_value) {
        print '<tr>';
        print "<th>$arg_1_name</th>";
        foreach ($comparison as $arg_2_value) {
            print '<td>';
            print $function($arg_1_value, $arg_2_value)==true ?
                        '<span style="color:00F;">TRUE</span>' : '<span style="color:#F00;">FALSE</span>';
            print '</td>';
        }
        print "</tr>";
    }
    print "</table>";
}
?>
Additional Information
Attached Files

- Relationships

- Notes
(0004635)
sblommers
06-08-10 08:26

It took me some time but I managed to workaround every incorrect comparison and created a diff. https://streamconsulting.nl/drop/Value_TypeChecking_4059.diff [^]

diff -r 9ce0fb81b2de modules/quercus/src/com/caucho/quercus/env/ArrayValue.java
--- a/modules/quercus/src/com/caucho/quercus/env/ArrayValue.java Fri Jun 04 10:57:18 2010 +0200
+++ b/modules/quercus/src/com/caucho/quercus/env/ArrayValue.java Tue Jun 08 17:23:30 2010 +0200
@@ -613,13 +613,25 @@
     // arrays are uncomparable, otherwise - compare value by value"
 
     // php/335h
+
+ if (rValue.isBoolean() || rValue.isNull()) {
+ boolean lBool = toBoolean();
+ boolean rBool = rValue.toBoolean();
 
- if (!rValue.isArray())
- return 1;
+ if (! lBool && rBool)
+ return -1;
+ if (lBool && ! rBool)
+ return 1;
 
- int lSize = getSize();
+ return 0;
+ }
+
+ if(!rValue.isArray())
+ return 1;
+
+ int lSize = getSize();
     int rSize = rValue.toArray().getSize();
-
+
     if (lSize != rSize)
       return lSize < rSize ? -1 : 1;
 
@@ -1419,8 +1431,16 @@
       return false;
 
     final Set<Map.Entry<Value,Value>> entryset = entrySet();
+
     if (rValue instanceof BooleanValue)
- return entryset.size() > 0 ? rValue.toBoolean() : !rValue.toBoolean();
+ return !entryset.isEmpty() ? rValue.toBoolean() : !rValue.toBoolean();
+
+ if(rValue instanceof ArrayValueImpl && entryset.isEmpty()) {
+ final Set<Map.Entry<Value,Value>> rentryset = ((ArrayValueImpl)rValue).entrySet();
+ if(rentryset.size() > 0)
+ return false;
+ else return true;
+ }
 
     for (Map.Entry<Value, Value> entry: entryset) {
       Value entryValue = entry.getValue();
diff -r 9ce0fb81b2de modules/quercus/src/com/caucho/quercus/env/BooleanValue.java
--- a/modules/quercus/src/com/caucho/quercus/env/BooleanValue.java Fri Jun 04 10:57:18 2010 +0200
+++ b/modules/quercus/src/com/caucho/quercus/env/BooleanValue.java Tue Jun 08 17:23:30 2010 +0200
@@ -262,7 +262,7 @@
   public int cmp(Value rValue)
   {
     boolean rBool = rValue.toBoolean();
-
+
     if (! _value && rBool)
       return -1;
     if (_value && ! rBool)
diff -r 9ce0fb81b2de modules/quercus/src/com/caucho/quercus/env/LongValue.java
--- a/modules/quercus/src/com/caucho/quercus/env/LongValue.java Fri Jun 04 10:57:18 2010 +0200
+++ b/modules/quercus/src/com/caucho/quercus/env/LongValue.java Tue Jun 08 17:23:30 2010 +0200
@@ -452,7 +452,7 @@
   @Override
   public int cmp(Value rValue)
   {
- if (rValue.isBoolean()) {
+ if (rValue.isBoolean() || rValue.isNull()) {
       boolean lBool = toBoolean();
       boolean rBool = rValue.toBoolean();
 
@@ -463,7 +463,10 @@
 
       return 0;
     }
-
+
+ if(rValue.isArray())
+ return -1;
+
     long l = _value;
     double r = rValue.toDouble();
 
diff -r 9ce0fb81b2de modules/quercus/src/com/caucho/quercus/env/NullValue.java
--- a/modules/quercus/src/com/caucho/quercus/env/NullValue.java Fri Jun 04 10:57:18 2010 +0200
+++ b/modules/quercus/src/com/caucho/quercus/env/NullValue.java Tue Jun 08 17:23:30 2010 +0200
@@ -565,6 +565,9 @@
       double l = 0;
       double r = rValue.toDouble();
 
+ if(r <= 0)
+ return -1;
+
       if (l == r)
         return 0;
       else if (l < r)
diff -r 9ce0fb81b2de modules/quercus/src/com/caucho/quercus/env/NumberValue.java
--- a/modules/quercus/src/com/caucho/quercus/env/NumberValue.java Fri Jun 04 10:57:18 2010 +0200
+++ b/modules/quercus/src/com/caucho/quercus/env/NumberValue.java Tue Jun 08 17:23:30 2010 +0200
@@ -40,6 +40,9 @@
   @Override
   public int cmp(Value rValue)
   {
+ if(rValue.isArray())
+ return -1;
+
     if (rValue.isBoolean() || rValue.isNull()) {
       boolean lBool = toBoolean();
       boolean rBool = rValue.toBoolean();
diff -r 9ce0fb81b2de modules/quercus/src/com/caucho/quercus/env/StringValue.java
--- a/modules/quercus/src/com/caucho/quercus/env/StringValue.java Fri Jun 04 10:57:18 2010 +0200
+++ b/modules/quercus/src/com/caucho/quercus/env/StringValue.java Tue Jun 08 17:23:30 2010 +0200
@@ -384,9 +384,37 @@
    */
   public int cmp(Value rValue)
   {
- if (isNumberConvertible() || rValue.isNumberConvertible()) {
+ if(rValue instanceof NullValue)
+ return cmpString(StringValue.EMPTY);
+
+ if(rValue.isArray())
+ return -1;
+
+ if(rValue instanceof BooleanValue) {
+ boolean lBool = toBoolean();
+ boolean rBool = rValue.toBoolean();
+
+ if (!lBool && rBool) return -1;
+ if (lBool && !rBool) return 1;
+ return 0;
+ }
+
+ if (isNumberConvertible() || rValue.isNumberConvertible()) {
+
       double l = toDouble();
       double r = rValue.toDouble();
+
+ if((!rValue.isNumberConvertible() && rValue instanceof ConstStringValue))
+ return -1;
+
+ if((!isNumberConvertible() && rValue instanceof ConstStringValue))
+ return 1;
+
+ if(!isNumberConvertible() && l > 0)
+ return 1;
+
+ if(l < 0 && (rValue instanceof NullValue || rValue instanceof BooleanValue))
+ return 1;
 
       if (l == r)
         return 0;
 

- Issue History
Date Modified Username Field Change
06-01-10 09:13 sblommers New Issue
06-08-10 08:26 sblommers Note Added: 0004635


Mantis 1.0.0rc3[^]
Copyright © 2000 - 2005 Mantis Group
29 total queries executed.
26 unique queries executed.
Powered by Mantis Bugtracker