1 /*
2  *  Error, fatal, and panic handling.
3  */
4 
5 #include "duk_internal.h"
6 
7 #define DUK__ERRFMT_BUFSIZE  256  /* size for formatting buffers */
8 
9 #if defined(DUK_USE_VERBOSE_ERRORS)
10 
duk_err_handle_error_fmt(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * fmt,...)11 DUK_INTERNAL void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...) {
12 	va_list ap;
13 	char msg[DUK__ERRFMT_BUFSIZE];
14 	va_start(ap, fmt);
15 	(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
16 	msg[sizeof(msg) - 1] = (char) 0;
17 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
18 	va_end(ap);  /* dead code, but ensures portability (see Linux man page notes) */
19 }
20 
duk_err_handle_error(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * msg)21 DUK_INTERNAL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {
22 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
23 }
24 
25 #else  /* DUK_USE_VERBOSE_ERRORS */
26 
duk_err_handle_error(duk_hthread * thr,duk_errcode_t code)27 DUK_INTERNAL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {
28 	duk_err_create_and_throw(thr, code);
29 }
30 
31 #endif  /* DUK_USE_VERBOSE_ERRORS */
32 
33 /*
34  *  Error throwing helpers
35  */
36 
37 #if defined(DUK_USE_VERBOSE_ERRORS)
38 #if defined(DUK_USE_PARANOID_ERRORS)
duk_err_require_type_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t index,const char * expect_name)39 DUK_INTERNAL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index, const char *expect_name) {
40 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
41 	                   expect_name, duk_get_type_name((duk_context *) thr, index), (long) index);
42 }
43 #else
duk_err_require_type_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t index,const char * expect_name)44 DUK_INTERNAL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index, const char *expect_name) {
45 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
46 	                   expect_name, duk_push_string_readable((duk_context *) thr, index), (long) index);
47 }
48 #endif
duk_err_range(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)49 DUK_INTERNAL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
50 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, message);
51 }
duk_err_api_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t index)52 DUK_INTERNAL void duk_err_api_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index) {
53 	DUK_ERROR_RAW_FMT1(thr, filename, linenumber, DUK_ERR_API_ERROR, "invalid stack index %ld", (long) (index));
54 }
duk_err_api(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)55 DUK_INTERNAL void duk_err_api(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
56 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_API_ERROR, message);
57 }
duk_err_unimplemented_defmsg(duk_hthread * thr,const char * filename,duk_int_t linenumber)58 DUK_INTERNAL void duk_err_unimplemented_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
59 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_UNIMPLEMENTED_ERROR, DUK_STR_UNIMPLEMENTED);
60 }
61 #if !defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
duk_err_unsupported_defmsg(duk_hthread * thr,const char * filename,duk_int_t linenumber)62 DUK_INTERNAL void duk_err_unsupported_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
63 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_UNSUPPORTED_ERROR, DUK_STR_UNSUPPORTED);
64 }
65 #endif
duk_err_internal_defmsg(duk_hthread * thr,const char * filename,duk_int_t linenumber)66 DUK_INTERNAL void duk_err_internal_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
67 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_INTERNAL_ERROR, DUK_STR_INTERNAL_ERROR);
68 }
duk_err_internal(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)69 DUK_INTERNAL void duk_err_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
70 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_INTERNAL_ERROR, message);
71 }
duk_err_alloc(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)72 DUK_INTERNAL void duk_err_alloc(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
73 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ALLOC_ERROR, message);
74 }
75 #else
76 /* The file/line arguments are NULL and 0, they're ignored by DUK_ERROR_RAW()
77  * when non-verbose errors are used.
78  */
duk_err_type(duk_hthread * thr)79 DUK_INTERNAL void duk_err_type(duk_hthread *thr) {
80 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_TYPE_ERROR, NULL);
81 }
duk_err_api(duk_hthread * thr)82 DUK_INTERNAL void duk_err_api(duk_hthread *thr) {
83 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_API_ERROR, NULL);
84 }
duk_err_range(duk_hthread * thr)85 DUK_INTERNAL void duk_err_range(duk_hthread *thr) {
86 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_RANGE_ERROR, NULL);
87 }
duk_err_syntax(duk_hthread * thr)88 DUK_INTERNAL void duk_err_syntax(duk_hthread *thr) {
89 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_SYNTAX_ERROR, NULL);
90 }
duk_err_unimplemented(duk_hthread * thr)91 DUK_INTERNAL void duk_err_unimplemented(duk_hthread *thr) {
92 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_UNIMPLEMENTED_ERROR, NULL);
93 }
duk_err_unsupported(duk_hthread * thr)94 DUK_INTERNAL void duk_err_unsupported(duk_hthread *thr) {
95 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_UNSUPPORTED_ERROR, NULL);
96 }
duk_err_internal(duk_hthread * thr)97 DUK_INTERNAL void duk_err_internal(duk_hthread *thr) {
98 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_INTERNAL_ERROR, NULL);
99 }
duk_err_alloc(duk_hthread * thr)100 DUK_INTERNAL void duk_err_alloc(duk_hthread *thr) {
101 	DUK_ERROR_RAW(thr, NULL, thr, DUK_ERR_ALLOC_ERROR, NULL);
102 }
103 #endif
104 
105 /*
106  *  Default fatal error handler
107  */
108 
duk_default_fatal_handler(duk_context * ctx,duk_errcode_t code,const char * msg)109 DUK_INTERNAL void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg) {
110 	DUK_UNREF(ctx);
111 #if defined(DUK_USE_FILE_IO)
112 	DUK_FPRINTF(DUK_STDERR, "FATAL %ld: %s\n", (long) code, (const char *) (msg ? msg : "null"));
113 	DUK_FFLUSH(DUK_STDERR);
114 #else
115 	/* omit print */
116 #endif
117 	DUK_D(DUK_DPRINT("default fatal handler called, code %ld -> calling DUK_PANIC()", (long) code));
118 	DUK_PANIC(code, msg);
119 	DUK_UNREACHABLE();
120 }
121 
122 /*
123  *  Default panic handler
124  */
125 
126 #if !defined(DUK_USE_PANIC_HANDLER)
duk_default_panic_handler(duk_errcode_t code,const char * msg)127 DUK_INTERNAL void duk_default_panic_handler(duk_errcode_t code, const char *msg) {
128 #if defined(DUK_USE_FILE_IO)
129 	DUK_FPRINTF(DUK_STDERR, "PANIC %ld: %s ("
130 #if defined(DUK_USE_PANIC_ABORT)
131 	            "calling abort"
132 #elif defined(DUK_USE_PANIC_EXIT)
133 	            "calling exit"
134 #elif defined(DUK_USE_PANIC_SEGFAULT)
135 	            "segfaulting on purpose"
136 #else
137 #error no DUK_USE_PANIC_xxx macro defined
138 #endif
139 	            ")\n", (long) code, (const char *) (msg ? msg : "null"));
140 	DUK_FFLUSH(DUK_STDERR);
141 #else
142 	/* omit print */
143 	DUK_UNREF(code);
144 	DUK_UNREF(msg);
145 #endif
146 
147 #if defined(DUK_USE_PANIC_ABORT)
148 	DUK_ABORT();
149 #elif defined(DUK_USE_PANIC_EXIT)
150 	DUK_EXIT(-1);
151 #elif defined(DUK_USE_PANIC_SEGFAULT)
152 	/* exit() afterwards to satisfy "noreturn" */
153 	DUK_CAUSE_SEGFAULT();  /* SCANBUILD: "Dereference of null pointer", normal */
154 	DUK_EXIT(-1);
155 #else
156 #error no DUK_USE_PANIC_xxx macro defined
157 #endif
158 
159 	DUK_UNREACHABLE();
160 }
161 #endif  /* !DUK_USE_PANIC_HANDLER */
162 
163 #undef DUK__ERRFMT_BUFSIZE
164