-
Notifications
You must be signed in to change notification settings - Fork 208
PHPC-1839 Fix accessing referenced strings #1223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
--TEST-- | ||
PHPC-1839: Referenced, out-of-scope, non-interned string in typeMap | ||
--SKIPIF-- | ||
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?> | ||
<?php skip_if_not_live(); ?> | ||
<?php skip_if_not_clean(); ?> | ||
--FILE-- | ||
<?php | ||
require_once __DIR__ . "/../utils/basic.inc"; | ||
|
||
function createTypemap() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using a function here to reproduce the behaviour of php-di. Notably this produces a different zval than in test 002 (see below). |
||
{ | ||
// Assemble the string so as to not have an interned string | ||
$rootValue = chr(ord('a')) . 'rray'; | ||
$documentValue = chr(ord('a')) . 'rray'; | ||
|
||
// Use a reference to this non-interned string in the type map | ||
$typemap = ['root' => &$rootValue, 'document' => &$documentValue]; | ||
|
||
return $typemap; | ||
} | ||
|
||
$typemap = createTypemap(); | ||
|
||
$manager = new MongoDB\Driver\Manager(URI); | ||
$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([])); | ||
|
||
echo "Before:\n"; | ||
debug_zval_dump($typemap); | ||
|
||
$cursor->setTypemap($typemap); | ||
|
||
echo "After:\n"; | ||
debug_zval_dump($typemap); | ||
|
||
?> | ||
===DONE=== | ||
<?php exit(0); ?> | ||
--EXPECT-- | ||
Before: | ||
array(2) refcount(2){ | ||
["root"]=> | ||
string(5) "array" refcount(1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Despite us assigning a reference, this is apparently converted by PHP once the variable goes out of scope. I was able to confirm this on all PHP versions: https://3v4l.org/12fdR. For this reason, I decided to keep both tests to make sure we're not running into strange behaviour anymore; this took enough time to discover already. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I discovered that this is indeed intended: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you clarify if the value of "root" (and other keys) here are still references, and this is just a matter of the behavior of php/php-src@2eb980f deciding not to render them as such? If so, perhaps note that in a comment on the first call to Based on my reading of Dereferencing and Unwrapping, the unwrapping in |
||
["document"]=> | ||
string(5) "array" refcount(1) | ||
} | ||
After: | ||
array(2) refcount(2){ | ||
["root"]=> | ||
string(5) "array" refcount(1) | ||
["document"]=> | ||
string(5) "array" refcount(1) | ||
} | ||
===DONE=== |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
--TEST-- | ||
PHPC-1839: Referenced local non-interned string in typeMap | ||
alcaeus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
--SKIPIF-- | ||
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?> | ||
<?php skip_if_not_live(); ?> | ||
<?php skip_if_not_clean(); ?> | ||
--FILE-- | ||
<?php | ||
require_once __DIR__ . "/../utils/basic.inc"; | ||
|
||
// Assemble the string so as to not have an interned string | ||
$rootValue = chr(ord('a')) . 'rray'; | ||
$documentValue = chr(ord('a')) . 'rray'; | ||
|
||
$typemap = ['root' => &$rootValue, 'document' => &$documentValue]; | ||
|
||
$manager = new MongoDB\Driver\Manager(URI); | ||
$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([])); | ||
|
||
echo "Before:\n"; | ||
debug_zval_dump($typemap); | ||
|
||
$cursor->setTypemap($typemap); | ||
|
||
echo "After:\n"; | ||
debug_zval_dump($typemap); | ||
|
||
?> | ||
===DONE=== | ||
<?php exit(0); ?> | ||
--EXPECT-- | ||
Before: | ||
array(2) refcount(2){ | ||
["root"]=> | ||
&string(5) "array" refcount(1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Honestly, I have no clue why PHP would show the correct values here. Maybe @sgolemon can provide some insight? |
||
["document"]=> | ||
&string(5) "array" refcount(1) | ||
} | ||
After: | ||
array(2) refcount(2){ | ||
["root"]=> | ||
&string(5) "array" refcount(1) | ||
["document"]=> | ||
&string(5) "array" refcount(1) | ||
} | ||
===DONE=== |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
--TEST-- | ||
PHPC-1839: Referenced, out-of-scope interned string in typeMap | ||
alcaeus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
--SKIPIF-- | ||
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?> | ||
<?php skip_if_not_live(); ?> | ||
<?php skip_if_not_clean(); ?> | ||
--FILE-- | ||
<?php | ||
require_once __DIR__ . "/../utils/basic.inc"; | ||
|
||
function createTypemap() | ||
{ | ||
$rootValue = 'array'; | ||
$documentValue = 'array'; | ||
|
||
$typemap = ['root' => &$rootValue, 'document' => &$documentValue]; | ||
|
||
return $typemap; | ||
} | ||
|
||
$typemap = createTypemap(); | ||
|
||
$manager = new MongoDB\Driver\Manager(URI); | ||
$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([])); | ||
|
||
echo "Before:\n"; | ||
debug_zval_dump($typemap); | ||
|
||
$cursor->setTypemap($typemap); | ||
|
||
echo "After:\n"; | ||
debug_zval_dump($typemap); | ||
|
||
?> | ||
===DONE=== | ||
<?php exit(0); ?> | ||
--EXPECT-- | ||
Before: | ||
array(2) refcount(2){ | ||
["root"]=> | ||
string(5) "array" refcount(1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this also a case where the values here are references, but There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, this test corresponds with bug1839-001, except for the use of an interned string vs. non-interned. |
||
["document"]=> | ||
string(5) "array" refcount(1) | ||
} | ||
After: | ||
array(2) refcount(2){ | ||
["root"]=> | ||
string(5) "array" refcount(1) | ||
["document"]=> | ||
string(5) "array" refcount(1) | ||
} | ||
===DONE=== |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
--TEST-- | ||
PHPC-1839: Non-referenced interned string in typeMap | ||
alcaeus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
--SKIPIF-- | ||
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?> | ||
<?php skip_if_not_live(); ?> | ||
<?php skip_if_not_clean(); ?> | ||
--FILE-- | ||
<?php | ||
require_once __DIR__ . "/../utils/basic.inc"; | ||
|
||
$rootValue = 'array'; | ||
$documentValue = 'array'; | ||
|
||
$typemap = ['root' => &$rootValue, 'document' => &$documentValue]; | ||
|
||
$manager = new MongoDB\Driver\Manager(URI); | ||
$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([])); | ||
|
||
echo "Before:\n"; | ||
debug_zval_dump($typemap); | ||
|
||
$cursor->setTypemap($typemap); | ||
|
||
echo "After:\n"; | ||
debug_zval_dump($typemap); | ||
|
||
?> | ||
===DONE=== | ||
<?php exit(0); ?> | ||
--EXPECT-- | ||
Before: | ||
array(2) refcount(2){ | ||
["root"]=> | ||
&string(5) "array" refcount(1) | ||
["document"]=> | ||
&string(5) "array" refcount(1) | ||
} | ||
After: | ||
array(2) refcount(2){ | ||
["root"]=> | ||
&string(5) "array" refcount(1) | ||
["document"]=> | ||
&string(5) "array" refcount(1) | ||
} | ||
===DONE=== |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, but do any of these tests actually need a live server? Could you test the same code path using
MongoDB\BSON\toPHP()
and a simple BSON document (e.g.0x05
followed by four null bytes).If you make that change, all of these test files can be moved to the
tests/bson
directory.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated and moved. Thanks for the suggestion.