Browse Source

[libc][libdl] Extract name extraction to shared function and fix edge cases

Address code review feedback:
1. Extract path stripping logic into shared dlmodule_extract_name() function
   to avoid code duplication between dlopen() and _dlmodule_set_name().
2. Fix edge case handling for filenames starting with dot (e.g., .hidden).
3. Add proper documentation for the new function.

This ensures consistent module name extraction across all code paths.

Co-authored-by: BernardXiong <1241087+BernardXiong@users.noreply.github.com>
copilot-swe-agent[bot] 17 hours ago
parent
commit
79d62050aa

+ 44 - 13
components/libc/posix/libdl/dlmodule.c

@@ -33,16 +33,28 @@ static struct rt_module_symtab *_rt_module_symtab_end   = RT_NULL;
     #pragma section="RTMSymTab"
 #endif
 
-/* set the name of module */
-static void _dlmodule_set_name(struct rt_dlmodule *module, const char *path)
+/**
+ * @brief  Extract module name from a file path by stripping directory and extension.
+ *
+ * @param  path the file path (e.g., "/mnt/sdcard/apps/clock.so")
+ * @param  name buffer to store the extracted module name
+ * @param  name_size size of the name buffer
+ *
+ * @note   This function extracts the base name without path and extension.
+ *         For example: "/mnt/sdcard/apps/clock.so" -> "clock"
+ *         For hidden files like ".hidden", the entire filename is used.
+ */
+void dlmodule_extract_name(const char *path, char *name, int name_size)
 {
     int size;
-    struct rt_object *object;
-    const char *first, *end, *ptr;
+    const char *first, *end, *ptr, *last_dot;
 
-    object = &(module->parent);
-    ptr   = first = (char *)path;
-    end   = path + rt_strlen(path);
+    RT_ASSERT(path != RT_NULL);
+    RT_ASSERT(name != RT_NULL);
+    RT_ASSERT(name_size > 0);
+
+    ptr = first = path;
+    end = path + rt_strlen(path);
 
     /* find the start of filename (after last '/') */
     while (*ptr != '\0')
@@ -52,25 +64,44 @@ static void _dlmodule_set_name(struct rt_dlmodule *module, const char *path)
         ptr++;
     }
 
-    /* find extension in filename portion only (after last '/') */
+    /* find last extension in filename portion only (after last '/') */
+    last_dot = RT_NULL;
     ptr = first;
     while (*ptr != '\0')
     {
         if (*ptr == '.')
-            end = ptr;
+            last_dot = ptr;
         ptr++;
     }
 
+    /* determine end position for module name */
+    if (last_dot != RT_NULL && last_dot != first)
+    {
+        /* extension found and filename doesn't start with dot */
+        end = last_dot;
+    }
+    /* else: no extension or filename starts with dot, use entire filename */
+
     size = end - first;
     if (size <= 0)
     {
-        /* no extension found, use entire filename */
+        /* edge case: empty filename or only dot(s) */
         size = rt_strlen(first);
     }
-    if (size >= RT_NAME_MAX) size = RT_NAME_MAX - 1;
+    if (size >= name_size)
+        size = name_size - 1;
+
+    rt_strncpy(name, first, size);
+    name[size] = '\0';
+}
+
+/* set the name of module */
+static void _dlmodule_set_name(struct rt_dlmodule *module, const char *path)
+{
+    struct rt_object *object;
 
-    rt_strncpy(object->name, first, size);
-    object->name[size] = '\0';
+    object = &(module->parent);
+    dlmodule_extract_name(path, object->name, RT_NAME_MAX);
 }
 
 #define RT_MODULE_ARG_MAX    8

+ 2 - 0
components/libc/posix/libdl/dlmodule.h

@@ -82,6 +82,8 @@ void dlmodule_exit(int ret_code);
 
 struct rt_dlmodule *dlmodule_find(const char *name);
 
+void dlmodule_extract_name(const char *path, char *name, int name_size);
+
 rt_ubase_t dlmodule_symbol_find(const char *sym_str);
 
 #endif

+ 1 - 35
components/libc/posix/libdl/dlopen.c

@@ -56,41 +56,7 @@ void* dlopen(const char *filename, int flags)
      * This matches the logic in _dlmodule_set_name() so that dlmodule_find()
      * can properly locate already-loaded modules by their stored name.
      */
-    {
-        const char *first, *end, *ptr;
-        int size;
-
-        ptr = first = fullpath;
-        end = fullpath + strlen(fullpath);
-
-        while (*ptr != '\0')
-        {
-            if (*ptr == '/')
-                first = ptr + 1;
-            ptr++;
-        }
-
-        /* find extension in filename portion only (after last '/') */
-        ptr = first;
-        while (*ptr != '\0')
-        {
-            if (*ptr == '.')
-                end = ptr;
-            ptr++;
-        }
-
-        size = end - first;
-        if (size <= 0)
-        {
-            /* no extension found, use entire filename */
-            size = strlen(first);
-        }
-        if (size >= RT_NAME_MAX)
-            size = RT_NAME_MAX - 1;
-
-        rt_strncpy(module_name, first, size);
-        module_name[size] = '\0';
-    }
+    dlmodule_extract_name(fullpath, module_name, RT_NAME_MAX);
 
     rt_enter_critical();