Skip to content

Commit a8a639b

Browse files
committed
PHPC-1006: Do not modify Persistable::bsonSerialize() retval
1 parent 065d28c commit a8a639b

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

src/bson-encode.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,11 @@ void php_phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *
401401
* properties, we'll need to filter them out later. */
402402
bool ht_data_from_properties = false;
403403

404+
/* If the object is an instance of MongoDB\BSON\Persistable, we will need to
405+
* inject the PHP class name as a BSON key and ignore any existing key in
406+
* the return value of bsonSerialize(). */
407+
bool skip_odm_field = false;
408+
404409
ZVAL_UNDEF(&obj_data);
405410

406411
switch(Z_TYPE_P(data)) {
@@ -455,11 +460,12 @@ void php_phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *
455460
if (instanceof_function(Z_OBJCE_P(data), php_phongo_persistable_ce TSRMLS_CC)) {
456461
#if PHP_VERSION_ID >= 70000
457462
bson_append_binary(bson, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t *)Z_OBJCE_P(data)->name->val, Z_OBJCE_P(data)->name->len);
458-
zend_hash_str_del(ht_data, PHONGO_ODM_FIELD_NAME, sizeof(PHONGO_ODM_FIELD_NAME)-1);
459463
#else
460464
bson_append_binary(bson, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t *)Z_OBJCE_P(data)->name, strlen(Z_OBJCE_P(data)->name));
461-
zend_hash_del(ht_data, PHONGO_ODM_FIELD_NAME, sizeof(PHONGO_ODM_FIELD_NAME));
462465
#endif
466+
/* Ensure that we ignore an existing key with the same name
467+
* if one exists in the bsonSerialize() return value. */
468+
skip_odm_field = true;
463469
}
464470

465471
break;
@@ -504,6 +510,10 @@ void php_phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *
504510
goto cleanup;
505511
}
506512

513+
if (skip_odm_field && !strcmp(ZSTR_VAL(string_key), PHONGO_ODM_FIELD_NAME)) {
514+
continue;
515+
}
516+
507517
if (flags & PHONGO_BSON_ADD_ID) {
508518
if (!strcmp(ZSTR_VAL(string_key), "_id")) {
509519
flags &= ~PHONGO_BSON_ADD_ID;
@@ -556,6 +566,10 @@ void php_phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *
556566
goto cleanup;
557567
}
558568

569+
if (skip_odm_field && !strcmp(string_key, PHONGO_ODM_FIELD_NAME)) {
570+
continue;
571+
}
572+
559573
if (flags & PHONGO_BSON_ADD_ID) {
560574
if (!strcmp(string_key, "_id")) {
561575
flags &= ~PHONGO_BSON_ADD_ID;

tests/bson/bug1006-001.phpt

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
--TEST--
2+
PHPC-1005: Do not modify memory of Persistable::bsonSerialize() return value
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/tools.php';
7+
8+
class MyClass implements MongoDB\BSON\Persistable
9+
{
10+
public $data;
11+
12+
public function __construct()
13+
{
14+
$this->data = [
15+
'__pclass' => 'baz',
16+
'foo' => 'bar',
17+
];
18+
}
19+
20+
function bsonSerialize()
21+
{
22+
return $this->data;
23+
}
24+
25+
function bsonUnserialize(array $data)
26+
{
27+
}
28+
}
29+
30+
$obj = new MyClass;
31+
var_dump($obj->data);
32+
hex_dump(fromPHP($obj));
33+
var_dump($obj->data);
34+
35+
?>
36+
===DONE===
37+
<?php exit(0); ?>
38+
--EXPECT--
39+
array(2) {
40+
["__pclass"]=>
41+
string(3) "baz"
42+
["foo"]=>
43+
string(3) "bar"
44+
}
45+
0 : 28 00 00 00 05 5f 5f 70 63 6c 61 73 73 00 07 00 [(....__pclass...]
46+
10 : 00 00 80 4d 79 43 6c 61 73 73 02 66 6f 6f 00 04 [...MyClass.foo..]
47+
20 : 00 00 00 62 61 72 00 00 [...bar..]
48+
array(2) {
49+
["__pclass"]=>
50+
string(3) "baz"
51+
["foo"]=>
52+
string(3) "bar"
53+
}
54+
===DONE===

0 commit comments

Comments
 (0)