From 4322cebc1764d433b3fce3b3a108252648bf59e7 Mon Sep 17 00:00:00 2001 From: "debing.sun" Date: Mon, 7 Jul 2025 10:12:51 +0800 Subject: [PATCH] Ensure empty error tables in scripts don't crash (#14163) This PR is based on: https://github.com/valkey-io/valkey/pull/2229 When calling the command `EVAL error{} 0`, Redis crashes with the following stack trace. This patch ensures we never leave the `err_info.msg` field null when we fail to extract a proper error message. --------- Signed-off-by: Fusl Signed-off-by: Binbin Co-authored-by: Fusl Co-authored-by: Binbin --- src/script_lua.c | 8 ++++++++ tests/unit/scripting.tcl | 31 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/script_lua.c b/src/script_lua.c index 47fb59683..2e8220743 100644 --- a/src/script_lua.c +++ b/src/script_lua.c @@ -2,9 +2,14 @@ * Copyright (c) 2009-Present, Redis Ltd. * All rights reserved. * + * Copyright (c) 2024-present, Valkey contributors. + * All rights reserved. + * * Licensed under your choice of (a) the Redis Source Available License 2.0 * (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the * GNU Affero General Public License v3 (AGPLv3). + * + * Portions of this file are available under BSD3 terms; see REDISCONTRIBUTIONS for more information. */ #include "script_lua.h" @@ -1580,6 +1585,9 @@ void luaExtractErrorInformation(lua_State *lua, errorInfo *err_info) { lua_getfield(lua, -1, "err"); if (lua_isstring(lua, -1)) { err_info->msg = sdsnew(lua_tostring(lua, -1)); + } else { + /* Ensure we never return a NULL msg. */ + err_info->msg = sdsnew("ERR unknown error"); } lua_pop(lua, 1); diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl index 05a37c00e..921cc2ada 100644 --- a/tests/unit/scripting.tcl +++ b/tests/unit/scripting.tcl @@ -1,3 +1,17 @@ +# +# Copyright (c) 2009-Present, Redis Ltd. +# All rights reserved. +# +# Copyright (c) 2024-present, Valkey contributors. +# All rights reserved. +# +# Licensed under your choice of (a) the Redis Source Available License 2.0 +# (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the +# GNU Affero General Public License v3 (AGPLv3). +# +# Portions of this file are available under BSD3 terms; see REDISCONTRIBUTIONS for more information. +# + foreach is_eval {0 1} { if {$is_eval == 1} { @@ -2447,4 +2461,21 @@ start_server {tags {"scripting"}} { assert { [r memory usage foo] <= $expected_memory}; } } + + test {EVAL - explicit error() call handling} { + # error("simple string error") + assert_error {ERR user_script:1: simple string error script: *} { + r eval "error('simple string error')" 0 + } + + # error({"err": "ERR table error"}) + assert_error {ERR table error script: *} { + r eval "error({err='ERR table error'})" 0 + } + + # error({}) + assert_error {ERR unknown error script: *} { + r eval "error({})" 0 + } + } }