Skip to content
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

cJSON can't handle an integer value with more than 53 bits of precision #14

Closed
jasonzio opened this issue Jun 21, 2016 · 6 comments
Closed
Labels

Comments

@jasonzio
Copy link

JSON syntax allows me to specify an integer that requires more than 53 bits of precision to correctly represent. cJSON can't store that in cJSON.valueint (which is only an int, which is 32 bits on most platforms), but storing it in a double will lose information (IEEE double-precision float only has 53 bits of mantissa).

Is there a reason why valueint couldn't be made a long long? Nearly all modern platforms treat that as int64_t. (I have a local fork with this change, which I've been using for quite some time; I'd be happy to submit a PR if you think this is a good idea.)

@DaveGamble
Copy link
Owner

DaveGamble commented Jun 21, 2016

You're quite right, of course. The reason this isn't a trivial change is support of "non-modern" platforms; specifically embedded systems, for which cJSON seems to have a lot of users. Also, I should bring to your attention that the JSON spec says precious little on precision and range of "numbers"; cJSON includes ints just as a convenience, and doubles as a compromise for a good-faith attempt to support the magical strings of numbers that JSON requires.

Feel free to submit a patch, but I'm a little concerned about how we manage the split between processors and potatoes. A #define would certainly get it, but I think the default state should be with 32bit ints. A proper solution will be to uncouple the double/int assignments all through, typedef cJSON_int somewhere, wire that through, then have a #ifndef cJSON_int_width / typedef cJSON_int int; #endif and allow a #ifdef cJSON_use_long_long_int #define cJSON_int_width / typedef cJSON_int long long. That also needs some hacking for the printf format specifier... and now you can see why I haven't just hacked this in already ;)

Actually, it would probably be fine just to allow one flag to extend the int range. No-one has requested lengths other than 32 and 64bit.

@jasonzio
Copy link
Author

This is the kind of thing that makes me wish C supported templates.

The #define/#ifdef approach is what I had in mind. Probably CJSON_USE_INT64; if defined, that would change valueint to "long long" and make the other necessary changes to accommodate it (e.g. the printf change). Keep it really simple to address this one issue.

I'd like to figure out a clean way of detecting a mismatch between the caller and the compiled cJSON.o file. One could live without it, but inevitably someone will make that mistake during development and the results will be ugly.

If C supported infinite-precision integers as part of the language, I'd worry more about making cJSON support them. But it doesn't, so "int" vs "long long" should suffice.

@DaveGamble
Copy link
Owner

How about, as a dangerous idea, we bet that /few/ people will be using sizeof(cJSON) outside the library, since it's an n-tree anyway.

On the basis of that bet, we can add a long long llvalue; to the end of the struct. That can then be #ifdef-ed in, and we can add a few lines to the library to fill it, along with some macros. With the exception of cJSON_SetIntValue/SetNumberValue, we could expose full API.

This means we can have different users/libraries with different versions of cJSON sharing the same objects without breaking. And gloriously the free chain will ensure that deletion works right too even across users.

This suggestion is hugely ugly though. And inefficient. I'm much more inclined to typedef a cJSON_int as either int or long long (and fix the format specifier using sizeof), and let people trying to link two different versions of cJSON across libraries be grownups and solve the problem themselves.

Thoughts?

@pierrg7
Copy link

pierrg7 commented Sep 29, 2016

What I suggest is to make integers available as a string value in addition to the default int value. If the developer using cJSON thinks there might be integer overflows, he could simply parse the string value outside cJSON.

@FSMaxB
Copy link
Collaborator

FSMaxB commented Sep 30, 2016

@pierrg7 That takes a lot of space in memory.

@FSMaxB
Copy link
Collaborator

FSMaxB commented Nov 4, 2016

I'll close this, because it is not in the scope of the library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants