MAINT-2338 Implemented binary parser depth control
parent
25e19c0e6f
commit
64b9b4c771
|
|
@ -51,6 +51,7 @@
|
|||
|
||||
// File constants
|
||||
static const int MAX_HDR_LEN = 20;
|
||||
static const S32 UNZIP_LLSD_MAX_DEPTH = 96;
|
||||
static const char LEGACY_NON_HEADER[] = "<llsd>";
|
||||
const std::string LLSD_BINARY_HEADER("LLSD/Binary");
|
||||
const std::string LLSD_XML_HEADER("LLSD/XML");
|
||||
|
|
@ -317,11 +318,11 @@ LLSDParser::LLSDParser()
|
|||
LLSDParser::~LLSDParser()
|
||||
{ }
|
||||
|
||||
S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes)
|
||||
S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes, S32 max_depth)
|
||||
{
|
||||
mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true;
|
||||
mMaxBytesLeft = max_bytes;
|
||||
return doParse(istr, data);
|
||||
return doParse(istr, data, max_depth);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -403,7 +404,7 @@ LLSDNotationParser::~LLSDNotationParser()
|
|||
{ }
|
||||
|
||||
// virtual
|
||||
S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
|
||||
S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const
|
||||
{
|
||||
// map: { string:object, string:object }
|
||||
// array: [ object, object, object ]
|
||||
|
|
@ -418,6 +419,10 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
|
|||
// binary: b##"ff3120ab1" | b(size)"raw data"
|
||||
char c;
|
||||
c = istr.peek();
|
||||
if (max_depth == 0)
|
||||
{
|
||||
return PARSE_FAILURE;
|
||||
}
|
||||
while(isspace(c))
|
||||
{
|
||||
// pop the whitespace.
|
||||
|
|
@ -434,7 +439,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
|
|||
{
|
||||
case '{':
|
||||
{
|
||||
S32 child_count = parseMap(istr, data);
|
||||
S32 child_count = parseMap(istr, data, max_depth - 1);
|
||||
if((child_count == PARSE_FAILURE) || data.isUndefined())
|
||||
{
|
||||
parse_count = PARSE_FAILURE;
|
||||
|
|
@ -453,7 +458,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
|
|||
|
||||
case '[':
|
||||
{
|
||||
S32 child_count = parseArray(istr, data);
|
||||
S32 child_count = parseArray(istr, data, max_depth - 1);
|
||||
if((child_count == PARSE_FAILURE) || data.isUndefined())
|
||||
{
|
||||
parse_count = PARSE_FAILURE;
|
||||
|
|
@ -658,7 +663,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
|
|||
return parse_count;
|
||||
}
|
||||
|
||||
S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const
|
||||
S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) const
|
||||
{
|
||||
// map: { string:object, string:object }
|
||||
map = LLSD::emptyMap();
|
||||
|
|
@ -693,7 +698,7 @@ S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const
|
|||
}
|
||||
putback(istr, c);
|
||||
LLSD child;
|
||||
S32 count = doParse(istr, child);
|
||||
S32 count = doParse(istr, child, max_depth);
|
||||
if(count > 0)
|
||||
{
|
||||
// There must be a value for every key, thus
|
||||
|
|
@ -718,7 +723,7 @@ S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const
|
|||
return parse_count;
|
||||
}
|
||||
|
||||
S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const
|
||||
S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const
|
||||
{
|
||||
// array: [ object, object, object ]
|
||||
array = LLSD::emptyArray();
|
||||
|
|
@ -737,7 +742,7 @@ S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const
|
|||
continue;
|
||||
}
|
||||
putback(istr, c);
|
||||
S32 count = doParse(istr, child);
|
||||
S32 count = doParse(istr, child, max_depth);
|
||||
if(PARSE_FAILURE == count)
|
||||
{
|
||||
return PARSE_FAILURE;
|
||||
|
|
@ -869,7 +874,7 @@ LLSDBinaryParser::~LLSDBinaryParser()
|
|||
}
|
||||
|
||||
// virtual
|
||||
S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
|
||||
S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const
|
||||
{
|
||||
/**
|
||||
* Undefined: '!'<br>
|
||||
|
|
@ -893,12 +898,16 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
if (max_depth == 0)
|
||||
{
|
||||
return PARSE_FAILURE;
|
||||
}
|
||||
S32 parse_count = 1;
|
||||
switch(c)
|
||||
{
|
||||
case '{':
|
||||
{
|
||||
S32 child_count = parseMap(istr, data);
|
||||
S32 child_count = parseMap(istr, data, max_depth - 1);
|
||||
if((child_count == PARSE_FAILURE) || data.isUndefined())
|
||||
{
|
||||
parse_count = PARSE_FAILURE;
|
||||
|
|
@ -917,7 +926,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
|
|||
|
||||
case '[':
|
||||
{
|
||||
S32 child_count = parseArray(istr, data);
|
||||
S32 child_count = parseArray(istr, data, max_depth - 1);
|
||||
if((child_count == PARSE_FAILURE) || data.isUndefined())
|
||||
{
|
||||
parse_count = PARSE_FAILURE;
|
||||
|
|
@ -1098,7 +1107,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
|
|||
return parse_count;
|
||||
}
|
||||
|
||||
S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const
|
||||
S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) const
|
||||
{
|
||||
map = LLSD::emptyMap();
|
||||
U32 value_nbo = 0;
|
||||
|
|
@ -1128,7 +1137,7 @@ S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const
|
|||
}
|
||||
}
|
||||
LLSD child;
|
||||
S32 child_count = doParse(istr, child);
|
||||
S32 child_count = doParse(istr, child, max_depth);
|
||||
if(child_count > 0)
|
||||
{
|
||||
// There must be a value for every key, thus child_count
|
||||
|
|
@ -1152,7 +1161,7 @@ S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const
|
|||
return parse_count;
|
||||
}
|
||||
|
||||
S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
|
||||
S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const
|
||||
{
|
||||
array = LLSD::emptyArray();
|
||||
U32 value_nbo = 0;
|
||||
|
|
@ -1168,7 +1177,7 @@ S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
|
|||
while((c != ']') && (count < size) && istr.good())
|
||||
{
|
||||
LLSD child;
|
||||
S32 child_count = doParse(istr, child);
|
||||
S32 child_count = doParse(istr, child, max_depth);
|
||||
if(PARSE_FAILURE == child_count)
|
||||
{
|
||||
return PARSE_FAILURE;
|
||||
|
|
@ -2238,7 +2247,7 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,
|
|||
return ZR_MEM_ERROR;
|
||||
}
|
||||
|
||||
if (!LLSDSerialize::fromBinary(data, istr, cur_size))
|
||||
if (!LLSDSerialize::fromBinary(data, istr, cur_size, UNZIP_LLSD_MAX_DEPTH))
|
||||
{
|
||||
free(result);
|
||||
return ZR_PARSE_ERROR;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public:
|
|||
* @return Returns the number of LLSD objects parsed into
|
||||
* data. Returns PARSE_FAILURE (-1) on parse failure.
|
||||
*/
|
||||
S32 parse(std::istream& istr, LLSD& data, S32 max_bytes);
|
||||
S32 parse(std::istream& istr, LLSD& data, S32 max_bytes, S32 max_depth = -1);
|
||||
|
||||
/** Like parse(), but uses a different call (istream.getline()) to read by lines
|
||||
* This API is better suited for XML, where the parse cannot tell
|
||||
|
|
@ -103,10 +103,12 @@ protected:
|
|||
* caller.
|
||||
* @param istr The input stream.
|
||||
* @param data[out] The newly parse structured data.
|
||||
* @param max_depth Max depth parser will check before exiting
|
||||
* with parse error, -1 - unlimited.
|
||||
* @return Returns the number of LLSD objects parsed into
|
||||
* data. Returns PARSE_FAILURE (-1) on parse failure.
|
||||
*/
|
||||
virtual S32 doParse(std::istream& istr, LLSD& data) const = 0;
|
||||
virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Virtual default function for resetting the parser
|
||||
|
|
@ -241,10 +243,12 @@ protected:
|
|||
* caller.
|
||||
* @param istr The input stream.
|
||||
* @param data[out] The newly parse structured data. Undefined on failure.
|
||||
* @param max_depth Max depth parser will check before exiting
|
||||
* with parse error, -1 - unlimited.
|
||||
* @return Returns the number of LLSD objects parsed into
|
||||
* data. Returns PARSE_FAILURE (-1) on parse failure.
|
||||
*/
|
||||
virtual S32 doParse(std::istream& istr, LLSD& data) const;
|
||||
virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
@ -252,18 +256,20 @@ private:
|
|||
*
|
||||
* @param istr The input stream.
|
||||
* @param map The map to add the parsed data.
|
||||
* @param max_depth Allowed parsing depth.
|
||||
* @return Returns The number of LLSD objects parsed into data.
|
||||
*/
|
||||
S32 parseMap(std::istream& istr, LLSD& map) const;
|
||||
S32 parseMap(std::istream& istr, LLSD& map, S32 max_depth) const;
|
||||
|
||||
/**
|
||||
* @brief Parse an array from the istream.
|
||||
*
|
||||
* @param istr The input stream.
|
||||
* @param array The array to append the parsed data.
|
||||
* @param max_depth Allowed parsing depth.
|
||||
* @return Returns The number of LLSD objects parsed into data.
|
||||
*/
|
||||
S32 parseArray(std::istream& istr, LLSD& array) const;
|
||||
S32 parseArray(std::istream& istr, LLSD& array, S32 max_depth) const;
|
||||
|
||||
/**
|
||||
* @brief Parse a string from the istream and assign it to data.
|
||||
|
|
@ -314,10 +320,12 @@ protected:
|
|||
* caller.
|
||||
* @param istr The input stream.
|
||||
* @param data[out] The newly parse structured data.
|
||||
* @param max_depth Max depth parser will check before exiting
|
||||
* with parse error, -1 - unlimited.
|
||||
* @return Returns the number of LLSD objects parsed into
|
||||
* data. Returns PARSE_FAILURE (-1) on parse failure.
|
||||
*/
|
||||
virtual S32 doParse(std::istream& istr, LLSD& data) const;
|
||||
virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const;
|
||||
|
||||
/**
|
||||
* @brief Virtual default function for resetting the parser
|
||||
|
|
@ -362,10 +370,12 @@ protected:
|
|||
* caller.
|
||||
* @param istr The input stream.
|
||||
* @param data[out] The newly parse structured data.
|
||||
* @param max_depth Max depth parser will check before exiting
|
||||
* with parse error, -1 - unlimited.
|
||||
* @return Returns the number of LLSD objects parsed into
|
||||
* data. Returns -1 on parse failure.
|
||||
*/
|
||||
virtual S32 doParse(std::istream& istr, LLSD& data) const;
|
||||
virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
@ -373,18 +383,20 @@ private:
|
|||
*
|
||||
* @param istr The input stream.
|
||||
* @param map The map to add the parsed data.
|
||||
* @param max_depth Allowed parsing depth.
|
||||
* @return Returns The number of LLSD objects parsed into data.
|
||||
*/
|
||||
S32 parseMap(std::istream& istr, LLSD& map) const;
|
||||
S32 parseMap(std::istream& istr, LLSD& map, S32 max_depth) const;
|
||||
|
||||
/**
|
||||
* @brief Parse an array from the istream.
|
||||
*
|
||||
* @param istr The input stream.
|
||||
* @param array The array to append the parsed data.
|
||||
* @param max_depth Allowed parsing depth.
|
||||
* @return Returns The number of LLSD objects parsed into data.
|
||||
*/
|
||||
S32 parseArray(std::istream& istr, LLSD& array) const;
|
||||
S32 parseArray(std::istream& istr, LLSD& array, S32 max_depth) const;
|
||||
|
||||
/**
|
||||
* @brief Parse a string from the istream and assign it to data.
|
||||
|
|
@ -800,16 +812,16 @@ public:
|
|||
LLPointer<LLSDBinaryFormatter> f = new LLSDBinaryFormatter;
|
||||
return f->format(sd, str, LLSDFormatter::OPTIONS_NONE);
|
||||
}
|
||||
static S32 fromBinary(LLSD& sd, std::istream& str, S32 max_bytes)
|
||||
static S32 fromBinary(LLSD& sd, std::istream& str, S32 max_bytes, S32 max_depth = -1)
|
||||
{
|
||||
LLPointer<LLSDBinaryParser> p = new LLSDBinaryParser;
|
||||
return p->parse(str, sd, max_bytes);
|
||||
return p->parse(str, sd, max_bytes, max_depth);
|
||||
}
|
||||
static LLSD fromBinary(std::istream& str, S32 max_bytes)
|
||||
static LLSD fromBinary(std::istream& str, S32 max_bytes, S32 max_depth = -1)
|
||||
{
|
||||
LLPointer<LLSDBinaryParser> p = new LLSDBinaryParser;
|
||||
LLSD sd;
|
||||
(void)p->parse(str, sd, max_bytes);
|
||||
(void)p->parse(str, sd, max_bytes, max_depth);
|
||||
return sd;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -917,7 +917,7 @@ void LLSDXMLParser::parsePart(const char *buf, int len)
|
|||
}
|
||||
|
||||
// virtual
|
||||
S32 LLSDXMLParser::doParse(std::istream& input, LLSD& data) const
|
||||
S32 LLSDXMLParser::doParse(std::istream& input, LLSD& data, S32 max_depth) const
|
||||
{
|
||||
#ifdef XML_PARSER_PERFORMANCE_TESTS
|
||||
XML_Timer timer( &parseTime );
|
||||
|
|
|
|||
Loading…
Reference in New Issue