summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2020-02-03 17:29:08 +0000
committerAndrey Kleshchev <andreykproductengine@lindenlab.com>2020-02-03 17:29:08 +0000
commitc8e89de61dd1b650b9caa4c2593b0327ef295ef3 (patch)
tree996787835051fed678c463c50c268b13e3f14f20
parente0727702ea00c975361cf94b4d2903a9fec6f6f8 (diff)
SL-2569 More bad alloc checks
-rw-r--r--indra/newview/llmeshrepository.cpp134
-rw-r--r--indra/newview/llmeshrepository.h6
2 files changed, 91 insertions, 49 deletions
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index ce41e2bd35..c9c3dffc5a 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1554,7 +1554,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
if (!zero)
{ //attempt to parse
- if (physicsShapeReceived(mesh_id, buffer, size))
+ if (physicsShapeReceived(mesh_id, buffer, size) == MESH_OK)
{
delete[] buffer;
return true;
@@ -1648,7 +1648,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, bool c
LLMeshRepository::sCacheBytesRead += bytes;
++LLMeshRepository::sCacheReads;
file.read(buffer, bytes);
- if (headerReceived(mesh_params, buffer, bytes))
+ if (headerReceived(mesh_params, buffer, bytes) == MESH_OK)
{
// Found mesh in VFS cache
return true;
@@ -1795,7 +1795,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
return retval;
}
-bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size)
+EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size)
{
const LLUUID mesh_id = mesh_params.getSculptID();
LLSD header;
@@ -1803,30 +1803,39 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
U32 header_size = 0;
if (data_size > 0)
{
- std::string res_str((char*) data, data_size);
+ std::istringstream stream;
+ try
+ {
+ std::string res_str((char*)data, data_size);
- std::string deprecated_header("<? LLSD/Binary ?>");
+ std::string deprecated_header("<? LLSD/Binary ?>");
- if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
- {
- res_str = res_str.substr(deprecated_header.size()+1, data_size);
- header_size = deprecated_header.size()+1;
- }
- data_size = res_str.size();
+ if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
+ {
+ res_str = res_str.substr(deprecated_header.size() + 1, data_size);
+ header_size = deprecated_header.size() + 1;
+ }
+ data_size = res_str.size();
- std::istringstream stream(res_str);
+ stream.str(res_str);
+ }
+ catch (std::bad_alloc&)
+ {
+ // out of memory, we won't be able to process this mesh
+ return MESH_OUT_OF_MEMORY;
+ }
if (!LLSDSerialize::fromBinary(header, stream, data_size))
{
LL_WARNS(LOG_MESH) << "Mesh header parse error. Not a valid mesh asset! ID: " << mesh_id
<< LL_ENDL;
- return false;
+ return MESH_PARSE_FAILURE;
}
if (!header.isMap())
{
LL_WARNS(LOG_MESH) << "Mesh header is invalid for ID: " << mesh_id << LL_ENDL;
- return false;
+ return MESH_INVALID;
}
if (header.has("version") && header["version"].asInteger() > MAX_MESH_VERSION)
@@ -1872,7 +1881,7 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
}
}
- return true;
+ return MESH_OK;
}
EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size)
@@ -1917,18 +1926,25 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat
if (data_size > 0)
{
- std::string res_str((char*) data, data_size);
-
- std::istringstream stream(res_str);
+ try
+ {
+ std::string res_str((char*)data, data_size);
+ std::istringstream stream(res_str);
- U32 uzip_result = LLUZipHelper::unzip_llsd(skin, stream, data_size);
- if (uzip_result != LLUZipHelper::ZR_OK)
- {
- LL_WARNS(LOG_MESH) << "Mesh skin info parse error. Not a valid mesh asset! ID: " << mesh_id
- << " uzip result" << uzip_result
- << LL_ENDL;
- return false;
- }
+ U32 uzip_result = LLUZipHelper::unzip_llsd(skin, stream, data_size);
+ if (uzip_result != LLUZipHelper::ZR_OK)
+ {
+ LL_WARNS(LOG_MESH) << "Mesh skin info parse error. Not a valid mesh asset! ID: " << mesh_id
+ << " uzip result" << uzip_result
+ << LL_ENDL;
+ return false;
+ }
+ }
+ catch (std::bad_alloc&)
+ {
+ LL_WARNS(LOG_MESH) << "Out of memory for mesh ID " << mesh_id << " of size: " << data_size << LL_ENDL;
+ return false;
+ }
}
{
@@ -1950,19 +1966,26 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3
LLSD decomp;
if (data_size > 0)
- {
- std::string res_str((char*) data, data_size);
-
- std::istringstream stream(res_str);
+ {
+ try
+ {
+ std::string res_str((char*)data, data_size);
+ std::istringstream stream(res_str);
- U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, stream, data_size);
- if (uzip_result != LLUZipHelper::ZR_OK)
- {
- LL_WARNS(LOG_MESH) << "Mesh decomposition parse error. Not a valid mesh asset! ID: " << mesh_id
- << " uzip result: " << uzip_result
- << LL_ENDL;
- return false;
- }
+ U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, stream, data_size);
+ if (uzip_result != LLUZipHelper::ZR_OK)
+ {
+ LL_WARNS(LOG_MESH) << "Mesh decomposition parse error. Not a valid mesh asset! ID: " << mesh_id
+ << " uzip result: " << uzip_result
+ << LL_ENDL;
+ return false;
+ }
+ }
+ catch (std::bad_alloc&)
+ {
+ LL_WARNS(LOG_MESH) << "Out of memory for mesh ID " << mesh_id << " of size: " << data_size << LL_ENDL;
+ return false;
+ }
}
{
@@ -1977,7 +2000,7 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3
return true;
}
-bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size)
+EMeshProcessingResult LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size)
{
LLSD physics_shape;
@@ -1994,8 +2017,19 @@ bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32
volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
volume_params.setSculptID(mesh_id, LL_SCULPT_TYPE_MESH);
LLPointer<LLVolume> volume = new LLVolume(volume_params,0);
- std::string mesh_string((char*) data, data_size);
- std::istringstream stream(mesh_string);
+
+ std::istringstream stream;
+ try
+ {
+ std::string mesh_string((char*)data, data_size);
+ stream.str(mesh_string);
+ }
+ catch (std::bad_alloc&)
+ {
+ // out of memory, we won't be able to process this mesh
+ delete d;
+ return MESH_OUT_OF_MEMORY;
+ }
if (volume->unpackVolumeFaces(stream, data_size))
{
@@ -2034,7 +2068,7 @@ bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32
LLMutexLock lock(mMutex);
mDecompositionQ.push_back(d);
}
- return true;
+ return MESH_OK;
}
LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures,
@@ -3143,15 +3177,21 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
U8 * data, S32 data_size)
{
LLUUID mesh_id = mMeshParams.getSculptID();
- bool success = (! MESH_HEADER_PROCESS_FAILED)
- && ((data != NULL) == (data_size > 0)) // if we have data but no size or have size but no data, something is wrong
- && gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size);
+ bool success = (!MESH_HEADER_PROCESS_FAILED)
+ && ((data != NULL) == (data_size > 0)); // if we have data but no size or have size but no data, something is wrong;
llassert(success);
+ EMeshProcessingResult res = MESH_UNKNOWN;
+ if (success)
+ {
+ res = gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size);
+ success = (res == MESH_OK);
+ }
if (! success)
{
// *TODO: Get real reason for parse failure here. Might we want to retry?
LL_WARNS(LOG_MESH) << "Unable to parse mesh header. ID: " << mesh_id
- << ", Unknown reason. Not retrying."
+ << ", Size: " << data_size
+ << ", Reason: " << res << " Not retrying."
<< LL_ENDL;
// Can't get the header so none of the LODs will be available
@@ -3431,7 +3471,7 @@ void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * /* body */, S3
{
if ((!MESH_PHYS_SHAPE_PROCESS_FAILED)
&& ((data != NULL) == (data_size > 0)) // if we have data but no size or have size but no data, something is wrong
- && gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size))
+ && gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size) == MESH_OK)
{
// good fetch from sim, write to VFS for caching
LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE);
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index bba0c9f2cb..9a627dabcb 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -57,6 +57,8 @@ typedef enum e_mesh_processing_result_enum
MESH_NO_DATA = 1,
MESH_OUT_OF_MEMORY,
MESH_HTTP_REQUEST_FAILED,
+ MESH_PARSE_FAILURE,
+ MESH_INVALID,
MESH_UNKNOWN
} EMeshProcessingResult;
@@ -336,11 +338,11 @@ public:
bool fetchMeshHeader(const LLVolumeParams& mesh_params, bool can_retry = true);
bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, bool can_retry = true);
- bool headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size);
+ EMeshProcessingResult headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size);
EMeshProcessingResult lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size);
bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
- bool physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
+ EMeshProcessingResult physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
LLSD& getMeshHeader(const LLUUID& mesh_id);
void notifyLoadedMeshes();