Skip to content

Issues parsing a previously encoded binary (non-UTF8) string. #1211

Description

@sfinktah

This is a bit of an edge case, but it seems to be handled in other platforms (to varying degrees).

The simplest explanation I can give you is just to show you this code:

#include <string>
#include "json.hpp"
using json = nlohmann::json;

int main(int argc, const char **argv) {
    std::string encoded("\u0006\u00e4\u00b4\u00d8\u008d\"");
    auto j3 = json::parse(encoded);
}

Which produced this exception:

JSON Exception: [json.exception.parse_error.101] parse error at 1: syntax error - invalid literal; last read: '<U+0006>'test complete.

Note: the same error occurs when nlohmann has done the previous encoding of the string (as shown below).

Whilst I fully understand the reason for the error, I don't believe that it is valid to assume all strings will be valid UTF-8, merely because the JSON spec includes \u0000 unicode escape sequences. I might be wrong, I haven't read the RFC lately.

Ignore everything below this line, as it's just more details. :)

Expanded tests

int main(int argc, const char **argv) {
    // binary string, not valid utf-8
    std::string ugly("\x06\xe4\xb4\xd8\x8d\x22");

    // will encode okay
    json j = {{ "text", ugly.c_str() }};
    printf("encoding complete.\n");                fflush(stdout);
    
    // 2.1.1 can dump okay
    // dumping: {"text":"\u0006▒؍\""}
    
    // 3.2.0 will trigger exception when dumping
    printf("dumping: %s\n", j.dump().c_str());     fflush(stdout);

    // both will trigger exception when parsing
    auto j2 = json::parse(j.dump());

    printf("test complete.\n");                    fflush(stdout);

Some tests with other platforms showed that php will not encode a raw non-UTF8 binary string, JavaScript (v8) had no issues, and python actually produced the "every character escaped" version I used in the initial example.

    // JavaScript tests (performed in Chrome console window)
    // helper functions from: https://nt4.com/js/hexdump.js
    
    /*
     * > j = JSON.stringify(sprintf("\x06\xe4\xb4\xd8\x8d\x22"))
     * < ""\u0006䴨�\"""
     * 
     * > hexdump(j)
     * < 0000000: 22 5c 75 30 30 30 36 e4 b4 d8 8d 5c 22 22          "\u0006....\""
     * 
     * > JSON.parse(j)
     * < "�䴨�""
     * 
     * > hexdump(JSON.parse(j))
     * < 0000000: 06 e4 b4 d8 8d 22                                  ....."
     */

PHP test:

    // PHP test (performed from bash shell, with the aid of a private helper)
    // (encode fails, but decode succeeds)

    /*
     * root@ec js $ echo -ne "\x06\xe4\xb4\xd8\x8d\x22" | phpparse - json_encode
     * false
     * 
     * root@ec js $ echo -n '"\u0006䴨�\""' | phpparse - json_decode
     * 䴨�"
     */
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    solution: proposed fixa fix for the issue has been proposed and waits for confirmationstate: stalethe issue has not been updated in a while and will be closed automatically soon unless it is updated

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions