vivkin / gason

Lightweight and fast JSON parser for C++
MIT License
338 stars 51 forks source link

gason does not work on platforms with tagged pointers (e.g. Android) #36

Open jyaif opened 3 years ago

jyaif commented 3 years ago

Android is starting to use tagged pointers (https://source.android.com/devices/tech/debug/tagged-pointers)

This code breaks with tagged pointers: https://github.com/vivkin/gason/blob/7aee524189da1c1ecd19f67981e3d903dae25470/src/gason.h#L33

A real life example that occurred on a Pixel 5 is of a JsonValue created with the tag 2, and with the payload 0xb400007a779ebdc0. Calling getTag() on that value returns 0, but it should have returned 2.

jyaif commented 3 years ago

AFAICT, turning JsonValue into this struct fixes this problem:

struct JsonValue {
    union {
      uint64_t ival_ = 0;
      double fval_;
    };
    uint8_t tag_ = JSON_NULL;

    JsonValue(double x) : fval_(x), tag_(JSON_NUMBER) {
    }
    JsonValue(JsonTag tag = JSON_NULL, void *payload = nullptr)
        : ival_((uintptr_t)payload), tag_(tag) {
    }
    bool isDouble() const {
        return tag_ == JSON_NUMBER;
    }
    JsonTag getTag() const {
        return (JsonTag)tag_;
    }
    uint64_t getPayload() const {
        assert(!isDouble());
        return ival_;
    }
    double toNumber() const {
        assert(getTag() == JSON_NUMBER);
        return fval_;
    }
    char *toString() const {
        assert(getTag() == JSON_STRING);
        return (char *)getPayload();
    }
    JsonNode *toNode() const {
        assert(getTag() == JSON_ARRAY || getTag() == JSON_OBJECT);
        return (JsonNode *)getPayload();
    }
};
jyaif commented 3 years ago

To the people hitting this issue: The proposed fix is under the same license as the library, so feel free to use it to patch things up.