1
0
Fork 0

try to fix potential crashes

This commit is contained in:
Jan Steemann 2016-06-14 16:41:00 +02:00
parent a3694e7a01
commit 24ee67eda7
12 changed files with 122 additions and 92 deletions

View File

@ -368,22 +368,14 @@ int arangodb::aql::CompareAstNodes(AstNode const* lhs, AstNode const* rhs,
if (lType == TRI_JSON_OBJECT) {
// this is a rather exceptional case, so we can
// afford the inefficiency to convert to node to
// afford the inefficiency to convert the node to
// JSON for comparison
// (this saves us from writing our own compare function
// for array AstNodes)
auto lJson = lhs->toJsonValue(TRI_UNKNOWN_MEM_ZONE);
auto rJson = rhs->toJsonValue(TRI_UNKNOWN_MEM_ZONE);
std::unique_ptr<TRI_json_t> lJson(lhs->toJsonValue(TRI_UNKNOWN_MEM_ZONE));
std::unique_ptr<TRI_json_t> rJson(rhs->toJsonValue(TRI_UNKNOWN_MEM_ZONE));
int res = TRI_CompareValuesJson(lJson, rJson, compareUtf8);
if (lJson != nullptr) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, lJson);
}
if (rJson != nullptr) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, rJson);
}
return res;
return TRI_CompareValuesJson(lJson.get(), rJson.get(), compareUtf8);
}
// all things equal

View File

@ -200,7 +200,7 @@ HttpHandler::status_t PathHandler::execute() {
return status_t(HANDLER_DONE);
}
void PathHandler::handleError(const Exception&) {
void PathHandler::handleError(Exception const&) {
createResponse(GeneralResponse::ResponseCode::SERVER_ERROR);
}
}

View File

@ -68,8 +68,14 @@ RocksDBFeature::RocksDBFeature(
}
RocksDBFeature::~RocksDBFeature() {
delete _db;
delete _comparator;
try {
delete _db;
} catch (...) {
}
try {
delete _comparator;
} catch (...) {
}
}
void RocksDBFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {

View File

@ -2030,7 +2030,7 @@ static void JS_UseDatabase(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_FORBIDDEN);
}
std::string&& name = TRI_ObjectToString(args[0]);
std::string name = TRI_ObjectToString(args[0]);
TRI_vocbase_t* vocbase = GetContextVocBase(isolate);

View File

@ -45,7 +45,13 @@ ApplicationServer::ApplicationServer(std::shared_ptr<ProgramOptions> options)
ApplicationServer::~ApplicationServer() {
for (auto& it : _features) {
delete it.second;
try {
delete it.second;
} catch (...) {
// we must skip over errors here as we're in the destructor.
// we cannot rely on the LoggerFeature being present either, so
// we have to suppress errors here
}
}
ApplicationServer::server = nullptr;

View File

@ -155,7 +155,11 @@ static TRI_json_t* UniquifyArrayJson(TRI_json_t const* array) {
// don't push value if it is the same as the last value
if (last == nullptr || TRI_CompareValuesJson(p, last, false) != 0) {
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result.get(), p);
int res = TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result.get(), p);
if (res != TRI_ERROR_NO_ERROR) {
return nullptr;
}
// remember last element
last = p;
@ -223,7 +227,11 @@ static TRI_json_t* GetMergedKeyArray(TRI_json_t const* lhs,
static_cast<TRI_json_t const*>(TRI_AtVector(&lhs->_value._objects, i));
TRI_ASSERT(TRI_IsStringJson(key));
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, keys.get(), key);
int res = TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, keys.get(), key);
if (res != TRI_ERROR_NO_ERROR) {
return nullptr;
}
}
n = TRI_LengthVector(&rhs->_value._objects);
@ -233,7 +241,11 @@ static TRI_json_t* GetMergedKeyArray(TRI_json_t const* lhs,
static_cast<TRI_json_t const*>(TRI_AtVector(&rhs->_value._objects, i));
TRI_ASSERT(TRI_IsStringJson(key));
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, keys.get(), key);
int res = TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, keys.get(), key);
if (res != TRI_ERROR_NO_ERROR) {
return nullptr;
}
}
// sort the key array in place
@ -370,25 +382,27 @@ int TRI_CompareValuesJson(TRI_json_t const* lhs, TRI_json_t const* rhs,
std::unique_ptr<TRI_json_t> keys(GetMergedKeyArray(lhs, rhs));
if (keys != nullptr) {
auto json = keys.get();
size_t const n = TRI_LengthVector(&json->_value._objects);
if (keys == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
for (size_t i = 0; i < n; ++i) {
auto keyElement = static_cast<TRI_json_t const*>(
TRI_AtVector(&json->_value._objects, i));
TRI_ASSERT(TRI_IsStringJson(keyElement));
auto json = keys.get();
size_t const n = TRI_LengthVector(&json->_value._objects);
TRI_json_t const* lhsValue = TRI_LookupObjectJson(
lhs, keyElement->_value._string.data); // may be NULL
TRI_json_t const* rhsValue = TRI_LookupObjectJson(
rhs, keyElement->_value._string.data); // may be NULL
for (size_t i = 0; i < n; ++i) {
auto keyElement = static_cast<TRI_json_t const*>(
TRI_AtVector(&json->_value._objects, i));
TRI_ASSERT(TRI_IsStringJson(keyElement));
int result = TRI_CompareValuesJson(lhsValue, rhsValue, useUTF8);
TRI_json_t const* lhsValue = TRI_LookupObjectJson(
lhs, keyElement->_value._string.data); // may be NULL
TRI_json_t const* rhsValue = TRI_LookupObjectJson(
rhs, keyElement->_value._string.data); // may be NULL
if (result != 0) {
return result;
}
int result = TRI_CompareValuesJson(lhsValue, rhsValue, useUTF8);
if (result != 0) {
return result;
}
}
// fall-through to returning 0

View File

@ -556,8 +556,8 @@ bool TRI_IsStringJson(TRI_json_t const* json) { return IsString(json); }
/// @brief adds a new sub-object to an array, copying it
////////////////////////////////////////////////////////////////////////////////
void TRI_PushBackArrayJson(TRI_memory_zone_t* zone, TRI_json_t* array,
TRI_json_t const* object) {
int TRI_PushBackArrayJson(TRI_memory_zone_t* zone, TRI_json_t* array,
TRI_json_t const* object) {
TRI_ASSERT(array->_type == TRI_JSON_ARRAY);
TRI_json_t* dst =
@ -565,11 +565,11 @@ void TRI_PushBackArrayJson(TRI_memory_zone_t* zone, TRI_json_t* array,
if (dst == nullptr) {
// out of memory
return;
return TRI_ERROR_OUT_OF_MEMORY;
}
// directly copy value into the obtained address
TRI_CopyToJson(zone, dst, object);
return TRI_CopyToJson(zone, dst, object);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -219,8 +219,8 @@ bool TRI_IsStringJson(TRI_json_t const* json);
/// @brief adds a new sub-object to an array, copying it
////////////////////////////////////////////////////////////////////////////////
void TRI_PushBackArrayJson(TRI_memory_zone_t*, TRI_json_t* array,
TRI_json_t const* object);
int TRI_PushBackArrayJson(TRI_memory_zone_t*, TRI_json_t* array,
TRI_json_t const* object);
////////////////////////////////////////////////////////////////////////////////
/// @brief adds a new sub-object to an array, not copying it

View File

@ -167,7 +167,7 @@ static bool ShouldFail(size_t n) {
////////////////////////////////////////////////////////////////////////////////
#ifdef ARANGODB_ENABLE_FAILURE_TESTS
static char* FailMalloc(TRI_memory_zone_t* zone, size_t n) {
static void* FailMalloc(TRI_memory_zone_t* zone, size_t n) {
// we can fail, so let's check whether we should fail intentionally...
if (zone->_failable && ShouldFail(n)) {
// intentionally return NULL
@ -175,7 +175,7 @@ static char* FailMalloc(TRI_memory_zone_t* zone, size_t n) {
return nullptr;
}
return static_cast<char*>(BuiltInMalloc(n));
return BuiltInMalloc(n);
}
#endif
@ -184,7 +184,7 @@ static char* FailMalloc(TRI_memory_zone_t* zone, size_t n) {
////////////////////////////////////////////////////////////////////////////////
#ifdef ARANGODB_ENABLE_FAILURE_TESTS
static char* FailRealloc(TRI_memory_zone_t* zone, void* old, size_t n) {
static void* FailRealloc(TRI_memory_zone_t* zone, void* old, size_t n) {
// we can fail, so let's check whether we should fail intentionally...
if (zone->_failable && ShouldFail(n)) {
// intentionally return NULL
@ -192,7 +192,7 @@ static char* FailRealloc(TRI_memory_zone_t* zone, void* old, size_t n) {
return nullptr;
}
return static_cast<char*>(BuiltInRealloc(old, n));
return BuiltInRealloc(old, n);
}
#endif

View File

@ -62,9 +62,7 @@ static void* ThreadStarter(void* data) {
try {
d->starter(d->_data);
} catch (...) {
TRI_FreeString(TRI_CORE_MEM_ZONE, d->_name);
TRI_Free(TRI_CORE_MEM_ZONE, d);
throw;
// we must not throw from here
}
TRI_FreeString(TRI_CORE_MEM_ZONE, d->_name);

View File

@ -33,7 +33,11 @@ LoggerStream::~LoggerStream() {
try {
Logger::log(_function, _file, _line, _level, _topicId, _out.str());
} catch (...) {
std::cerr << "failed to log: " << _out.str() << std::endl;
try {
// logging the error may fail as well, and we should never throw in the dtor
std::cerr << "failed to log: " << _out.str() << std::endl;
} catch (...) {
}
}
}

View File

@ -108,46 +108,51 @@ TRI_Utf8ValueNFC::~TRI_Utf8ValueNFC() {
////////////////////////////////////////////////////////////////////////////////
static void CreateErrorObject(v8::Isolate* isolate, int errorNumber,
std::string const& message) {
if (errorNumber == TRI_ERROR_OUT_OF_MEMORY) {
LOG(ERR) << "encountered out-of-memory error";
std::string const& message) noexcept {
try {
if (errorNumber == TRI_ERROR_OUT_OF_MEMORY) {
LOG(ERR) << "encountered out-of-memory error";
}
v8::Handle<v8::String> errorMessage = TRI_V8_STD_STRING(message);
if (errorMessage.IsEmpty()) {
isolate->ThrowException(v8::Object::New(isolate));
return;
}
v8::Handle<v8::Value> err = v8::Exception::Error(errorMessage);
if (err.IsEmpty()) {
isolate->ThrowException(v8::Object::New(isolate));
return;
}
v8::Handle<v8::Object> errorObject = err->ToObject();
if (errorObject.IsEmpty()) {
isolate->ThrowException(v8::Object::New(isolate));
return;
}
errorObject->Set(TRI_V8_ASCII_STRING("errorNum"),
v8::Number::New(isolate, errorNumber));
errorObject->Set(TRI_V8_ASCII_STRING("errorMessage"), errorMessage);
TRI_GET_GLOBALS();
TRI_GET_GLOBAL(ArangoErrorTempl, v8::ObjectTemplate);
v8::Handle<v8::Object> ArangoError = ArangoErrorTempl->NewInstance();
if (!ArangoError.IsEmpty()) {
errorObject->SetPrototype(ArangoError);
}
isolate->ThrowException(errorObject);
} catch (...) {
// must not throw from here, as a C++ exception must not escape the
// C++ bindings that are called by V8. if it does, the program will crash
}
v8::Handle<v8::String> errorMessage = TRI_V8_STD_STRING(message);
if (errorMessage.IsEmpty()) {
isolate->ThrowException(v8::Object::New(isolate));
return;
}
v8::Handle<v8::Value> err = v8::Exception::Error(errorMessage);
if (err.IsEmpty()) {
isolate->ThrowException(v8::Object::New(isolate));
return;
}
v8::Handle<v8::Object> errorObject = err->ToObject();
if (errorObject.IsEmpty()) {
isolate->ThrowException(v8::Object::New(isolate));
return;
}
errorObject->Set(TRI_V8_ASCII_STRING("errorNum"),
v8::Number::New(isolate, errorNumber));
errorObject->Set(TRI_V8_ASCII_STRING("errorMessage"), errorMessage);
TRI_GET_GLOBALS();
TRI_GET_GLOBAL(ArangoErrorTempl, v8::ObjectTemplate);
v8::Handle<v8::Object> ArangoError = ArangoErrorTempl->NewInstance();
if (!ArangoError.IsEmpty()) {
errorObject->SetPrototype(ArangoError);
}
isolate->ThrowException(errorObject);
}
////////////////////////////////////////////////////////////////////////////////
@ -4032,7 +4037,6 @@ v8::Handle<v8::Value> TRI_ExecuteJavaScriptString(
void TRI_CreateErrorObject(v8::Isolate* isolate, int errorNumber) {
v8::HandleScope scope(isolate);
CreateErrorObject(isolate, errorNumber, TRI_errno_string(errorNumber));
}
@ -4055,9 +4059,15 @@ void TRI_CreateErrorObject(v8::Isolate* isolate, int errorNumber,
v8::HandleScope scope(isolate);
if (autoPrepend) {
CreateErrorObject(
isolate, errorNumber,
message + ": " + std::string(TRI_errno_string(errorNumber)));
try {
// does string concatenation, so we must wrap this in a try...catch block
CreateErrorObject(
isolate, errorNumber,
message + ": " + std::string(TRI_errno_string(errorNumber)));
} catch (...) {
// we cannot do anything about this here, but no C++ exception must
// escape the C++ bindings called by V8
}
} else {
CreateErrorObject(isolate, errorNumber, message);
}