Closed wmjordan closed 5 years ago
The screenshot of problem 2.
Thanks for the submission
I would try to work on this this week/weekend. But if you have bandwidth to help me with it, that would be nice too.
Thanks,
It was very very strange that the security issue 2 could not be reproduced on my computer. I checked the source code and could not find any clue why the pointer could go wrong. For security issue 1 is quite easy to fix, but performance issues need a little more time.
Maybe the issue is only in the latest nuget package and not the source code?
I was forking the latest source code when I met with the above issues.
I found fixing the security issue 1 would need passing one more parameter length
to the DecodeJSONString
method, the problem spread further beyond my first thought.
Length of the string or the hexidecimal \u value?
The whole JSON string.
The following code reproduced the issue either:
NetJSON.NetJSON.Deserialize<string>("\"abc")
Since the JSON code was not correctly terminated, the DecodeJSONString
method could read beyond the end of the string.
NetJSON would report "Input is not a valid JSON.", or read too much until it happen to meet with another code somewhere in the memory.
My second thought was that passing a pointer to the end of the string might be more efficient and easier to implement.
I could put a check for \0 null pointer value to break out of the infinite loop and only throw that error for non primitive type
Thanks,
Putting in the checks slows than decoding of string. I would like to find a way to know quickly without reading all the string similar to string skipping for property and keys in the dictionary.
using the following
var value = NetJSON.Deserialize<string[]>("[\"\\"ab\"]"); with escape for the "\" will give you the expected array of "ab . Without it, it will throw invalid json due to my current logic since it is depending on the escape of \ because it cannot detect end of the string been evaluate since it is character by character and also because it assume a string starts with " and ends with ".
if you add the logic to check for the "\0" then you will have to magically detect when you are deserializing a regular string and a complex type else the first \" in the string will get swallowed up
I believe i resolved both the current issues. I figured out a quick way to detect plain strings and it context by checking simply for index of zero for the decode method.
Please test with the latest pointing to this commit and let me know if all the issues are resolved: https://github.com/rpgmaker/NetJSON/commit/afdeb40b48b826b689795f75362f59f1a8cafdb4
If it is resolved, please close this ticket.
Thanks,
Problem 1 was solved by adding the check for '\0' in the last commit.
I also added the performance suggestion for number 3-4 here: https://github.com/rpgmaker/NetJSON/commit/e7df7adb7fe0d0c3de089691546a8b95b853fe90
I did not do perf 2 because i will still have to convert the string from hex to number, and it seem easier to use int.parse and collect the string once. Plus, internally, the new string uses the fast alloc and also navigate the pointer smarter to create the string. So it is a little different from the typically "".
if you could implement the perf #2 solution for me. Then i can add it in as a pull request.
Thanks,
Great, I've also just learned that .NET strings are both length-prefixed and zero-terminated. Checking the trailing zero char can quickly determine the end of the string, unless that somehow the string contains zero char--it is possible in .NET strings. The alternative is solution is to move the pointer backward by a int* where you can get the length of the string.
var s = "string";
fixed(char* ptr = s) {
int* l = (char*)ptr;
--l;
Assert.IsTrue(*l == s.Length);
}
I will look for some time to see whether I can solve the problem 1 and problem 2.
Thanks for the update.
I am closing this issue since there is a PR for it.
1) Security and performance problems
There're some problems in the source code of the
DecodeJSONString
method, in the Unicode decoding section for \u????.2) Security problem about single quoted string:
The above statement will produce unexpected result like the following (executed in the C# Intermediate window of VS):