Skip to content

Commit f5e4976

Browse files
committed
PHPC-314: Read fieldPaths elements and check for correct map types
1 parent 3fad0c5 commit f5e4976

File tree

2 files changed

+141
-1
lines changed

2 files changed

+141
-1
lines changed

src/bson.c

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,78 @@ static bool php_phongo_bson_state_parse_type(zval* options, const char* name, ph
12011201
return retval;
12021202
} /* }}} */
12031203

1204+
/* Loops over each element in the fieldPaths array (if exists, and is an
1205+
* array), and then checks whether each element is a valid type mapping */
1206+
bool php_phongo_bson_state_parse_fieldpaths(zval* typemap, php_phongo_bson_typemap* map TSRMLS_DC) /* {{{ */
1207+
{
1208+
zval* fieldpaths = NULL;
1209+
HashTable* ht_data;
1210+
1211+
if (!php_array_existsc(typemap, "fieldPaths")) {
1212+
return true;
1213+
}
1214+
1215+
fieldpaths = php_array_fetchc_array(typemap, "fieldPaths");
1216+
1217+
if (!fieldpaths) {
1218+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "The 'fieldPaths' element is not an array");
1219+
return false;
1220+
}
1221+
1222+
ht_data = HASH_OF(fieldpaths);
1223+
1224+
#if PHP_VERSION_ID >= 70000
1225+
{
1226+
zend_string* string_key = NULL;
1227+
zend_ulong num_key = 0;
1228+
zval* property;
1229+
1230+
ZEND_HASH_FOREACH_KEY_VAL(ht_data, num_key, string_key, property)
1231+
{
1232+
zend_class_entry* map_ce = NULL;
1233+
php_phongo_bson_typemap_types map_type;
1234+
1235+
if (!string_key) {
1236+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "The 'fieldPaths' element is not an associative array");
1237+
return false;
1238+
}
1239+
1240+
if (!php_phongo_bson_state_parse_type(fieldpaths, ZSTR_VAL(string_key), &map_type, &map_ce TSRMLS_CC)) {
1241+
return false;
1242+
}
1243+
}
1244+
ZEND_HASH_FOREACH_END();
1245+
}
1246+
#else
1247+
{
1248+
HashPosition pos;
1249+
zval** property;
1250+
1251+
for (
1252+
zend_hash_internal_pointer_reset_ex(ht_data, &pos);
1253+
zend_hash_get_current_data_ex(ht_data, (void**) &property, &pos) == SUCCESS;
1254+
zend_hash_move_forward_ex(ht_data, &pos)) {
1255+
1256+
char* string_key = NULL;
1257+
uint string_key_len = 0;
1258+
ulong num_key = 0;
1259+
zend_class_entry* map_ce = NULL;
1260+
php_phongo_bson_typemap_types map_type;
1261+
1262+
if (HASH_KEY_IS_STRING != zend_hash_get_current_key_ex(ht_data, &string_key, &string_key_len, &num_key, 0, &pos)) {
1263+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "The 'fieldPaths' element is not an associative array");
1264+
return false;
1265+
}
1266+
1267+
if (!php_phongo_bson_state_parse_type(fieldpaths, string_key, &map_type, &map_ce TSRMLS_CC)) {
1268+
return false;
1269+
}
1270+
}
1271+
}
1272+
#endif /* PHP_VERSION_ID >= 70000 */
1273+
return true;
1274+
} /* }}} */
1275+
12041276
/* Applies the array argument to a typemap struct. Returns true on success;
12051277
* otherwise, false is returned an an exception is thrown. */
12061278
bool php_phongo_bson_typemap_to_state(zval* typemap, php_phongo_bson_typemap* map TSRMLS_DC) /* {{{ */
@@ -1211,7 +1283,8 @@ bool php_phongo_bson_typemap_to_state(zval* typemap, php_phongo_bson_typemap* ma
12111283

12121284
if (!php_phongo_bson_state_parse_type(typemap, "array", &map->array_type, &map->array TSRMLS_CC) ||
12131285
!php_phongo_bson_state_parse_type(typemap, "document", &map->document_type, &map->document TSRMLS_CC) ||
1214-
!php_phongo_bson_state_parse_type(typemap, "root", &map->root_type, &map->root TSRMLS_CC)) {
1286+
!php_phongo_bson_state_parse_type(typemap, "root", &map->root_type, &map->root TSRMLS_CC) ||
1287+
!php_phongo_bson_state_parse_fieldpaths(typemap, map TSRMLS_CC)) {
12151288

12161289
/* Exception should already have been thrown */
12171290
return false;
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
--TEST--
2+
Cursor::setTypeMap(): fieldPaths must be an array, with single key/string elements
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php NEEDS('STANDALONE'); CLEANUP(STANDALONE); ?>
6+
--FILE--
7+
<?php
8+
9+
require_once __DIR__ . "/../utils/basic.inc";
10+
11+
abstract class MyAbstractDocument implements MongoDB\BSON\Unserializable {}
12+
13+
class MyDocument {}
14+
15+
$fieldPaths = [
16+
'notAnArray',
17+
['notAssociative'],
18+
['missing' => 'MissingClass'],
19+
['abstract' => 'MyAbstractDocument'],
20+
['my' => 'MyDocument'],
21+
['unserialize' => 'MongoDB\BSON\Unserializable'],
22+
];
23+
24+
$manager = new MongoDB\Driver\Manager(STANDALONE);
25+
$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([]));
26+
27+
foreach ($fieldPaths as $fieldPath) {
28+
$typeMap = ['fieldPaths' => $fieldPath];
29+
30+
printf("Test typeMap: %s\n", json_encode($typeMap));
31+
32+
echo throws(function() use ($cursor, $typeMap) {
33+
$cursor->setTypeMap($typeMap);
34+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
35+
36+
echo "\n";
37+
}
38+
39+
?>
40+
===DONE===
41+
<?php exit(0); ?>
42+
--EXPECT--
43+
Test typeMap: {"fieldPaths":"notAnArray"}
44+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
45+
The 'fieldPaths' element is not an array
46+
47+
Test typeMap: {"fieldPaths":["notAssociative"]}
48+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
49+
The 'fieldPaths' element is not an associative array
50+
51+
Test typeMap: {"fieldPaths":{"missing":"MissingClass"}}
52+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
53+
Class MissingClass does not exist
54+
55+
Test typeMap: {"fieldPaths":{"abstract":"MyAbstractDocument"}}
56+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
57+
Class MyAbstractDocument is not instantiatable
58+
59+
Test typeMap: {"fieldPaths":{"my":"MyDocument"}}
60+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
61+
Class MyDocument does not implement MongoDB\BSON\Unserializable
62+
63+
Test typeMap: {"fieldPaths":{"unserialize":"MongoDB\\BSON\\Unserializable"}}
64+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
65+
Class MongoDB\BSON\Unserializable is not instantiatable
66+
67+
===DONE===

0 commit comments

Comments
 (0)