Skip to content

Commit da47bb9

Browse files
committed
PHPC-1839 Fix accessing referenced non-interned strings
1 parent 1dcfb80 commit da47bb9

File tree

5 files changed

+209
-0
lines changed

5 files changed

+209
-0
lines changed

src/contrib/php_array_api.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,12 @@ PHP_ARRAY_FETCH_TYPE_MAP(zend_bool, bool)
281281
*/
282282
static inline
283283
PAA_LONG php_array_zval_to_long(zval *z) {
284+
try_again:
284285
if (!z) { return 0; }
285286
switch(Z_TYPE_P(z)) {
287+
case IS_REFERENCE:
288+
z = Z_REFVAL_P(z);
289+
goto try_again;
286290
case IS_NULL: return 0;
287291
#ifdef ZEND_ENGINE_3
288292
case IS_FALSE: return 0;
@@ -315,8 +319,12 @@ PHP_ARRAY_FETCH_TYPE_MAP(PAA_LONG, long)
315319
*/
316320
static inline
317321
double php_array_zval_to_double(zval *z) {
322+
try_again:
318323
if (!z) { return 0.0; }
319324
switch (Z_TYPE_P(z)) {
325+
case IS_REFERENCE:
326+
z = Z_REFVAL_P(z);
327+
goto try_again;
320328
case IS_NULL: return 0.0;
321329
#ifdef ZEND_ENGINE_3
322330
case IS_FALSE: return 0.0;
@@ -357,10 +365,14 @@ static inline
357365
char *php_array_zval_to_string(zval *z, int *plen, zend_bool *pfree) {
358366
*plen = 0;
359367
*pfree = 0;
368+
try_again:
360369
if (!z) { return NULL; }
361370
switch (Z_TYPE_P(z)) {
362371
case IS_NULL:
363372
return (char *)"";
373+
case IS_REFERENCE:
374+
z = Z_REFVAL_P(z);
375+
goto try_again;
364376
case IS_STRING:
365377
*plen = Z_STRLEN_P(z);
366378
return Z_STRVAL_P(z);

tests/cursor/bug1839-001.phpt

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
--TEST--
2+
PHPC-1839: Referenced, out-of-scope, non-interned string in typeMap
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php skip_if_not_live(); ?>
6+
<?php skip_if_not_clean(); ?>
7+
--FILE--
8+
<?php
9+
require_once __DIR__ . "/../utils/basic.inc";
10+
11+
function createTypemap()
12+
{
13+
// Assemble the string so as to not have an interned string
14+
$rootValue = chr(ord('a')) . 'rray';
15+
$documentValue = chr(ord('a')) . 'rray';
16+
17+
// Use a reference to this non-interned string in the type map
18+
$typemap = ['root' => &$rootValue, 'document' => &$documentValue];
19+
20+
return $typemap;
21+
}
22+
23+
$typemap = createTypemap();
24+
25+
$manager = new MongoDB\Driver\Manager(URI);
26+
$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([]));
27+
28+
echo "Before:\n";
29+
debug_zval_dump($typemap);
30+
31+
$cursor->setTypemap($typemap);
32+
33+
echo "After:\n";
34+
debug_zval_dump($typemap);
35+
36+
?>
37+
===DONE===
38+
<?php exit(0); ?>
39+
--EXPECT--
40+
Before:
41+
array(2) refcount(2){
42+
["root"]=>
43+
string(5) "array" refcount(1)
44+
["document"]=>
45+
string(5) "array" refcount(1)
46+
}
47+
After:
48+
array(2) refcount(2){
49+
["root"]=>
50+
string(5) "array" refcount(1)
51+
["document"]=>
52+
string(5) "array" refcount(1)
53+
}
54+
===DONE===

tests/cursor/bug1839-002.phpt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--TEST--
2+
PHPC-1839: Referenced local non-interned string in typeMap
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php skip_if_not_live(); ?>
6+
<?php skip_if_not_clean(); ?>
7+
--FILE--
8+
<?php
9+
require_once __DIR__ . "/../utils/basic.inc";
10+
11+
// Assemble the string so as to not have an interned string
12+
$rootValue = chr(ord('a')) . 'rray';
13+
$documentValue = chr(ord('a')) . 'rray';
14+
15+
$typemap = ['root' => &$rootValue, 'document' => &$documentValue];
16+
17+
$manager = new MongoDB\Driver\Manager(URI);
18+
$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([]));
19+
20+
echo "Before:\n";
21+
debug_zval_dump($typemap);
22+
23+
$cursor->setTypemap($typemap);
24+
25+
echo "After:\n";
26+
debug_zval_dump($typemap);
27+
28+
?>
29+
===DONE===
30+
<?php exit(0); ?>
31+
--EXPECT--
32+
Before:
33+
array(2) refcount(2){
34+
["root"]=>
35+
&string(5) "array" refcount(1)
36+
["document"]=>
37+
&string(5) "array" refcount(1)
38+
}
39+
After:
40+
array(2) refcount(2){
41+
["root"]=>
42+
&string(5) "array" refcount(1)
43+
["document"]=>
44+
&string(5) "array" refcount(1)
45+
}
46+
===DONE===

tests/cursor/bug1839-003.phpt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
--TEST--
2+
PHPC-1839: Referenced, out-of-scope interned string in typeMap
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php skip_if_not_live(); ?>
6+
<?php skip_if_not_clean(); ?>
7+
--FILE--
8+
<?php
9+
require_once __DIR__ . "/../utils/basic.inc";
10+
11+
function createTypemap()
12+
{
13+
$rootValue = 'array';
14+
$documentValue = 'array';
15+
16+
$typemap = ['root' => &$rootValue, 'document' => &$documentValue];
17+
18+
return $typemap;
19+
}
20+
21+
$typemap = createTypemap();
22+
23+
$manager = new MongoDB\Driver\Manager(URI);
24+
$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([]));
25+
26+
echo "Before:\n";
27+
debug_zval_dump($typemap);
28+
29+
$cursor->setTypemap($typemap);
30+
31+
echo "After:\n";
32+
debug_zval_dump($typemap);
33+
34+
?>
35+
===DONE===
36+
<?php exit(0); ?>
37+
--EXPECT--
38+
Before:
39+
array(2) refcount(2){
40+
["root"]=>
41+
string(5) "array" refcount(1)
42+
["document"]=>
43+
string(5) "array" refcount(1)
44+
}
45+
After:
46+
array(2) refcount(2){
47+
["root"]=>
48+
string(5) "array" refcount(1)
49+
["document"]=>
50+
string(5) "array" refcount(1)
51+
}
52+
===DONE===

tests/cursor/bug1839-004.phpt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
PHPC-1839: Non-referenced interned string in typeMap
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php skip_if_not_live(); ?>
6+
<?php skip_if_not_clean(); ?>
7+
--FILE--
8+
<?php
9+
require_once __DIR__ . "/../utils/basic.inc";
10+
11+
$rootValue = 'array';
12+
$documentValue = 'array';
13+
14+
$typemap = ['root' => &$rootValue, 'document' => &$documentValue];
15+
16+
$manager = new MongoDB\Driver\Manager(URI);
17+
$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([]));
18+
19+
echo "Before:\n";
20+
debug_zval_dump($typemap);
21+
22+
$cursor->setTypemap($typemap);
23+
24+
echo "After:\n";
25+
debug_zval_dump($typemap);
26+
27+
?>
28+
===DONE===
29+
<?php exit(0); ?>
30+
--EXPECT--
31+
Before:
32+
array(2) refcount(2){
33+
["root"]=>
34+
&string(5) "array" refcount(1)
35+
["document"]=>
36+
&string(5) "array" refcount(1)
37+
}
38+
After:
39+
array(2) refcount(2){
40+
["root"]=>
41+
&string(5) "array" refcount(1)
42+
["document"]=>
43+
&string(5) "array" refcount(1)
44+
}
45+
===DONE===

0 commit comments

Comments
 (0)