[CDRIVER-1974] BSON_TYPE_CODE and BSON_TYPE_CODEWSCOPE fail to roundtrip through JSON correctly Created: 01/Jan/17  Updated: 08/Feb/17  Resolved: 04/Jan/17

Status: Closed
Project: C Driver
Component/s: json, libbson
Affects Version/s: None
Fix Version/s: 1.6.0

Type: Bug Priority: Major - P3
Reporter: Arseny Vakhrushev Assignee: A. Jesse Jiryu Davis
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: File libbson2.c    

 Description   

Two BSON types, namely BSON_TYPE_CODE and BSON_TYPE_CODEWSCOPE, fail to transition through their JSON representation.

In case of BSON_TYPE_CODE, its binary data will be different from the source document. That's especially weird because the JSON representation is restored with no difference.

In case of BSON_TYPE_CODEWSCOPE, both the binary data and the JSON representation will be different from the source document when scope is an empty document (note the additional space between the scope brackets). When scope is not empty, the binary data will differ.

Example:

#include <stdio.h>
#include <bson.h>
 
void test(const bson_t *src) {
	char *json = bson_as_json(src, 0); // src -> json
	bson_t *dst = bson_new_from_json(json, -1, 0); // json -> dst
	char *json_ = bson_as_json(dst, 0); // dst -> json_
 
	BSON_ASSERT(json && dst && json_); // No errors
 
	printf("Testing %s\n", json);
	printf("... and %s\n", json_);
	printf("* as JSON - %s\n", strcmp(json, json_) ? "failed!!!" : "OK"); // Compare as JSON
	printf("* as binary - %s\n", !bson_equal(src, dst) ? "failed!!!" : "OK"); // Compare as binary
	printf("\n");
 
	bson_destroy(dst);
	bson_free(json);
	bson_free(json_);
}
 
int main() {
	bson_t *b1 = bson_new();
	bson_t *b2 = bson_new();
	bson_t *b3 = bson_new();
	bson_t *b4 = bson_new();
	bson_t *scope = bson_new();
 
	// All types roundtrip alright, for example:
 
	BSON_APPEND_BINARY(b1, "a", 0x80, "abc", 3);
	BSON_APPEND_MINKEY(b1, "b");
	BSON_APPEND_REGEX(b1, "c", "abc", "def");
	test(b1);
 
	// Except for these guys:
 
	BSON_APPEND_CODE(b2, "a", "abc");
	test(b2);
 
	BSON_APPEND_CODE_WITH_SCOPE(b3, "a", "abc", scope);
	test(b3);
 
	BSON_APPEND_BOOL(scope, "bool", 1); // Non-empty scope now
	BSON_APPEND_CODE_WITH_SCOPE(b4, "a", "abc", scope);
	test(b4);
 
	bson_destroy(b1);
	bson_destroy(b2);
	bson_destroy(b3);
	bson_destroy(b4);
	bson_destroy(scope);
	return 0;
}

Output:

Testing { "a" : { "$binary" : "YWJj", "$type" : "80" }, "b" : { "$minKey" : 1 }, "c" : { "$regex" : "abc", "$options" : "def" } }
... and { "a" : { "$binary" : "YWJj", "$type" : "80" }, "b" : { "$minKey" : 1 }, "c" : { "$regex" : "abc", "$options" : "def" } }
* as JSON - OK
* as binary - OK
 
Testing { "a" : { "$code" : "abc" } }
... and { "a" : { "$code" : "abc" } }
* as JSON - OK
* as binary - failed!!!
 
Testing { "a" : { "$code" : "abc", "$scope" : { } } }
... and { "a" : { "$code" : "abc", "$scope" : {  } } }
* as JSON - failed!!!
* as binary - failed!!!
 
Testing { "a" : { "$code" : "abc", "$scope" : { "bool" : true } } }
... and { "a" : { "$code" : "abc", "$scope" : { "bool" : true } } }
* as JSON - OK
* as binary - failed!!!



 Comments   
Comment by Arseny Vakhrushev [ 08/Feb/17 ]

No prob. Will do.

Comment by A. Jesse Jiryu Davis [ 08/Feb/17 ]

Ah. Yeah, I didn't understand what issue you were reporting. If you'd like to report that we have a strange error message when parsing a top-level document with a $scope field, could you open a new issue that says exactly that please?

Comment by Arseny Vakhrushev [ 08/Feb/17 ]

Hey Jesse. Well thanks for your answer!

I am aware that these two JSONs aren't valid. The stress is on the error message actually, in particular, the difference between them.

Let me try again. I know that this is invalid ...

{ "$code" : "abc" }

... and I get what I deserve:

Invalid MongoDB extended JSON

But when I add a scope (the whole thing is still invalid), ...

{ "$code" : "abc", "$scope" : { "a" : 123 } } }

... I get something that I can't understand:

Invalid state 1

Hope it makes more sense now. Could be an indicator of some bug or at least some apparent inconsistency.

Comment by A. Jesse Jiryu Davis [ 08/Feb/17 ]

Hi Arseny. Code and Code With Scope types of elements of a BSON document. They can't stand alone. This works:

{"field_name": {"$code": "abc"}}
{"field_name": {"$code": "abc", "$scope": {"a": 1}}}

If that doesn't make sense, consider this question. Is this a JSON representation of a valid BSON document?:

1

No it isn't. Integers must be elements of a BSON document. This works:

{"field_name": 1}

Same with Code elements.

Comment by Arseny Vakhrushev [ 08/Feb/17 ]

I didn't want to create a separate issue, but if I do this:

#include <stdio.h>
#include <bson.h>
 
void test(const char *json) {
	bson_error_t error;
	bson_t *bson = bson_new_from_json(json, -1, &error);
	printf("%s --> ", json);
	if (!bson) printf("ERROR: %s\n", error.message);
	else {
		printf("OK\n");
		bson_destroy(bson);
	}
}
 
int main() {
	test("{ \"$code\" : \"abc\" }");
	test("{ \"$code\" : \"abc\", \"$scope\" : { \"a\" : 1 } } }");
	return 0;
}

I get this:

$ ./a.out
{ "$code" : "abc" } --> ERROR: Invalid MongoDB extended JSON
{ "$code" : "abc", "$scope" : { "a" : 1 } } } --> ERROR: Invalid state 1

What in the world is "Invalid state 1"?

Comment by Arseny Vakhrushev [ 04/Jan/17 ]

Great news indeed! Thanks Jesse! I will be looking forward to the next release then.

Comment by A. Jesse Jiryu Davis [ 04/Jan/17 ]

Thanks for the report. Good news, this has already been fixed on master, as part of the JSONSL port and code with scope fixes (CDRIVER-1370, CDRIVER-1913). I linked your program against libbson on master and it prints "OK" for all tests.

Comment by Arseny Vakhrushev [ 01/Jan/17 ]

Happy new year lol!

Generated at Wed Feb 07 21:13:46 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.