@@ -362,20 +362,27 @@ _noop (void)
362362 return; \
363363 } else \
364364 (void) 0
365- #define HANDLE_OPTION (_selection_statement , _key , _type , _state ) \
366- _selection_statement (len == strlen (_key) && strncmp ((const char *) val, (_key), len) == 0) \
367- { \
368- if (bson->bson_type && bson->bson_type != (_type)) { \
369- _bson_json_read_set_error (reader, \
370- "Invalid key \"%s\". Looking for values " \
371- "for type \"%s\", got \"%s\"", \
372- (_key), \
373- _bson_json_type_name (bson->bson_type), \
374- _bson_json_type_name (_type)); \
375- return; \
376- } \
377- bson->bson_type = (_type); \
378- bson->bson_state = (_state); \
365+
366+ #define HANDLE_OPTION_KEY_COMPARE (_key ) (len == strlen (_key) && memcmp (key, (_key), len) == 0)
367+
368+ #define HANDLE_OPTION_TYPE_CHECK (_key , _type ) \
369+ if (bson->bson_type && bson->bson_type != (_type)) { \
370+ _bson_json_read_set_error (reader, \
371+ "Invalid key \"%s\". Looking for values " \
372+ "for type \"%s\", got \"%s\"", \
373+ (_key), \
374+ _bson_json_type_name (bson->bson_type), \
375+ _bson_json_type_name (_type)); \
376+ return; \
377+ } \
378+ ((void) 0)
379+
380+ #define HANDLE_OPTION (_selection_statement , _key , _type , _state ) \
381+ _selection_statement (HANDLE_OPTION_KEY_COMPARE (_key)) \
382+ { \
383+ HANDLE_OPTION_TYPE_CHECK (_key, _type); \
384+ bson->bson_type = (_type); \
385+ bson->bson_state = (_state); \
379386 }
380387
381388
@@ -1159,23 +1166,40 @@ _bson_json_read_start_map (bson_json_reader_t *reader) /* IN */
11591166}
11601167
11611168
1169+ #define BSON_PRIVATE_SPECIAL_KEYS_XMACRO (X ) \
1170+ X (binary) \
1171+ X (code) \
1172+ X (date) \
1173+ X (dbPointer) \
1174+ X (maxKey) \
1175+ X (minKey) \
1176+ X (numberDecimal) \
1177+ X (numberDouble) \
1178+ X (numberInt) \
1179+ X (numberLong) \
1180+ X (oid) \
1181+ X (options) \
1182+ X (regex) \
1183+ X (regularExpression) \
1184+ X (scope) \
1185+ X (symbol) \
1186+ X (timestamp) \
1187+ X (type) \
1188+ X (undefined) \
1189+ X (uuid)
1190+
1191+
11621192static bool
11631193_is_known_key (const char * key , size_t len )
11641194{
1165- bool ret ;
1166-
1167- #define IS_KEY (k ) (len == strlen (k) && (0 == memcmp (k, key, len)))
1168-
1169- ret = (IS_KEY ("$regularExpression" ) || IS_KEY ("$regex" ) || IS_KEY ("$options" ) || IS_KEY ("$code" ) ||
1170- IS_KEY ("$scope" ) || IS_KEY ("$oid" ) || IS_KEY ("$binary" ) || IS_KEY ("$type" ) || IS_KEY ("$date" ) ||
1171- IS_KEY ("$undefined" ) || IS_KEY ("$maxKey" ) || IS_KEY ("$minKey" ) || IS_KEY ("$timestamp" ) ||
1172- IS_KEY ("$numberInt" ) || IS_KEY ("$numberLong" ) || IS_KEY ("$numberDouble" ) || IS_KEY ("$numberDecimal" ) ||
1173- IS_KEY ("$numberInt" ) || IS_KEY ("$numberLong" ) || IS_KEY ("$numberDouble" ) || IS_KEY ("$numberDecimal" ) ||
1174- IS_KEY ("$dbPointer" ) || IS_KEY ("$symbol" ) || IS_KEY ("$uuid" ));
1175-
1195+ #define IS_KEY (k ) \
1196+ if (len == strlen ("$" #k) && (0 == memcmp ("$" #k, key, len))) { \
1197+ return true; \
1198+ }
1199+ BSON_PRIVATE_SPECIAL_KEYS_XMACRO (IS_KEY )
11761200#undef IS_KEY
11771201
1178- return ret ;
1202+ return false ;
11791203}
11801204
11811205static void
@@ -1242,9 +1266,10 @@ _bson_json_read_map_key (bson_json_reader_t *reader, /* IN */
12421266 return ;
12431267 }
12441268
1269+ const char * const key = (const char * ) val ;
1270+
12451271 if (bson -> read_state == BSON_JSON_IN_START_MAP ) {
1246- if (len > 0 && val [0 ] == '$' && _is_known_key ((const char * ) val , len ) &&
1247- bson -> n >= 0 /* key is in subdocument */ ) {
1272+ if (len > 0 && key [0 ] == '$' && _is_known_key (key , len ) && bson -> n >= 0 /* key is in subdocument */ ) {
12481273 bson -> read_state = BSON_JSON_IN_BSON_TYPE ;
12491274 bson -> bson_type = (bson_type_t ) 0 ;
12501275 memset (& bson -> bson_type_data , 0 , sizeof bson -> bson_type_data );
@@ -1281,30 +1306,42 @@ _bson_json_read_map_key (bson_json_reader_t *reader, /* IN */
12811306 HANDLE_OPTION (else if , "$numberDouble" , BSON_TYPE_DOUBLE , BSON_JSON_LF_DOUBLE )
12821307 HANDLE_OPTION (else if , "$symbol" , BSON_TYPE_SYMBOL , BSON_JSON_LF_SYMBOL )
12831308 HANDLE_OPTION (else if , "$numberDecimal" , BSON_TYPE_DECIMAL128 , BSON_JSON_LF_DECIMAL128 )
1284- else if (! strcmp ("$timestamp" , ( const char * ) val ))
1309+ else if (HANDLE_OPTION_KEY_COMPARE ("$timestamp" ))
12851310 {
1311+ HANDLE_OPTION_TYPE_CHECK ("$timestamp" , BSON_TYPE_TIMESTAMP );
12861312 bson -> bson_type = BSON_TYPE_TIMESTAMP ;
12871313 bson -> read_state = BSON_JSON_IN_BSON_TYPE_TIMESTAMP_STARTMAP ;
12881314 }
1289- else if (! strcmp ("$regularExpression" , ( const char * ) val ))
1315+ else if (HANDLE_OPTION_KEY_COMPARE ("$regularExpression" ))
12901316 {
1317+ HANDLE_OPTION_TYPE_CHECK ("$regularExpression" , BSON_TYPE_REGEX );
12911318 bson -> bson_type = BSON_TYPE_REGEX ;
12921319 bson -> read_state = BSON_JSON_IN_BSON_TYPE_REGEX_STARTMAP ;
12931320 }
1294- else if (! strcmp ("$dbPointer" , ( const char * ) val ))
1321+ else if (HANDLE_OPTION_KEY_COMPARE ("$dbPointer" ))
12951322 {
1323+ HANDLE_OPTION_TYPE_CHECK ("$dbPointer" , BSON_TYPE_DBPOINTER );
1324+
12961325 /* start parsing "key": {"$dbPointer": {...}}, save "key" for later */
12971326 _bson_json_buf_set (& bson -> dbpointer_key , bson -> key , bson -> key_buf .len );
12981327
12991328 bson -> bson_type = BSON_TYPE_DBPOINTER ;
13001329 bson -> read_state = BSON_JSON_IN_BSON_TYPE_DBPOINTER_STARTMAP ;
13011330 }
1302- else if (! strcmp ("$code" , ( const char * ) val ))
1331+ else if (HANDLE_OPTION_KEY_COMPARE ("$code" ))
13031332 {
1333+ // "$code" may come after "$scope".
1334+ if (bson -> bson_type != BSON_TYPE_CODEWSCOPE ) {
1335+ HANDLE_OPTION_TYPE_CHECK ("$code" , BSON_TYPE_CODE );
1336+ }
13041337 _bson_json_read_code_or_scope_key (bson , false /* is_scope */ , val , len );
13051338 }
1306- else if (! strcmp ("$scope" , ( const char * ) val ))
1339+ else if (HANDLE_OPTION_KEY_COMPARE ("$scope" ))
13071340 {
1341+ // "$scope" may come after "$code".
1342+ if (bson -> bson_type != BSON_TYPE_CODE ) {
1343+ HANDLE_OPTION_TYPE_CHECK ("$scope" , BSON_TYPE_CODEWSCOPE );
1344+ }
13081345 _bson_json_read_code_or_scope_key (bson , true /* is_scope */ , val , len );
13091346 }
13101347 else
0 commit comments