Problem/Motivation

Cache items containing a string like $foo are not returned by PhpBackend->get().

Proposed resolution

Escape $ character (#0) or use nowdoc (#2).Use var_export (#14).

Remaining tasks

User interface changes

API changes

Comments

The last submitted patch, phpbackend-escape-test.patch, failed testing.

olli’s picture

Title: PhpBackend should escape $foo » PhpBackend expands $foo and ${bar()}
Issue summary: View changes
StatusFileSize
new1.9 KB
new948 bytes
sun’s picture

Title: PhpBackend expands $foo and ${bar()} » Cache\PhpBackend expands $foo and ${bar()}
Priority: Normal » Major

Major (at minimum).

chx’s picture

Status: Needs review » Reviewed & tested by the community

Oh boy. PHP. I like #2 much better. Nowdoc is php 5.3.0 in case anyone wonders. Now i wonder, are we going to bump against the 2gb limit of a string? I'd guess not cos other backends store $cache->data too. I hope there are no more landmines buried in phpbackend...

Anonymous’s picture

nice find, glad to see we can remove the slashes crap.

olli’s picture

I think we need to do something with the $cid too, filed #2267649: Some cache keys do not work with PhpBackend.

dman’s picture

Issue tags: +Needs tests, +Drupal8NZ

Pretty sure this sort of rewriting is going to need tests. Flagging for a do-able Sprint task.
(I see one test - so that's a good base for novice to think up and add a few other ways to break things)

quietone’s picture

Installed the patch and tested successfully. But get unexpected results when the input test string has three backslashes. The test passes but the display shows four backslashes, not the three expected.

Input:
$with_variable = array('foo' => '"three backslashes \\\"');

Test result:
Value array ( 'foo' => '"three backslashes \\\\"', ) is identical to value array ( 'foo' => '"three backslashes \\\\"', )

chx’s picture

@quietone thanks for the report. Which patch did you test?

damien tournoud’s picture

I would like to see:

$content = "<?php return unserialize(" . var_export(serialize($item)) . ");";

Which is the proper way of doing this.

But really, I would like to see this whole craziness go away. Storing cache entry in the opcode cache sounds like a terrible idea (even if I suggested it a long time ago). This is especially true because:

(1) The current implementation relies of the Opcode cache stating the file;
(2) MTimeProtectedFileStorage triggers at least an additional stat() call anyway (to get the mtime of the containing directory)

At this point (small file, with a stat() on it just done), loading the content of the file should be pretty cheap.

chx’s picture

Status: Reviewed & tested by the community » Needs work
Anonymous’s picture

re. #10:

- if serializing before var_export means we don't have to force callers of the API to implement extra methods on their data, then yay, that is cleaner.

- i agree on wanting to kill this backend entirely. the thinking behind it was roughly:

a) D8 is horribly slow
b) we need a faster cache system
c) we can't rely on APCu everywhere

removing this backend is primarily about convincing the maintainers that we can ship D8 without it.

damien tournoud’s picture

- if serializing before var_export means we don't have to force callers of the API to implement extra methods on their data, then yay, that is cleaner.

No, var_export() is just used to export of the serialized string into PHP code. That doesn't change anything functionally.

olli’s picture

Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new1.09 KB
new2.08 KB

Nice!! var_export() is also used in doctrine PhpFileCache.

Anonymous’s picture

yes, and note that var_export put stupid constraints on the caller, which is why we avoided it in the first place.

olli’s picture

Re #8: That is because the test results use var_export which escapes the third backslash ('\\\"' equals '\\\\"').

Agree with #13, I don't think this changes anything compared to #0 or #2 - just less code.

damien tournoud’s picture

Status: Needs review » Reviewed & tested by the community
-    if (!$unsafe_eof_in_data) {
-      $content = "<?php return unserialize(<<<$EOF
-$data
-$EOF
-);";

Erm. We were not even quoting the string? :)

This whole thing was only working because:

(1) PHP casts unknown constants to strings and
(2) We just silence all errors when including the file.

Let's get this in and stop the bleeding...

damien tournoud’s picture

Priority: Major » Critical

Actually, bumping to critical because of the very real risk this opens up remote code execution possibilities.

Anonymous’s picture

i agree with this RTBC, and the implementation is much simpler. yay.

#18 - can you explain what the remote code vulnerabilities are?

dries’s picture

Status: Reviewed & tested by the community » Fixed

Committed to 8.x. Thanks!

  • Commit 3ee31d1 on 8.x by Dries:
    Issue #2265977 by olli: fixed php backend serialization.
    

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.