diff --git a/examples/utest/testcases/kernel/Kconfig b/examples/utest/testcases/kernel/Kconfig index 163e22a1da..ec1054fae8 100644 --- a/examples/utest/testcases/kernel/Kconfig +++ b/examples/utest/testcases/kernel/Kconfig @@ -1,5 +1,9 @@ menu "Kernel Testcase" +config UTEST_OBJECT_TC + bool "object test" + default y + config UTEST_MEMHEAP_TC bool "memheap stability test" default y diff --git a/examples/utest/testcases/kernel/SConscript b/examples/utest/testcases/kernel/SConscript index 820f1ae042..283f1da691 100644 --- a/examples/utest/testcases/kernel/SConscript +++ b/examples/utest/testcases/kernel/SConscript @@ -5,6 +5,9 @@ cwd = GetCurrentDir() src = [] CPPPATH = [cwd] +if GetDepend(['UTEST_OBJECT_TC']): + src += ['object_tc.c'] + if GetDepend(['UTEST_MEMHEAP_TC']): src += ['memheap_tc.c'] diff --git a/examples/utest/testcases/kernel/object_tc.c b/examples/utest/testcases/kernel/object_tc.c new file mode 100644 index 0000000000..156fd8e730 --- /dev/null +++ b/examples/utest/testcases/kernel/object_tc.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-07-18 kurisaW First commit + */ + +#include +#include +#include + +/** + * @brief Test case for verifying object name handling functionality + * + * @note This test suite validates: + * 1. Proper truncation of long object names + * 2. Correct NULL name handling + * 3. Exact length name preservation + * 4. Both static and dynamic object initialization + * 5. Memory safety and boundary conditions + */ + +static void test_object_name_handling(void) +{ + struct rt_object static_obj1; + struct rt_object static_obj2; + struct rt_object static_obj3; + rt_object_t dyn_obj = RT_NULL; + char test_name[RT_NAME_MAX + 5]; + + for (int i = 0; i < sizeof(test_name) - 1; i++) + { + test_name[i] = 'A' + (i % 26); + } + test_name[sizeof(test_name) - 1] = '\0'; + + /* Test 1: Static Object Initialization - Extra Long Name */ + rt_object_init(&static_obj1, RT_Object_Class_Thread, test_name); + uassert_true(rt_strlen(static_obj1.name) <= RT_NAME_MAX - 1); + uassert_true(static_obj1.name[RT_NAME_MAX - 1] == '\0'); + + /* Test 2: Dynamic Object Allocation */ + dyn_obj = rt_object_allocate(RT_Object_Class_Thread, test_name); + uassert_not_null(dyn_obj); + if (dyn_obj) + { + uassert_true(rt_strlen(dyn_obj->name) <= RT_NAME_MAX - 1); + uassert_true(dyn_obj->name[RT_NAME_MAX - 1] == '\0'); + rt_object_delete(dyn_obj); + dyn_obj = RT_NULL; + } + + /* Test 3: NULL Name Handling - Using New Static Object */ + rt_object_init(&static_obj2, RT_Object_Class_Thread, NULL); + uassert_true(static_obj2.name[0] == '\0'); + + /* Test 4: Dynamic Object with NULL Name */ + dyn_obj = rt_object_allocate(RT_Object_Class_Thread, NULL); + uassert_not_null(dyn_obj); + if (dyn_obj) + { + uassert_true(dyn_obj->name[0] == '\0'); + rt_object_delete(dyn_obj); + dyn_obj = RT_NULL; + } + + /* Test 5: Fixed-Length Name - Using Third Static Object */ + char exact_name[RT_NAME_MAX]; + rt_memset(exact_name, 'B', RT_NAME_MAX - 1); + exact_name[RT_NAME_MAX - 1] = '\0'; + + rt_object_init(&static_obj3, RT_Object_Class_Thread, exact_name); + uassert_str_equal(static_obj3.name, exact_name); + + rt_object_detach(&static_obj1); + rt_object_detach(&static_obj2); + rt_object_detach(&static_obj3); +} + +static rt_err_t testcase_init(void) +{ + return RT_EOK; +} + +static rt_err_t testcase_cleanup(void) +{ + return RT_EOK; +} + +static void test_object_suite(void) +{ + UTEST_UNIT_RUN(test_object_name_handling); +} +UTEST_TC_EXPORT(test_object_suite, "testcases.kernel.object_test", testcase_init, testcase_cleanup, 10); diff --git a/src/object.c b/src/object.c index 0ab018f445..03911b98a5 100644 --- a/src/object.c +++ b/src/object.c @@ -355,6 +355,7 @@ void rt_object_init(struct rt_object *object, const char *name) { rt_base_t level; + rt_size_t len; #ifdef RT_DEBUGING_ASSERT struct rt_list_node *node = RT_NULL; #endif /* RT_DEBUGING_ASSERT */ @@ -390,10 +391,20 @@ void rt_object_init(struct rt_object *object, /* set object type to static */ object->type = type | RT_Object_Class_Static; #if RT_NAME_MAX > 0 - rt_strncpy(object->name, name, RT_NAME_MAX); /* copy name */ + if (name) + { + len = rt_strlen(name); + len = len > RT_NAME_MAX - 1 ? RT_NAME_MAX - 1 : len; + rt_memcpy(object->name, name, len); + object->name[len] = '\0'; + } + else + { + object->name[0] = '\0'; + } #else object->name = name; -#endif /* RT_NAME_MAX > 0 */ +#endif RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object)); @@ -461,6 +472,7 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) { struct rt_object *object; rt_base_t level; + rt_size_t len; struct rt_object_information *information; #ifdef RT_USING_MODULE struct rt_dlmodule *module = dlmodule_self(); @@ -491,10 +503,20 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) object->flag = 0; #if RT_NAME_MAX > 0 - rt_strncpy(object->name, name, RT_NAME_MAX - 1); /* copy name */ + if (name) + { + len = rt_strlen(name); + len = len > RT_NAME_MAX - 1 ? RT_NAME_MAX - 1 : len; + rt_memcpy(object->name, name, len); + object->name[len] = '\0'; + } + else + { + object->name[0] = '\0'; + } #else object->name = name; -#endif /* RT_NAME_MAX > 0 */ +#endif RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));