• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef SRC_NODE_ERRORS_H_
2 #define SRC_NODE_ERRORS_H_
3 
4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5 
6 #include "debug_utils-inl.h"
7 #include "env.h"
8 #include "v8.h"
9 
10 // Use ostringstream to print exact-width integer types
11 // because the format specifiers are not available on AIX.
12 #include <sstream>
13 
14 namespace node {
15 
16 enum ErrorHandlingMode { CONTEXTIFY_ERROR, FATAL_ERROR, MODULE_ERROR };
17 void AppendExceptionLine(Environment* env,
18                          v8::Local<v8::Value> er,
19                          v8::Local<v8::Message> message,
20                          enum ErrorHandlingMode mode);
21 
22 [[noreturn]] void FatalError(const char* location, const char* message);
23 [[noreturn]] void OnFatalError(const char* location, const char* message);
24 [[noreturn]] void OOMErrorHandler(const char* location, bool is_heap_oom);
25 
26 // Helpers to construct errors similar to the ones provided by
27 // lib/internal/errors.js.
28 // Example: with `V(ERR_INVALID_ARG_TYPE, TypeError)`, there will be
29 // `node::ERR_INVALID_ARG_TYPE(isolate, "message")` returning
30 // a `Local<Value>` containing the TypeError with proper code and message
31 
32 #define ERRORS_WITH_CODE(V)                                                    \
33   V(ERR_BUFFER_CONTEXT_NOT_AVAILABLE, Error)                                   \
34   V(ERR_BUFFER_OUT_OF_BOUNDS, RangeError)                                      \
35   V(ERR_BUFFER_TOO_LARGE, Error)                                               \
36   V(ERR_CLOSED_MESSAGE_PORT, Error)                                            \
37   V(ERR_CONSTRUCT_CALL_REQUIRED, TypeError)                                    \
38   V(ERR_CONSTRUCT_CALL_INVALID, TypeError)                                     \
39   V(ERR_CRYPTO_INITIALIZATION_FAILED, Error)                                   \
40   V(ERR_CRYPTO_INVALID_AUTH_TAG, TypeError)                                    \
41   V(ERR_CRYPTO_INVALID_COUNTER, TypeError)                                     \
42   V(ERR_CRYPTO_INVALID_CURVE, TypeError)                                       \
43   V(ERR_CRYPTO_INVALID_DIGEST, TypeError)                                      \
44   V(ERR_CRYPTO_INVALID_IV, TypeError)                                          \
45   V(ERR_CRYPTO_INVALID_JWK, TypeError)                                         \
46   V(ERR_CRYPTO_INVALID_KEYLEN, RangeError)                                     \
47   V(ERR_CRYPTO_INVALID_KEYPAIR, RangeError)                                    \
48   V(ERR_CRYPTO_INVALID_KEYTYPE, RangeError)                                    \
49   V(ERR_CRYPTO_INVALID_MESSAGELEN, RangeError)                                 \
50   V(ERR_CRYPTO_INVALID_SCRYPT_PARAMS, RangeError)                              \
51   V(ERR_CRYPTO_INVALID_STATE, Error)                                           \
52   V(ERR_CRYPTO_INVALID_TAG_LENGTH, RangeError)                                 \
53   V(ERR_CRYPTO_JWK_UNSUPPORTED_CURVE, Error)                                   \
54   V(ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE, Error)                                \
55   V(ERR_CRYPTO_OPERATION_FAILED, Error)                                        \
56   V(ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH, RangeError)                           \
57   V(ERR_CRYPTO_UNKNOWN_CIPHER, Error)                                          \
58   V(ERR_CRYPTO_UNKNOWN_DH_GROUP, Error)                                        \
59   V(ERR_CRYPTO_UNSUPPORTED_OPERATION, Error)                                   \
60   V(ERR_CRYPTO_JOB_INIT_FAILED, Error)                                         \
61   V(ERR_DLOPEN_DISABLED, Error)                                                \
62   V(ERR_DLOPEN_FAILED, Error)                                                  \
63   V(ERR_ENCODING_INVALID_ENCODED_DATA, TypeError)                              \
64   V(ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE, Error)                            \
65   V(ERR_ILLEGAL_CONSTRUCTOR, Error)                                            \
66   V(ERR_INVALID_ADDRESS, Error)                                                \
67   V(ERR_INVALID_ARG_VALUE, TypeError)                                          \
68   V(ERR_OSSL_EVP_INVALID_DIGEST, Error)                                        \
69   V(ERR_INVALID_ARG_TYPE, TypeError)                                           \
70   V(ERR_INVALID_OBJECT_DEFINE_PROPERTY, TypeError)                             \
71   V(ERR_INVALID_MODULE, Error)                                                 \
72   V(ERR_INVALID_STATE, Error)                                                  \
73   V(ERR_INVALID_THIS, TypeError)                                               \
74   V(ERR_INVALID_TRANSFER_OBJECT, TypeError)                                    \
75   V(ERR_MEMORY_ALLOCATION_FAILED, Error)                                       \
76   V(ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE, Error)                             \
77   V(ERR_MISSING_ARGS, TypeError)                                               \
78   V(ERR_MISSING_TRANSFERABLE_IN_TRANSFER_LIST, TypeError)                      \
79   V(ERR_MISSING_PASSPHRASE, TypeError)                                         \
80   V(ERR_MISSING_PLATFORM_FOR_WORKER, Error)                                    \
81   V(ERR_NON_CONTEXT_AWARE_DISABLED, Error)                                     \
82   V(ERR_OUT_OF_RANGE, RangeError)                                              \
83   V(ERR_SCRIPT_EXECUTION_INTERRUPTED, Error)                                   \
84   V(ERR_SCRIPT_EXECUTION_TIMEOUT, Error)                                       \
85   V(ERR_STRING_TOO_LONG, Error)                                                \
86   V(ERR_TLS_INVALID_PROTOCOL_METHOD, TypeError)                                \
87   V(ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED, Error)                                \
88   V(ERR_VM_MODULE_CACHED_DATA_REJECTED, Error)                                 \
89   V(ERR_VM_MODULE_LINK_FAILURE, Error)                                         \
90   V(ERR_WASI_NOT_STARTED, Error)                                               \
91   V(ERR_WORKER_INIT_FAILED, Error)                                             \
92   V(ERR_PROTO_ACCESS, Error)
93 
94 #define V(code, type)                                                          \
95   template <typename... Args>                                                  \
96   inline v8::Local<v8::Value> code(                                            \
97       v8::Isolate* isolate, const char* format, Args&&... args) {              \
98     std::string message = SPrintF(format, std::forward<Args>(args)...);        \
99     v8::Local<v8::String> js_code = OneByteString(isolate, #code);             \
100     v8::Local<v8::String> js_msg =                                             \
101         OneByteString(isolate, message.c_str(), message.length());             \
102     v8::Local<v8::Object> e = v8::Exception::type(js_msg)                      \
103                                   ->ToObject(isolate->GetCurrentContext())     \
104                                   .ToLocalChecked();                           \
105     e->Set(isolate->GetCurrentContext(),                                       \
106            OneByteString(isolate, "code"),                                     \
107            js_code)                                                            \
108         .Check();                                                              \
109     return e;                                                                  \
110   }                                                                            \
111   template <typename... Args>                                                  \
112   inline void THROW_##code(                                                    \
113       v8::Isolate* isolate, const char* format, Args&&... args) {              \
114     isolate->ThrowException(                                                   \
115         code(isolate, format, std::forward<Args>(args)...));                   \
116   }                                                                            \
117   template <typename... Args>                                                  \
118   inline void THROW_##code(                                                    \
119       Environment* env, const char* format, Args&&... args) {                  \
120     THROW_##code(env->isolate(), format, std::forward<Args>(args)...);         \
121   }
122 ERRORS_WITH_CODE(V)
123 #undef V
124 
125 // Errors with predefined static messages
126 
127 #define PREDEFINED_ERROR_MESSAGES(V)                                           \
128   V(ERR_BUFFER_CONTEXT_NOT_AVAILABLE,                                          \
129     "Buffer is not available for the current Context")                         \
130   V(ERR_CLOSED_MESSAGE_PORT, "Cannot send data on closed MessagePort")         \
131   V(ERR_CONSTRUCT_CALL_INVALID, "Constructor cannot be called")                \
132   V(ERR_CONSTRUCT_CALL_REQUIRED, "Cannot call constructor without `new`")      \
133   V(ERR_CRYPTO_INITIALIZATION_FAILED, "Initialization failed")                 \
134   V(ERR_CRYPTO_INVALID_AUTH_TAG, "Invalid authentication tag")                 \
135   V(ERR_CRYPTO_INVALID_COUNTER, "Invalid counter")                             \
136   V(ERR_CRYPTO_INVALID_CURVE, "Invalid EC curve name")                         \
137   V(ERR_CRYPTO_INVALID_DIGEST, "Invalid digest")                               \
138   V(ERR_CRYPTO_INVALID_IV, "Invalid initialization vector")                    \
139   V(ERR_CRYPTO_INVALID_JWK, "Invalid JWK format")                              \
140   V(ERR_CRYPTO_INVALID_KEYLEN, "Invalid key length")                           \
141   V(ERR_CRYPTO_INVALID_KEYPAIR, "Invalid key pair")                            \
142   V(ERR_CRYPTO_INVALID_KEYTYPE, "Invalid key type")                            \
143   V(ERR_CRYPTO_INVALID_MESSAGELEN, "Invalid message length")                   \
144   V(ERR_CRYPTO_INVALID_SCRYPT_PARAMS, "Invalid scrypt params")                 \
145   V(ERR_CRYPTO_INVALID_STATE, "Invalid state")                                 \
146   V(ERR_CRYPTO_INVALID_TAG_LENGTH, "Invalid taglength")                        \
147   V(ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE, "Unsupported JWK Key Type.")          \
148   V(ERR_CRYPTO_OPERATION_FAILED, "Operation failed")                           \
149   V(ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH,                                       \
150     "Input buffers must have the same byte length")                            \
151   V(ERR_CRYPTO_UNKNOWN_CIPHER, "Unknown cipher")                               \
152   V(ERR_CRYPTO_UNKNOWN_DH_GROUP, "Unknown DH group")                           \
153   V(ERR_CRYPTO_UNSUPPORTED_OPERATION, "Unsupported crypto operation")          \
154   V(ERR_CRYPTO_JOB_INIT_FAILED, "Failed to initialize crypto job config")      \
155   V(ERR_DLOPEN_FAILED, "DLOpen failed")                                        \
156   V(ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE,                                   \
157     "Context not associated with Node.js environment")                         \
158   V(ERR_ILLEGAL_CONSTRUCTOR, "Illegal constructor")                            \
159   V(ERR_INVALID_ADDRESS, "Invalid socket address")                             \
160   V(ERR_INVALID_MODULE, "No such module")                                      \
161   V(ERR_INVALID_THIS, "Value of \"this\" is the wrong type")                   \
162   V(ERR_INVALID_TRANSFER_OBJECT, "Found invalid object in transferList")       \
163   V(ERR_MEMORY_ALLOCATION_FAILED, "Failed to allocate memory")                 \
164   V(ERR_OSSL_EVP_INVALID_DIGEST, "Invalid digest used")                        \
165   V(ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE,                                    \
166     "A message object could not be deserialized successfully in the target "   \
167     "vm.Context")                                                              \
168   V(ERR_MISSING_TRANSFERABLE_IN_TRANSFER_LIST,                                 \
169     "Object that needs transfer was found in message but not listed "          \
170     "in transferList")                                                         \
171   V(ERR_MISSING_PLATFORM_FOR_WORKER,                                           \
172     "The V8 platform used by this instance of Node does not support "          \
173     "creating Workers")                                                        \
174   V(ERR_NON_CONTEXT_AWARE_DISABLED,                                            \
175     "Loading non context-aware native addons has been disabled")               \
176   V(ERR_SCRIPT_EXECUTION_INTERRUPTED,                                          \
177     "Script execution was interrupted by `SIGINT`")                            \
178   V(ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED, "Failed to set PSK identity hint")    \
179   V(ERR_WASI_NOT_STARTED, "wasi.start() has not been called")                  \
180   V(ERR_WORKER_INIT_FAILED, "Worker initialization failure")                   \
181   V(ERR_PROTO_ACCESS,                                                          \
182     "Accessing Object.prototype.__proto__ has been "                           \
183     "disallowed with --disable-proto=throw")
184 
185 #define V(code, message)                                                     \
186   inline v8::Local<v8::Value> code(v8::Isolate* isolate) {                   \
187     return code(isolate, message);                                           \
188   }                                                                          \
189   inline void THROW_ ## code(v8::Isolate* isolate) {                         \
190     isolate->ThrowException(code(isolate, message));                         \
191   }                                                                          \
192   inline void THROW_ ## code(Environment* env) {                             \
193     THROW_ ## code(env->isolate());                                          \
194   }
PREDEFINED_ERROR_MESSAGES(V)195   PREDEFINED_ERROR_MESSAGES(V)
196 #undef V
197 
198 // Errors with predefined non-static messages
199 inline void THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(Environment* env,
200                                                int64_t timeout) {
201   std::ostringstream message;
202   message << "Script execution timed out after ";
203   message << timeout << "ms";
204   THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(env, message.str().c_str());
205 }
206 
ERR_BUFFER_TOO_LARGE(v8::Isolate * isolate)207 inline v8::Local<v8::Value> ERR_BUFFER_TOO_LARGE(v8::Isolate* isolate) {
208   char message[128];
209   snprintf(message, sizeof(message),
210       "Cannot create a Buffer larger than 0x%zx bytes",
211       v8::TypedArray::kMaxLength);
212   return ERR_BUFFER_TOO_LARGE(isolate, message);
213 }
214 
ERR_STRING_TOO_LONG(v8::Isolate * isolate)215 inline v8::Local<v8::Value> ERR_STRING_TOO_LONG(v8::Isolate* isolate) {
216   char message[128];
217   snprintf(message, sizeof(message),
218       "Cannot create a string longer than 0x%x characters",
219       v8::String::kMaxLength);
220   return ERR_STRING_TOO_LONG(isolate, message);
221 }
222 
223 #define THROW_AND_RETURN_IF_NOT_BUFFER(env, val, prefix)                     \
224   do {                                                                       \
225     if (!Buffer::HasInstance(val))                                           \
226       return node::THROW_ERR_INVALID_ARG_TYPE(env,                           \
227                                               prefix " must be a buffer");   \
228   } while (0)
229 
230 #define THROW_AND_RETURN_IF_NOT_STRING(env, val, prefix)                     \
231   do {                                                                       \
232     if (!val->IsString())                                                    \
233       return node::THROW_ERR_INVALID_ARG_TYPE(env,                           \
234                                               prefix " must be a string");   \
235   } while (0)
236 
237 namespace errors {
238 
239 class TryCatchScope : public v8::TryCatch {
240  public:
241   enum class CatchMode { kNormal, kFatal };
242 
243   explicit TryCatchScope(Environment* env, CatchMode mode = CatchMode::kNormal)
244       : v8::TryCatch(env->isolate()), env_(env), mode_(mode) {}
245   ~TryCatchScope();
246 
247   // Since the dtor is not virtual we need to make sure no one creates
248   // object of it in the free store that might be held by polymorphic pointers.
249   void* operator new(std::size_t count) = delete;
250   void* operator new[](std::size_t count) = delete;
251   TryCatchScope(TryCatchScope&) = delete;
252   TryCatchScope(TryCatchScope&&) = delete;
253   TryCatchScope operator=(TryCatchScope&) = delete;
254   TryCatchScope operator=(TryCatchScope&&) = delete;
255 
256  private:
257   Environment* env_;
258   CatchMode mode_;
259 };
260 
261 // Trigger the global uncaught exception handler `process._fatalException`
262 // in JS land (which emits the 'uncaughtException' event). If that returns
263 // true, continue program execution, otherwise exit the process.
264 void TriggerUncaughtException(v8::Isolate* isolate,
265                               const v8::TryCatch& try_catch);
266 void TriggerUncaughtException(v8::Isolate* isolate,
267                               v8::Local<v8::Value> error,
268                               v8::Local<v8::Message> message,
269                               bool from_promise = false);
270 
271 const char* errno_string(int errorno);
272 void PerIsolateMessageListener(v8::Local<v8::Message> message,
273                                v8::Local<v8::Value> error);
274 
275 void DecorateErrorStack(Environment* env,
276                         const errors::TryCatchScope& try_catch);
277 }  // namespace errors
278 
279 v8::ModifyCodeGenerationFromStringsResult ModifyCodeGenerationFromStrings(
280     v8::Local<v8::Context> context,
281     v8::Local<v8::Value> source,
282     bool is_code_like);
283 
284 }  // namespace node
285 
286 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
287 
288 #endif  // SRC_NODE_ERRORS_H_
289