zserge / jsmn

Jsmn is a world fastest JSON parser/tokenizer. This is the official repo replacing the old one at Bitbucket
MIT License
3.64k stars 778 forks source link

Undefined behaviour / program freeze while accessing first token #191

Closed V10lator closed 4 years ago

V10lator commented 4 years ago

This is my code:

#define JSMN_STATIC
#include "jsmn/jsmn.h"

-- SNIP --

        debugPrintf("First 3 characters of RAM file: %c%c%c", ramFile[0], ramFile[1], ramFile[3]);
        debugPrintf("Last 3 characters of RAM file: %c%c%c", ramFile[ramIndex - 2], ramFile[ramIndex - 1], ramFile[ramIndex]);
        debugPrintf("Parsing keys.json...");

        jsmn_parser parser;
        jsmn_init(&parser);
        debugPrintf("Parser initialized!");
        int tn = jsmn_parse(&parser, ramFile, ramIndex, NULL, 0);
        //TODO: Error checking
        debugPrintf("Found %d JSON tokens", tn);
        jsmntok_t tokens[tn];
        jsmn_init(&parser);
        debugPrintf("Parser reinitialized!");
        if(jsmn_parse(&parser, ramFile, ramIndex, tokens, tn) != tn)
        {
            debugPrintf("Parsing error 1");
            //TODO
        }
        else
            debugPrintf("Parser reinitialized!");

        if(tokens[0].type != JSMN_ARRAY)
        {
            debugPrintf("Parsing error 2: %d", tokens[0].type);
            //TODO
        }
        else
            debugPrintf("JSON Array found!");

And this is the result of the debugging prints:

First 3 characters of RAM file: [{t
Last 3 characters of RAM file: "}]
Parsing keys.json...
Parser initialized!
Found 39832 JSON tokens
Parser reinitialized!

So it freezes at the line if(tokens[0].type != JSMN_ARRAY) which should have been initialized by JSMN.

Please note that this is on an architecture which does not guarantee any memory to be zero allocated.

//EDIT: Was too fast. New code:

        debugPrintf("First 5 characters of RAM file: %c%c%c%c%c", ramFile[0], ramFile[1], ramFile[2], ramFile[3], ramFile[4]);
        debugPrintf("Last 5 characters of RAM file: %c%c%c%c%c", ramFile[ramIndex - 4], ramFile[ramIndex - 3], ramFile[ramIndex - 2], ramFile[ramIndex - 1], ramFile[ramIndex]);
        debugPrintf("Parsing keys.json...");

        jsmn_parser parser;
        jsmn_init(&parser);
        debugPrintf("Parser initialized!");
        int tn = jsmn_parse(&parser, ramFile, ramIndex, NULL, 0);
        //TODO: Error checking
        debugPrintf("Found %d JSON tokens", tn);
        jsmntok_t tokens[tn];
        jsmn_init(&parser);
        debugPrintf("Parser reinitialized!");
        if(jsmn_parse(&parser, ramFile, ramIndex, tokens, tn) != tn)
        {
            debugPrintf("Parsing error 1");
            //TODO
        }
        else
            debugPrintf("Tokens initialized!");

        debugPrintf("Examining tokens[0]:");
        debugPrintf("\ttype = %#010x", tokens[0].type);
        debugPrintf("\tstart = %#010x", tokens[0].start);
        debugPrintf("\tend = %#010x", tokens[0].end);
        debugPrintf("\tsize = %#010x", tokens[0].size);

Debugging output:

First 5 characters of RAM file: [{"ti
Last 5 characters of RAM file: 00"}]
Parsing keys.json...
Parser initialized!
Found 39832 JSON tokens
Spoofing tokens[0]...
Parser reinitialized!

So it's freezing at if(jsmn_parse(&parser, ramFile, ramIndex, tokens, tn) != tn).

Please note that the ramFile string is not terminated by a '\0' char. Could this cause the issue?

//EDIT²: Yes, fixed by adding \0 to the end. Not sure if you want to fix this (we pass the size of the JSON string to JSMN, so why doesn't it use that info?),

pt300 commented 4 years ago

First thing, can you revert any changes and test with #define JSMN_STRICT ? The non-strict mode, sadly the default for now, doesn't really work well and is planned to be removed. Have a feeling it might be causing the problems.

V10lator commented 4 years ago

I tried as you suggested but the error is still the same. If you need to know what data I'm trying to parse, it's this: http://cldr.xyz/json

pt300 commented 4 years ago

I have tested your case with my eyes and valgrind and seems like the problem might be at some other point in your code as it doesn't seem to be in here. You should look around for possible memory corruption before this piece of code.

pt300 commented 4 years ago

I will close this issue for now but feel free to reopen if you believe the problem is definitely with JSMN.

V10lator commented 4 years ago

That JSON parsing is almost the first thing happening in the app. It only initializes a few things, reads a json config file, downloads the json file from the link above to ram and parses it. Also porting to another json library fixed the problem for me, so I'm really not sure what happened here.

Anyway, thanks for your support. I'll check JSMN out again at a later point in time (maybe I'm really overlooking some corruption but I searched for it the whole day before making this report... But I also need to inform myself how to use i.e. Valgrind on the platform I'm developing for).