mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
prevent stack overflow when parsing huge json array
Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
parent
2cc649c97e
commit
c8588c323c
2 changed files with 48 additions and 4 deletions
|
|
@ -83,6 +83,30 @@ struct JSONStringStream {
|
|||
const Ch* tail_;
|
||||
};
|
||||
|
||||
template <typename JSONCharType>
|
||||
class JSONDocument : public rapidjson::GenericDocument<JSONCharType> {
|
||||
public:
|
||||
JSONDocument(ExecutionState& state)
|
||||
: m_state(state)
|
||||
{
|
||||
}
|
||||
|
||||
bool StartObject()
|
||||
{
|
||||
CHECK_STACK_OVERFLOW(m_state);
|
||||
return rapidjson::GenericDocument<JSONCharType>::StartObject();
|
||||
}
|
||||
|
||||
bool StartArray()
|
||||
{
|
||||
CHECK_STACK_OVERFLOW(m_state);
|
||||
return rapidjson::GenericDocument<JSONCharType>::StartArray();
|
||||
}
|
||||
|
||||
private:
|
||||
ExecutionState& m_state;
|
||||
};
|
||||
|
||||
template <typename CharType, typename JSONCharType>
|
||||
static Value parseJSONWorker(ExecutionState& state, const rapidjson::GenericValue<JSONCharType>& value)
|
||||
{
|
||||
|
|
@ -156,12 +180,12 @@ static Value parseJSONWorker(ExecutionState& state, const rapidjson::GenericValu
|
|||
}
|
||||
|
||||
template <typename CharType, typename JSONCharType>
|
||||
static Value parseJSON(ExecutionState& state, const CharType* data, size_t length, rapidjson::GenericDocument<JSONCharType>& jsonDocument)
|
||||
static Value parseJSON(ExecutionState& state, const CharType* data, size_t length, JSONDocument<JSONCharType>& jsonDocument)
|
||||
{
|
||||
auto strings = &state.context()->staticStrings();
|
||||
|
||||
JSONStringStream<JSONCharType> stringStream(data, length);
|
||||
jsonDocument.ParseStream(stringStream);
|
||||
jsonDocument.template ParseStream<rapidjson::kParseDefaultFlags, JSONCharType, JSONStringStream<JSONCharType>, JSONDocument<JSONCharType>>(stringStream);
|
||||
if (jsonDocument.HasParseError()) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::SyntaxError, strings->JSON.string(), true, strings->parse.string(), rapidjson::GetParseError_En(jsonDocument.GetParseError()));
|
||||
}
|
||||
|
|
@ -197,7 +221,7 @@ Value JSON::parse(ExecutionState& state, Value text, Value reviver)
|
|||
|
||||
// 1, 2, 3
|
||||
String* JText = text.toString(state);
|
||||
rapidjson::GenericDocument<rapidjson::UTF16<char16_t>> parseResult;
|
||||
JSONDocument<rapidjson::UTF16<char16_t>> parseResult(state);
|
||||
Value unfiltered;
|
||||
if (JText->has8BitContent()) {
|
||||
size_t len = JText->length();
|
||||
|
|
|
|||
|
|
@ -2063,6 +2063,26 @@ public:
|
|||
|
||||
//!@name Parse from stream
|
||||
//!@{
|
||||
//! Parse JSON text from an input stream (with Encoding conversion)
|
||||
/*! \tparam parseFlags Combination of \ref ParseFlag.
|
||||
\tparam SourceEncoding Encoding of input stream
|
||||
\tparam InputStream Type of input stream, implementing Stream concept
|
||||
\param is Input stream to be parsed.
|
||||
\return The document itself for fluent API.
|
||||
*/
|
||||
template <unsigned parseFlags, typename SourceEncoding, typename InputStream, typename Handler>
|
||||
GenericDocument& ParseStream(InputStream& is)
|
||||
{
|
||||
ValueType::SetNull(); // Remove existing root if exist
|
||||
GenericReader<SourceEncoding, Encoding, StackAllocator> reader(&stack_.GetAllocator());
|
||||
ClearStackOnExit scope(*this);
|
||||
parseResult_ = reader.template Parse<parseFlags>(is, (Handler&)*this);
|
||||
if (parseResult_) {
|
||||
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
|
||||
this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13.
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Parse JSON text from an input stream (with Encoding conversion)
|
||||
/*! \tparam parseFlags Combination of \ref ParseFlag.
|
||||
|
|
@ -2189,7 +2209,7 @@ public:
|
|||
//! Get the capacity of stack in bytes.
|
||||
size_t GetStackCapacity() const { return stack_.GetCapacity(); }
|
||||
|
||||
private:
|
||||
protected:
|
||||
// clear stack on any exit from ParseStream, e.g. due to exception
|
||||
struct ClearStackOnExit {
|
||||
explicit ClearStackOnExit(GenericDocument& d)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue