lib: hashtable: Prevent recursive calling of callback functions
authorChristoph Niedermaier <cniedermaier@dh-electronics.com>
Fri, 6 Dec 2024 23:04:19 +0000 (00:04 +0100)
committerFabio Estevam <festevam@gmail.com>
Sat, 7 Dec 2024 12:07:45 +0000 (09:07 -0300)
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>
lib/hashtable.c

index e8a59e2..75c263b 100644 (file)
@@ -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;
 }
 
 /*