Mantis - Quercus
Viewing Issue Advanced Details
2350 major always 01-21-08 05:04 01-23-08 11:00
rvt  
nam  
normal  
closed 3.1.5  
fixed  
none    
none 3.1.5  
0002350: appen string operation cannot be doen with a string is retreived from file_get_contents
When a string is retreived from file_get_contents an append operation cannot be executed in PHP and results in a exception.

java.lang.UnsupportedOperationException: com.caucho.quercus.env.LargeStringBuilderValue
    at com.caucho.quercus.env.StringValue.append(StringValue.java:875)
    at com.caucho.quercus.env.StringValue.appendUnicode(StringValue.java:993)
    at com.caucho.quercus.expr.AppendExpr.eval(AppendExpr.java:92)
    at com.caucho.quercus.expr.Expr.evalCopy(Expr.java:398)


The reason behind this is that the file_get_content() java implementation returns an LargeStringBuilderValue object and on this object no append operations can be done (largeStringBuilderValue calls it's parent class StringValue to do the work).

the append function looks like this:

  @Override
  public Value eval(Env env)
  {
    Value value = _value.eval(env);

    StringValue sb = value.toStringBuilder(env);

    for (AppendExpr ptr = _next; ptr != null; ptr = ptr._next) {
      Value ptrValue = ptr._value.eval(env);
      
      sb = sb.appendUnicode(ptrValue.toString());
    }

    return sb;
}

The line StringValue sb = value.toStringBuilder(env); will return a LargeStringBuilderValue object and which the operation sb = sb.appendUnicode(ptrValue.toString()); get's executed which will fail.

My current solution is to let file_get_contents return a StringBuilderValue instead of returning a LargeStringBuilderValue, however I am not sure if this will conflict with thus bug: http://bugs.caucho.com/view.php?id=2101 [^] (file_get_content slow on large files)

1) One other possible solution is that StringValue sb = value.toStringBuilder(env); will always return StringBuilderValue. But I don't know the implications of this change

2) My current solution is to let file_get_contents return a StringBuilderValue.

Here is the new function.

  /**
   * Parses the file, returning it as a string array.
   *
   * @param filename the file's name
   * @param useIncludePath if true, use the include path
   * @param context the resource context
   */
  @ReturnNullAsFalse
  public static StringValue
    file_get_contents(Env env,
              StringValue filename,
              @Optional boolean useIncludePath,
              @Optional Value context,
              @Optional long offset,
              @Optional("4294967296") long maxLen)
  {
    if (filename.length() == 0) {
      env.warning(L.l("file name must not be null"));
      return null;
    }

    BinaryStream s = fopen(env, filename, "r", useIncludePath, context);

    if (! (s instanceof BinaryInput))
      return null;

    BinaryInput is = (BinaryInput) s;
    
    StringValue bb = env.createLargeBinaryBuilder();
    bb.appendReadAll(is, maxLen);
    
    s.close();

    StringValue bbb = new StringBuilderValue(bb.toString());

    return bbb;
  }


Let me know which solution is best and I can create a proper patch.

Ries


How to duplicate:
<?php
$a='';
$a=file_get_contents('http://www.rvantwisk.nl/');; [^]
$a .= '----'; // her ethe exception is thrown
print $a;
?>

Notes
(0002668)
nam   
01-23-08 11:00   
php/0338