diff options
author | Christoph Niedermaier <cniedermaier@dh-electronics.com> | 2024-12-07 00:04:19 +0100 |
---|---|---|
committer | Fabio Estevam <festevam@gmail.com> | 2024-12-07 09:07:45 -0300 |
commit | 86f58ea539e35b47235dff0dd77ec20fe8894469 (patch) | |
tree | 80caf2023734b0baeac12803e3f95052abeaa1b6 /lib/hashtable.c | |
parent | 489b965564ad73c7a2e8f8743908347775c5df3b (diff) |
lib: hashtable: Prevent recursive calling of callback functions
In case there are two variables which each implement env callback
that performs env_set() on the other variable, the callbacks will
call each other recursively until the stack runs out. Prevent such
a recursion from happening.
Example which triggers this behavior:
static int on_foo(...) { env_set("bar", 0); ... }
static int on_bar(...) { env_set("foo", 0); ... }
U_BOOT_ENV_CALLBACK(foo, on_foo);
U_BOOT_ENV_CALLBACK(bar, on_bar);
Signed-off-by: Christoph Niedermaier <cniedermaier@dh-electronics.com>
Suggested-by: Marek Vasut <marex@denx.de>
Diffstat (limited to 'lib/hashtable.c')
-rw-r--r-- | lib/hashtable.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/lib/hashtable.c b/lib/hashtable.c index e8a59e2dcac..75c263b5053 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -221,11 +221,32 @@ static int do_callback(const struct env_entry *e, const char *name, const char *value, enum env_op op, int flags) { + int ret = 0; + #ifndef CONFIG_XPL_BUILD - if (e->callback) - return e->callback(name, value, op, flags); + static bool in_callback; + + if (!e->callback || in_callback) + return 0; + + /* + * In case there are two variables which each implement env callback + * that performs env_set() on the other variable, the callbacks will + * call each other recursively until the stack runs out. Prevent such + * a recursion from happening. + * + * Example which triggers this behavior: + * static int on_foo(...) { env_set("bar", 0); ... } + * static int on_bar(...) { env_set("foo", 0); ... } + * U_BOOT_ENV_CALLBACK(foo, on_foo); + * U_BOOT_ENV_CALLBACK(bar, on_bar); + */ + in_callback = true; + ret = e->callback(name, value, op, flags); + in_callback = false; #endif - return 0; + + return ret; } /* |