#3309: optimize parsing from stream (no copying of entire JSON to memory); limit maximum depth to avoid stack overflow with malicious documents (fuzzing - #3285); code cleanup

This commit is contained in:
Günter Obiltschnig
2021-06-15 18:55:59 +02:00
parent 6d7fafd6f1
commit c4c2df26b3
7 changed files with 142 additions and 82 deletions

View File

@@ -65,7 +65,7 @@ class JSON_API Parser: private ParserImpl
{
public:
Parser(const Handler::Ptr& pHandler = new ParseHandler, std::size_t bufSize = JSON_PARSE_BUFFER_SIZE);
Parser(const Handler::Ptr& pHandler = new ParseHandler);
/// Creates JSON Parser, using the given Handler and buffer size.
virtual ~Parser();
@@ -76,6 +76,10 @@ public:
void setAllowComments(bool comments);
/// Allow or disallow comments. By default, comments are not allowed.
///
/// If set to true, comments will be filtered out of the input data
/// before passing the JSON on to the parser. This will impact performance,
/// especially when reading from a std::istream.
bool getAllowComments() const;
/// Returns true if comments are allowed, false otherwise.
@@ -85,7 +89,11 @@ public:
void setAllowNullByte(bool nullByte);
/// Allow or disallow null byte in strings.
///
/// By default, null byte is allowed.
/// By default, null byte is allowed (true).
///
/// If set to false, an additional check for "\u0000" will be performed
/// before passing the JSON on to the parser. This will impact performance,
/// especially when reading from a std::istream.
bool getAllowNullByte() const;
/// Returns true if null byte is allowed, false otherwise.
@@ -94,6 +102,10 @@ public:
void setDepth(std::size_t depth);
/// Sets the allowed JSON depth.
///
/// Default maximum depth is 128. Setting this value too high
/// may result in a stack overflow when parsing a (malicious)
/// JSON document.
std::size_t getDepth() const;
/// Returns the allowed JSON depth.

View File

@@ -38,11 +38,9 @@ namespace JSON {
class JSON_API ParserImpl
{
protected:
static const std::size_t JSON_PARSE_BUFFER_SIZE = 4096;
static const std::size_t JSON_PARSER_STACK_SIZE = 128;
static const int JSON_UNLIMITED_DEPTH = -1;
static const std::size_t JSON_DEFAULT_DEPTH = 128;
ParserImpl(const Handler::Ptr& pHandler = new ParseHandler, std::size_t bufSize = JSON_PARSE_BUFFER_SIZE);
ParserImpl(const Handler::Ptr& pHandler = new ParseHandler);
/// Creates JSON ParserImpl, using the given Handler and buffer size.
virtual ~ParserImpl();
@@ -101,12 +99,13 @@ private:
void handleObject();
void handle();
void handle(const std::string& json);
void handle(std::istream& json);
void stripComments(std::string& json);
bool checkError();
struct json_stream* _pJSON;
Handler::Ptr _pHandler;
int _depth;
std::size_t _depth;
char _decimalPoint;
bool _allowNullByte;
bool _allowComments;