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

Can't throw exception when starting file is a number #1649

Closed
h3x4n1um opened this issue Jun 23, 2019 · 4 comments
Closed

Can't throw exception when starting file is a number #1649

h3x4n1um opened this issue Jun 23, 2019 · 4 comments
Labels
kind: bug solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@h3x4n1um
Copy link

h3x4n1um commented Jun 23, 2019

  • What is the issue you have?

When parsing binary file, if several first bytes of file is number, the json parser not throw an exception

  • Please describe the steps to reproduce the issue. Can you provide a small but working code example?

The below example show that it recognize fake_undetected.json file is a json file

#include <filesystem>
#include <fstream>
#include <iomanip>
#include <iostream>

#include "json.hpp"

int main(){
    std::ifstream input;
    std::ofstream output;
    nlohmann::json js;
    int test = 2019;

    //create real json
    output.open("real.json");
    js["Hello"] = "Hi";
    js["Year"] = test;
    output << std::setw(4) << js;
    output.close();

    //create detected fake json file
    output.open("fake_detected.json", std::ofstream::binary);
    output.write(reinterpret_cast <const char*> (&test), sizeof test);
    output.close();

    //create undetected fake json file
    output.open("fake_undetected.json", std::ofstream::binary);
    output << test;
    output.write(reinterpret_cast <const char*> (&test), sizeof test);
    output.close();

    //verify json
    std::filesystem::path p = std::filesystem::current_path();
    for (auto &file : std::filesystem::recursive_directory_iterator(p)){
        if (std::filesystem::is_regular_file(file.path())){
            input.open(file.path());
            try{
                input >> js;
                std::cout << file.path() << " is a json" << std::endl;
            }
            catch(nlohmann::json::exception &e){
                std::cerr << file.path() << " is not a json" << std::endl;
            }
            input.close();
        }
    }
    return 0;
}
  • What is the expected behavior?

It should throw nlohmann::json::exception when parse fake_undetected.json

  • And what is the actual behavior instead?

Opposite above

I use GCC 9.0 (MSYS2 with MinGW-w64 package) and compile using

g++ -lstdc++fs -std=c++17 -c test.cpp -o test.o
  • Did you use a released version of the library or the version from the develop branch?

I use released version 3.6.1 of the library

Hello, world!

@nlohmann
Copy link
Owner

The issue is that parsing via input >> json is not required to read the stream until the last character: if the prefix is a JSON value, it is returned and the stream is left at the first character after the parsed value. This allows for incremental parsing from a stream.

For your case, try using the static function json::parse. It takes the input as parameter and will throw if the input is not completely read.

Here is an example:

#include "json.hpp"
#include <iostream>
#include <sstream>

using json = nlohmann::json;

int main()
{
    // works and prints "123"
    {
        std::stringstream ss;
        ss << "123ab" << std::endl;
        
        json j;
        ss >> j;
        
        std::cout << j << std::endl;
    }
    
    // throws [json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: '123a'; expected end of input
    {
        std::stringstream ss;
        ss << "123ab" << std::endl;

        json j = json::parse(ss);
    }
}

@nlohmann nlohmann added the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label Jun 24, 2019
@nlohmann
Copy link
Owner

@h3x4n1um Do you need further assistance?

@h3x4n1um
Copy link
Author

@h3x4n1um Do you need further assistance?

Thankyou, that's very kind of you but I think using json::parse as a workaround is fine for me until the problem is fixed

@nlohmann
Copy link
Owner

For operator>> I cannot pass a parameter to control whether trailing characters should be treated like an error. For parse I could add another parameter, but this is not yet planned. So at least for the near future, there will be no fix for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: bug solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

2 participants