mirror of https://gitee.com/bigwinds/arangodb
try to fix potential crashes
This commit is contained in:
parent
a3694e7a01
commit
24ee67eda7
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 (...) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue