summaryrefslogtreecommitdiff
path: root/indra/llcommon/llsdserialize.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/llsdserialize.cpp')
-rw-r--r--indra/llcommon/llsdserialize.cpp61
1 files changed, 42 insertions, 19 deletions
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index a487322d17..c3fb4ebc2c 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -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");
@@ -327,11 +328,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);
}
@@ -413,7 +414,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 ]
@@ -428,6 +429,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.
@@ -444,7 +449,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;
@@ -463,7 +468,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;
@@ -668,7 +673,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();
@@ -703,7 +708,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
@@ -728,7 +733,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();
@@ -747,7 +752,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;
@@ -879,7 +884,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>
@@ -903,12 +908,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;
@@ -927,7 +936,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;
@@ -1108,7 +1117,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;
@@ -1138,7 +1147,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
@@ -1162,7 +1171,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;
@@ -1178,7 +1187,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;
@@ -2248,7 +2257,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;
@@ -2263,13 +2272,24 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,
//and trailers are different for the formats.
U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size )
{
+ if (size == 0)
+ {
+ LL_WARNS() << "No data to unzip." << LL_ENDL;
+ return NULL;
+ }
+
U8* result = NULL;
U32 cur_size = 0;
z_stream strm;
const U32 CHUNK = 0x4000;
- U8 *in = new U8[size];
+ U8 *in = new(std::nothrow) U8[size];
+ if (in == NULL)
+ {
+ LL_WARNS() << "Memory allocation failure." << LL_ENDL;
+ return NULL;
+ }
is.read((char*) in, size);
U8 out[CHUNK];
@@ -2313,7 +2333,10 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32
U8* new_result = (U8*) realloc(result, cur_size + have);
if (new_result == NULL)
{
- LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL;
+ LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size
+ << " bytes; requested " << cur_size + have
+ << " bytes; total syze: ." << size << " bytes."
+ << LL_ENDL;
inflateEnd(&strm);
if (result)
{