-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue 1994 #2031
base: main
Are you sure you want to change the base?
Issue 1994 #2031
Conversation
dctrue2
commented
Dec 4, 2021
•
edited
Loading
edited
- Issue 1994 demonstrates how integer overflow issues are not properly handled.
- Added validation checks for parsing integers to ensure they fit within each data type's defined range; added corresponding tests.
6348091
to
38b639d
Compare
Convert each integer type to a BigInteger to validate that the value is within the proper range, otherwise throw a NumberFormatException. Added corresponding tests to JsonParserTest.
38b639d
to
bedcb10
Compare
Your changes look good, thanks! Could you please:
One issue with this approach might be lossless conversion from floating point values. Because your code uses Sorry for this long comment; I hope some of the points are helpful though. Also as side note: GitHub understands certain keywords. Could you please edit the description of your pull request and add the following, so GitHub understands that this pull request closes that issue:
Note that I am not a member of this project. Feel free to consider my comment only as suggestion. |
374354c
to
7c58d0a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking this on!
Though this is potentially a breaking change, it seems like the right thing to do, both because it fixes potential silent data loss and because it is consistent with what we do elsewhere (as detailed in the issue).
The new tests are great, but I had a few suggestions for the implementation changes.
@@ -203,6 +203,17 @@ public float getAsFloat() { | |||
*/ | |||
@Override | |||
public long getAsLong() { | |||
|
|||
if (isNumber()) { | |||
final BigInteger val = getAsBigInteger(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is suddenly very expensive if value
is already a Long
. getAsBigInteger()
will convert it to a string which it will then parse back into a new BigInteger
object. If this method is called more than once, it will do the same thing every time. I think it would be worth adding instanceof
checks to bypass this for when value
is Long
or any of the smaller java.lang
types, and likewise in the other cases. Also, you're checking isNumber()
here, so it looks as if you could reasonably move the true-case from the isNumber() ?
code below.
Also we can borrow an idea from the implementation of BigInteger.longValueExact()
for a simpler overflow check. (Since that method was added in Java 8 we unfortunately can't use it directly.)
I'm imagining code something like this:
if (isNumber()) {
if (value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof Byte) {
return ((Number) value).longValue();
}
BigInteger val = getAsBigInteger();
if (val.bitLength() >= 64) {...throw...}
return val.longValue();
}
return Long.parseLong(getAsString());
|
||
try { | ||
jsonObject.get("bigIntegerU").getAsLong(); | ||
fail("Big Integer values greater than Long.MAX_VALUE should not parse as a Long"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to write BigInteger
here with no space.
return isNumber() ? getAsNumber().intValue() : Integer.parseInt(getAsString()); | ||
} | ||
|
||
/** | ||
* convenience method to get this element as a primitive byte. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These methods can all throw NumberFormatException, even before this change. I think it is the javadoc of the overridden methods in JsonElement
that should be updated to reflect that.
I've run this change against Google's internal tests and unfortunately there were quite a few failures. It looks as if there might be about 10 distinct root causes, which fall into two main categories:
Although we could imagine tweaks to allow these cases to continue to work, or perhaps to update the tests so they don't trigger the problems, my feeling is that it is probably best to leave well enough alone. So I am probably going to close this PR and the associated issue. |
Sounds good @eamonnmcmanus and @Marcono1234! We greatly appreciate your feedback. Clearly, building in the necessary checks to make all possible test cases resolve as expected is a bit more laborious and expensive than at first glance from the initial issue posting. |
Just curious, are those tests running directly against the |