Skip to content

Commit b3b3a55

Browse files
committed
PHPC-884: Do not skip public property with empty string name during BSON encoding
This removes our is_public_property() helper function in favor of a simpler check on the mangled property name (as done by PHP's json_encode() function).
1 parent d65aa7a commit b3b3a55

File tree

2 files changed

+47
-79
lines changed

2 files changed

+47
-79
lines changed

src/bson.c

Lines changed: 20 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,44 +1271,6 @@ static void phongo_bson_append(bson_t *bson, php_phongo_bson_flags_t flags, cons
12711271
}
12721272
}
12731273

1274-
#if PHP_VERSION_ID >= 70000
1275-
static bool is_public_property(zend_class_entry *ce, zend_string *name, zend_string **member TSRMLS_DC) /* {{{ */
1276-
#else
1277-
static bool is_public_property(zend_class_entry *ce, const char *prop_name, int prop_name_len TSRMLS_DC) /* {{{ */
1278-
#endif
1279-
{
1280-
zend_property_info *property_info = NULL;
1281-
1282-
#if PHP_VERSION_ID >= 70000
1283-
if (ZSTR_VAL(name)[0] == 0) {
1284-
const char *prop_name,
1285-
*class_name;
1286-
size_t prop_name_len;
1287-
1288-
zend_unmangle_property_name_ex(name,
1289-
&class_name, &prop_name, &prop_name_len);
1290-
(*member) = zend_string_init(prop_name, prop_name_len, 0);
1291-
} else (*member) = zend_string_copy(name);
1292-
property_info = zend_get_property_info(ce, (*member), 1 TSRMLS_CC);
1293-
1294-
if (!property_info) /* undefined property */
1295-
return true;
1296-
1297-
if (property_info == ZEND_WRONG_PROPERTY_INFO) {
1298-
return false;
1299-
}
1300-
1301-
return (property_info->flags & ZEND_ACC_PUBLIC);
1302-
#else
1303-
zval member;
1304-
ZVAL_STRINGL(&member, prop_name, prop_name_len, 0);
1305-
property_info = zend_get_property_info(ce, &member, 1 TSRMLS_CC);
1306-
1307-
return (property_info && (property_info->flags & ZEND_ACC_PUBLIC));
1308-
#endif
1309-
}
1310-
/* }}} */
1311-
13121274
void phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *bson, bson_t **bson_out TSRMLS_DC) /* {{{ */
13131275
{
13141276
HashTable *ht_data = NULL;
@@ -1422,49 +1384,31 @@ void phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *bson
14221384
zval *value;
14231385

14241386
ZEND_HASH_FOREACH_KEY_VAL(ht_data, num_key, string_key, value) {
1425-
/* Ensure we're working with a string key */
1426-
if (!string_key) {
1427-
string_key = zend_long_to_str(num_key);
1428-
} else {
1429-
zend_string_addref(string_key);
1430-
}
1431-
1432-
if (Z_TYPE_P(data) == IS_OBJECT) {
1433-
zend_string *member = NULL;
1434-
1435-
/* Ignore non-public properties */
1436-
if (!instanceof_function(Z_OBJCE_P(data), php_phongo_serializable_ce) &&
1437-
!is_public_property(Z_OBJCE_P(data), string_key, &member TSRMLS_CC)) {
1438-
if (member) {
1439-
zend_string_release(member);
1387+
if (string_key) {
1388+
if (ht_data_from_properties) {
1389+
/* Skip protected and private properties */
1390+
if (ZSTR_VAL(string_key)[0] == '\0' && ZSTR_LEN(string_key) > 0) {
1391+
zend_string_release(string_key);
1392+
continue;
14401393
}
1441-
zend_string_release(string_key);
1442-
continue;
14431394
}
14441395

14451396
if (flags & PHONGO_BSON_ADD_ID) {
1446-
if (!strcmp(member ? ZSTR_VAL(member) : ZSTR_VAL(string_key), "_id")) {
1397+
if (!strcmp(ZSTR_VAL(string_key), "_id")) {
14471398
flags &= ~PHONGO_BSON_ADD_ID;
14481399
}
14491400
}
1401+
}
14501402

1451-
phongo_bson_append(bson, flags & ~PHONGO_BSON_ADD_ID,
1452-
member ? ZSTR_VAL(member) : ZSTR_VAL(string_key),
1453-
member ? ZSTR_LEN(member) : ZSTR_LEN(string_key),
1454-
value TSRMLS_CC);
1455-
1456-
if (member) {
1457-
zend_string_release(member);
1458-
}
1403+
/* Ensure we're working with a string key */
1404+
if (!string_key) {
1405+
string_key = zend_long_to_str(num_key);
14591406
} else {
1460-
if (flags & PHONGO_BSON_ADD_ID) {
1461-
if (!strcmp(ZSTR_VAL(string_key), "_id")) {
1462-
flags &= ~PHONGO_BSON_ADD_ID;
1463-
}
1464-
}
1465-
phongo_bson_append(bson, flags & ~PHONGO_BSON_ADD_ID, ZSTR_VAL(string_key), ZSTR_LEN(string_key), value TSRMLS_CC);
1407+
zend_string_addref(string_key);
14661408
}
14671409

1410+
phongo_bson_append(bson, flags & ~PHONGO_BSON_ADD_ID, ZSTR_VAL(string_key), strlen(ZSTR_VAL(string_key)), value TSRMLS_CC);
1411+
14681412
zend_string_release(string_key);
14691413
} ZEND_HASH_FOREACH_END();
14701414
}
@@ -1489,24 +1433,21 @@ void phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *bson
14891433

14901434
if (hash_type == HASH_KEY_IS_STRING) {
14911435
if (ht_data_from_properties) {
1492-
const char *class_name;
1493-
zend_unmangle_property_name(string_key, string_key_len-1, &class_name, (const char **)&string_key);
1494-
string_key_len = strlen(string_key);
1495-
1496-
/* Ignore non-public properties */
1497-
if (!is_public_property(Z_OBJCE_P(data), string_key, string_key_len TSRMLS_CC)) {
1436+
/* Skip protected and private properties */
1437+
if (string_key[0] == '\0' && string_key_len > 1) {
14981438
continue;
14991439
}
1500-
} else {
1501-
/* Chop off the \0 from string lengths */
1502-
string_key_len -= 1;
15031440
}
15041441

15051442
if (flags & PHONGO_BSON_ADD_ID) {
15061443
if (!strcmp(string_key, "_id")) {
15071444
flags &= ~PHONGO_BSON_ADD_ID;
15081445
}
15091446
}
1447+
1448+
/* PHP's HashTable API includes the terminating NULL byte in key's
1449+
* string length, so subtract to track the equivalent strlen(). */
1450+
string_key_len -= 1;
15101451
}
15111452

15121453
/* Ensure we're working with a string key */

tests/bson/bson-fromPHP-005.phpt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
BSON\fromPHP(): PHP document with public property whose name is an empty string
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/tools.php';
7+
8+
$tests = [
9+
['' => 1],
10+
(object) ['' => 1],
11+
];
12+
13+
foreach ($tests as $document) {
14+
$s = fromPHP($document);
15+
echo "Test ", toJSON($s), "\n";
16+
hex_dump($s);
17+
}
18+
19+
?>
20+
===DONE===
21+
<?php exit(0); ?>
22+
--EXPECT--
23+
Test { "" : 1 }
24+
0 : 0b 00 00 00 10 00 01 00 00 00 00 [...........]
25+
Test { "" : 1 }
26+
0 : 0b 00 00 00 10 00 01 00 00 00 00 [...........]
27+
===DONE===

0 commit comments

Comments
 (0)