Fix runtime bugs

- fix string leak in `js_printf_internal` on errors
- read `errno` before potential side effects in `js_os_stat`
This commit is contained in:
Charlie Gordon 2024-02-11 12:49:40 +01:00
parent c9e6c56c70
commit 48deab1aeb
2 changed files with 21 additions and 22 deletions

View File

@ -150,7 +150,7 @@ static JSValue js_printf_internal(JSContext *ctx,
uint8_t cbuf[UTF8_CHAR_LEN_MAX+1]; uint8_t cbuf[UTF8_CHAR_LEN_MAX+1];
JSValue res; JSValue res;
DynBuf dbuf; DynBuf dbuf;
const char *fmt_str; const char *fmt_str = NULL;
const uint8_t *fmt, *fmt_end; const uint8_t *fmt, *fmt_end;
const uint8_t *p; const uint8_t *p;
char *q; char *q;
@ -251,7 +251,7 @@ static JSValue js_printf_internal(JSContext *ctx,
string_arg = JS_ToCString(ctx, argv[i++]); string_arg = JS_ToCString(ctx, argv[i++]);
if (!string_arg) if (!string_arg)
goto fail; goto fail;
int32_arg = unicode_from_utf8((uint8_t *)string_arg, UTF8_CHAR_LEN_MAX, &p); int32_arg = unicode_from_utf8((const uint8_t *)string_arg, UTF8_CHAR_LEN_MAX, &p);
JS_FreeCString(ctx, string_arg); JS_FreeCString(ctx, string_arg);
} else { } else {
if (JS_ToInt32(ctx, &int32_arg, argv[i++])) if (JS_ToInt32(ctx, &int32_arg, argv[i++]))
@ -355,6 +355,7 @@ static JSValue js_printf_internal(JSContext *ctx,
return res; return res;
fail: fail:
JS_FreeCString(ctx, fmt_str);
dbuf_free(&dbuf); dbuf_free(&dbuf);
return JS_EXCEPTION; return JS_EXCEPTION;
} }
@ -1638,7 +1639,7 @@ static JSValue js_os_seek(JSContext *ctx, JSValueConst this_val,
} }
static JSValue js_os_read_write(JSContext *ctx, JSValueConst this_val, static JSValue js_os_read_write(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int magic) int argc, JSValueConst *argv, int magic)
{ {
int fd; int fd;
uint64_t pos, len; uint64_t pos, len;
@ -1779,7 +1780,7 @@ static JSValue js_os_ttySetRaw(JSContext *ctx, JSValueConst this_val,
#endif /* !_WIN32 */ #endif /* !_WIN32 */
static JSValue js_os_remove(JSContext *ctx, JSValueConst this_val, static JSValue js_os_remove(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv) int argc, JSValueConst *argv)
{ {
const char *filename; const char *filename;
int ret; int ret;
@ -2532,12 +2533,14 @@ static JSValue js_os_stat(JSContext *ctx, JSValueConst this_val,
else else
res = stat(path, &st); res = stat(path, &st);
#endif #endif
if (res < 0)
err = errno;
else
err = 0;
JS_FreeCString(ctx, path); JS_FreeCString(ctx, path);
if (res < 0) { if (res < 0) {
err = errno;
obj = JS_NULL; obj = JS_NULL;
} else { } else {
err = 0;
obj = JS_NewObject(ctx); obj = JS_NewObject(ctx);
if (JS_IsException(obj)) if (JS_IsException(obj))
return JS_EXCEPTION; return JS_EXCEPTION;
@ -2648,7 +2651,7 @@ static JSValue js_os_utimes(JSContext *ctx, JSValueConst this_val,
/* sleep(delay_ms) */ /* sleep(delay_ms) */
static JSValue js_os_sleep(JSContext *ctx, JSValueConst this_val, static JSValue js_os_sleep(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv) int argc, JSValueConst *argv)
{ {
int64_t delay; int64_t delay;
int ret; int ret;
@ -2712,7 +2715,7 @@ static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val,
#if !defined(_WIN32) #if !defined(_WIN32)
static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val, static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv) int argc, JSValueConst *argv)
{ {
const char *target, *linkpath; const char *target, *linkpath;
int err; int err;
@ -3763,7 +3766,7 @@ JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name)
/**********************************************************/ /**********************************************************/
static JSValue js_print(JSContext *ctx, JSValueConst this_val, static JSValue js_print(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv) int argc, JSValueConst *argv)
{ {
int i; int i;
const char *str; const char *str;

View File

@ -598,7 +598,7 @@ typedef struct JSFunctionBytecode {
uint8_t backtrace_barrier : 1; /* stop backtrace on this function */ uint8_t backtrace_barrier : 1; /* stop backtrace on this function */
uint8_t read_only_bytecode : 1; uint8_t read_only_bytecode : 1;
uint8_t is_direct_or_indirect_eval : 1; /* used by JS_GetScriptOrModuleName() */ uint8_t is_direct_or_indirect_eval : 1; /* used by JS_GetScriptOrModuleName() */
/* XXX: 4 bits available */ /* XXX: 10 bits available */
uint8_t *byte_code_buf; /* (self pointer) */ uint8_t *byte_code_buf; /* (self pointer) */
int byte_code_len; int byte_code_len;
JSAtom func_name; JSAtom func_name;
@ -1042,13 +1042,11 @@ static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
JSValueConst val, int flags, int scope_idx); JSValueConst val, int flags, int scope_idx);
JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...); JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
static __maybe_unused void JS_DumpAtoms(JSRuntime *rt); static __maybe_unused void JS_DumpAtoms(JSRuntime *rt);
static __maybe_unused void JS_DumpString(JSRuntime *rt, static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p);
const JSString *p);
static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt); static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);
static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p); static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);
static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p); static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);
static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, JSValueConst val);
JSValueConst val);
static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val); static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);
static __maybe_unused void JS_PrintValue(JSContext *ctx, static __maybe_unused void JS_PrintValue(JSContext *ctx,
const char *str, const char *str,
@ -1057,14 +1055,11 @@ static __maybe_unused void JS_DumpShapes(JSRuntime *rt);
static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val, static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int magic); int argc, JSValueConst *argv, int magic);
static void js_array_finalizer(JSRuntime *rt, JSValue val); static void js_array_finalizer(JSRuntime *rt, JSValue val);
static void js_array_mark(JSRuntime *rt, JSValueConst val, static void js_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
JS_MarkFunc *mark_func);
static void js_object_data_finalizer(JSRuntime *rt, JSValue val); static void js_object_data_finalizer(JSRuntime *rt, JSValue val);
static void js_object_data_mark(JSRuntime *rt, JSValueConst val, static void js_object_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
JS_MarkFunc *mark_func);
static void js_c_function_finalizer(JSRuntime *rt, JSValue val); static void js_c_function_finalizer(JSRuntime *rt, JSValue val);
static void js_c_function_mark(JSRuntime *rt, JSValueConst val, static void js_c_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
JS_MarkFunc *mark_func);
static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val); static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val);
static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val, static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,
JS_MarkFunc *mark_func); JS_MarkFunc *mark_func);
@ -4190,7 +4185,7 @@ static JSValue JS_ConcatString1(JSContext *ctx,
return JS_MKPTR(JS_TAG_STRING, p); return JS_MKPTR(JS_TAG_STRING, p);
} }
/* op1 and op2 are converted to strings. For convience, op1 or op2 = /* op1 and op2 are converted to strings. For convenience, op1 or op2 =
JS_EXCEPTION are accepted and return JS_EXCEPTION. */ JS_EXCEPTION are accepted and return JS_EXCEPTION. */
static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2) static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2)
{ {
@ -17157,6 +17152,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
op1 = sp[-1]; op1 = sp[-1];
pc += 4; pc += 4;
/* quick and dirty test for JS_TAG_INT, JS_TAG_BOOL, JS_TAG_NULL and JS_TAG_UNDEFINED */
if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) { if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {
res = JS_VALUE_GET_INT(op1); res = JS_VALUE_GET_INT(op1);
} else { } else {
@ -50589,7 +50585,7 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
#ifdef CONFIG_BIGNUM #ifdef CONFIG_BIGNUM
case JS_TAG_BIG_DECIMAL: case JS_TAG_BIG_DECIMAL:
val = JS_ToStringFree(ctx, val); val = JS_ToStringFree(ctx, val);
if (JS_IsException(val)) if (JS_IsException(val))
break; break;
goto redo; goto redo;
#endif #endif