8000 fix: handle NaN and Infinity float values in gRPC by ariasmn · Pull Request #4631 · grafana/k6 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

fix: handle NaN and Infinity float values in gRPC #4631

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

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

ariasmn
Copy link
Contributor
@ariasmn ariasmn commented Mar 15, 2025

Fixes (?): #3990

The problem was in this specific line:

b, err := req.ToObject(c.vu.Runtime()).MarshalJSON()

This MarshalJSON implemented in Sobek uses a copy of JSON.stringify() under the hood, and per JSON RFC, neither Infinity or NaN as values are accepted as valid numbers.

However, since we rely on ProtoJSON, which does support special strings "Infinity" and "NaN", I guess that the idea would be to "normalize" them as a string format before marshaling, which is what this PR implements.

@ariasmn ariasmn force-pushed the fix/grpc-special-string-float branch from 2fa5e78 to fdd70b2 Compare March 15, 2025 11:46
@ariasmn
Copy link
Contributor Author
ariasmn commented Mar 15, 2025

Couple of things:

  • Having a hard time trying to understand how to build the tests (I'm guessing that it should be a test case in here). I just checked that current tests pass and added one for wrapped double value, but I guess I'd have to add another one for a normal float proto.
  • I still don't think that this approach is good enough... I feel like maybe the best bet would be to create the proto message using protoreflect and then marshaling normally, but I haven't tried if that would break wrappers and reflection implementations (and also is a bit long in terms of code, atleast the way I did it at my company).

@ariasmn ariasmn marked this pull request as ready for review March 20, 2025 15:26
@ariasmn ariasmn requested a review from a team as a code owner March 20, 2025 15:26
@ariasmn ariasmn requested review from mstoykov and joanlopez and removed request for a team March 20, 2025 15:26
@joanlopez joanlopez requested a review from oleiade March 20, 2025 15:50
Copy link
Contributor
@mstoykov mstoykov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR and sorry for the slow reply 🙇

I have left some comments around the code.

On the whole idea I am still not particularly certain this is ... what should be done, if anything.

Trying to figure out how this works in other cases I found protocolbuffers/protobuf-javascript#49 which seems to suggest that this isn't really supported. But maybe I am getting something wrong.

From the test it seems that this just works on the way back which seems awfully convient.

b, err := req.ToObject(c.vu.Runtime()).MarshalJSON()

object := req.ToObject(c.vu.Runtime())
normalized, err := normalizeNumberStrings(object, c.vu.Runtime())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you are effectively changing the input I would expect that you will first copy it as otherwiser this is breaking change and likely a very strange one, where after calling some grpc method suddently a bunch of your floats are strings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the object is built based on the req, which is a sobek.Value passed by value, so we shouldn't worry about it, no? Or am I misunderstanding you? (Probably this, my brain is fried today, sorry 😞 )

@ariasmn
Copy link
Contributor Author
ariasmn commented Apr 11, 2025

Hey @mstoykov, thanks a lot for the review!

I’ve made some changes based on your comments. There’s one part I didn't change yet because I’m not fully sure I understand it correctly, but we can keep discussing it in the open conversation.

Regarding the issue you mentioned: it looks like an older open issue. From what I saw, the code has since changed and now properly asserts both Infinity and NaN:

https://github.com/protocolbuffers/protobuf-javascript/blob/0768cc9f18bec192c393d7c2962ee8ab5ad1931b/binary/encoder.js#L411-L418

I also tested it locally using the dummy.proto from the issue, for both client and server (wire format). Additionally, the ProtoJSON documentation confirms that both values are officially supported.

Just a heads-up: I might be a bit slower next week if any further changes are needed — apologies in advance.

Thanks again for the great feedback. 🙏

EDIT: Tests are failing, don't know if related to my changes but the client_test.go tests are passing correctly locally 🤔

@ariasmn ariasmn requested a review from mstoykov May 2, 2025 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0