diff options
author | Jason Carey <jcarey@argv.me> | 2015-07-31 18:18:07 -0400 |
---|---|---|
committer | Jason Carey <jcarey@argv.me> | 2015-08-10 14:42:34 -0400 |
commit | df71fbb001ce204c9f60b9ec66b1178b851cdbb4 (patch) | |
tree | a7bac74c1f97333c510948c7d8a6e71e0afa47ae /src | |
parent | bed94851c02602dcf4ba9dcec376cfda7f33e657 (diff) | |
download | mongo-df71fbb001ce204c9f60b9ec66b1178b851cdbb4.tar.gz |
SERVER-19705 unmix MozJS and Mongo Error Codes
SpiderMonkey error codes overlap with Mongo error codes in thrown user
assertions. Avoid that by lifting our error codes above theirs.
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/dbtests/jstests.cpp | 38 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/exception.cpp | 34 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/exception.h | 8 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/implscope.cpp | 7 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/jsthread.cpp | 2 |
5 files changed, 75 insertions, 14 deletions
diff --git a/src/mongo/dbtests/jstests.cpp b/src/mongo/dbtests/jstests.cpp index 4723fcf9b96..4a4ebb408a4 100644 --- a/src/mongo/dbtests/jstests.cpp +++ b/src/mongo/dbtests/jstests.cpp @@ -2175,6 +2175,43 @@ public: } }; +class ErrorCodeFromInvoke { +public: + void run() { + unique_ptr<Scope> s(globalScriptEngine->newScope()); + + { + bool threwException = false; + try { + s->invoke("\"use strict\"; x = 10;", 0, 0); + } catch (...) { + threwException = true; + + auto status = exceptionToStatus(); + + ASSERT_EQUALS(status.code(), ErrorCodes::JSInterpreterFailure); + } + + ASSERT(threwException); + } + + { + bool threwException = false; + try { + s->invoke("UUID(1,2,3,4,5);", 0, 0); + } catch (...) { + threwException = true; + + auto status = exceptionToStatus(); + + ASSERT_EQUALS(status.code(), ErrorCodes::BadValue); + } + + ASSERT(threwException); + } + } +}; + class All : public Suite { public: All() : Suite("js") { @@ -2226,6 +2263,7 @@ public: add<NoReturnSpecified>(); add<RecursiveInvoke>(); + add<ErrorCodeFromInvoke>(); add<RoundTripTests::DBRefTest>(); add<RoundTripTests::DBPointerTest>(); diff --git a/src/mongo/scripting/mozjs/exception.cpp b/src/mongo/scripting/mozjs/exception.cpp index 1d6880da05f..e54de1fa5ca 100644 --- a/src/mongo/scripting/mozjs/exception.cpp +++ b/src/mongo/scripting/mozjs/exception.cpp @@ -31,6 +31,7 @@ #include "mongo/scripting/mozjs/exception.h" #include <jsfriendapi.h> +#include <limits> #include "mongo/scripting/mozjs/jsstringwrapper.h" #include "mongo/util/assert_util.h" @@ -50,6 +51,9 @@ const JSErrorFormatString* uncatchableErrorCallback(void* data, const unsigned c return &kUncatchableErrorFormatString; } +static_assert(std::numeric_limits<std::uint32_t>::max() - JSErr_Limit > ErrorCodes::MaxError, + "Not enough space in an unsigned int for Mongo ErrorCodes and JSErrorNumbers"); + } // namespace void mongoToJSException(JSContext* cx) { @@ -58,14 +62,15 @@ void mongoToJSException(JSContext* cx) { auto callback = status.code() == ErrorCodes::JSUncatchableError ? uncatchableErrorCallback : errorCallback; - JS_ReportErrorNumber(cx, callback, nullptr, status.code(), status.reason().c_str()); + JS_ReportErrorNumber( + cx, callback, nullptr, JSErr_Limit + status.code(), status.reason().c_str()); } void setJSException(JSContext* cx, ErrorCodes::Error code, StringData sd) { auto callback = code == ErrorCodes::JSUncatchableError ? uncatchableErrorCallback : errorCallback; - JS_ReportErrorNumber(cx, callback, nullptr, code, sd.rawData()); + JS_ReportErrorNumber(cx, callback, nullptr, JSErr_Limit + code, sd.rawData()); } Status currentJSExceptionToStatus(JSContext* cx, ErrorCodes::Error altCode, StringData altReason) { @@ -78,17 +83,28 @@ Status currentJSExceptionToStatus(JSContext* cx, ErrorCodes::Error altCode, Stri if (!report) return Status(altCode, altReason.rawData()); + return JSErrorReportToStatus(cx, report, altCode, altReason); +} + +Status JSErrorReportToStatus(JSContext* cx, + JSErrorReport* report, + ErrorCodes::Error altCode, + StringData altReason) { JSStringWrapper jsstr(cx, js::ErrorReportToString(cx, report)); if (!jsstr) return Status(altCode, altReason.rawData()); - /** - * errorNumber is only set by library consumers of MozJS, and then only via - * JS_ReportErrorNumber, so all of the codes we see here are ours. - */ - return Status(report->errorNumber ? static_cast<ErrorCodes::Error>(report->errorNumber) - : altCode, - jsstr.toStringData().toString()); + ErrorCodes::Error error = altCode; + + if (report->errorNumber) { + if (report->errorNumber < JSErr_Limit) { + error = ErrorCodes::JSInterpreterFailure; + } else { + error = static_cast<ErrorCodes::Error>(report->errorNumber - JSErr_Limit); + } + } + + return Status(error, jsstr.toStringData().toString()); } void throwCurrentJSException(JSContext* cx, ErrorCodes::Error altCode, StringData altReason) { diff --git a/src/mongo/scripting/mozjs/exception.h b/src/mongo/scripting/mozjs/exception.h index 9ef48664db6..b3dcbfa67bb 100644 --- a/src/mongo/scripting/mozjs/exception.h +++ b/src/mongo/scripting/mozjs/exception.h @@ -55,6 +55,14 @@ void setJSException(JSContext* cx, ErrorCodes::Error code, StringData sd); Status currentJSExceptionToStatus(JSContext* cx, ErrorCodes::Error altCode, StringData altReason); /** + * Converts a JSErrorReport to status + */ +Status JSErrorReportToStatus(JSContext* cx, + JSErrorReport* report, + ErrorCodes::Error altCode, + StringData altReason); + +/** * Turns the current JS exception into a C++ exception * * The altCode and altReason are used if no JS exception is pending diff --git a/src/mongo/scripting/mozjs/implscope.cpp b/src/mongo/scripting/mozjs/implscope.cpp index f77c130d9f4..0c110ec546a 100644 --- a/src/mongo/scripting/mozjs/implscope.cpp +++ b/src/mongo/scripting/mozjs/implscope.cpp @@ -114,10 +114,9 @@ void MozJSImplScope::_reportError(JSContext* cx, const char* message, JSErrorRep ss << " :\n" << ValueWriter(cx, stack).toString(); } - scope->_status = - Status(report->errorNumber ? static_cast<ErrorCodes::Error>(report->errorNumber) - : ErrorCodes::JSInterpreterFailure, - ss); + scope->_status = Status( + JSErrorReportToStatus(cx, report, ErrorCodes::JSInterpreterFailure, message).code(), + ss); } } diff --git a/src/mongo/scripting/mozjs/jsthread.cpp b/src/mongo/scripting/mozjs/jsthread.cpp index 9d409fa9beb..4a3b441a885 100644 --- a/src/mongo/scripting/mozjs/jsthread.cpp +++ b/src/mongo/scripting/mozjs/jsthread.cpp @@ -177,7 +177,7 @@ private: } catch (...) { auto status = exceptionToStatus(); - log() << "js thread raised js exception: " << status; + log() << "js thread raised js exception: " << status.reason(); _sharedData->setErrored(true); _sharedData->_returnData = BSON("ret" << BSONUndefined); } |