diff --git a/.github/utest/kernel/object.cfg b/.github/utest/kernel/object.cfg new file mode 100644 index 0000000000..d522d6a637 --- /dev/null +++ b/.github/utest/kernel/object.cfg @@ -0,0 +1,6 @@ +CONFIG_UTEST_OBJECT_TC=y + +# dependencies +CONFIG_RT_USING_CI_ACTION=y +CONFIG_RT_USING_DEVICE=y +CONFIG_RT_USING_SEMAPHORE=y diff --git a/.github/workflows/utest_auto_run.yml b/.github/workflows/utest_auto_run.yml index 1a3660f8d0..d8827b8ecf 100644 --- a/.github/workflows/utest_auto_run.yml +++ b/.github/workflows/utest_auto_run.yml @@ -47,6 +47,9 @@ jobs: config_file: - "default.cfg" + # kernel + # - "kernel/object.cfg" + # cpp11 # - "cpp11/cpp11.cfg" diff --git a/bsp/qemu-vexpress-a9/.config b/bsp/qemu-vexpress-a9/.config index 8953cba090..ffc470a12c 100644 --- a/bsp/qemu-vexpress-a9/.config +++ b/bsp/qemu-vexpress-a9/.config @@ -108,7 +108,7 @@ # CONFIG_RT_UTEST_TC_USING_KLIBC is not set # end of klibc options -CONFIG_RT_NAME_MAX=8 +CONFIG_RT_NAME_MAX=16 # CONFIG_RT_USING_ARCH_DATA_TYPE is not set # CONFIG_RT_USING_NANO is not set # CONFIG_RT_USING_SMART is not set @@ -496,6 +496,7 @@ CONFIG_RT_PAGE_MAX_ORDER=11 # CONFIG_PKG_USING_FREEMODBUS is not set # CONFIG_PKG_USING_NANOPB is not set # CONFIG_PKG_USING_WIFI_HOST_DRIVER is not set +# CONFIG_PKG_USING_ESP_HOSTED is not set # # Wi-Fi @@ -603,6 +604,7 @@ CONFIG_RT_PAGE_MAX_ORDER=11 # CONFIG_PKG_USING_QMODBUS is not set # CONFIG_PKG_USING_PNET is not set # CONFIG_PKG_USING_OPENER is not set +# CONFIG_PKG_USING_FREEMQTT is not set # end of IoT - internet of things # @@ -831,6 +833,7 @@ CONFIG_RT_PAGE_MAX_ORDER=11 # CONFIG_PKG_USING_RMP is not set # CONFIG_PKG_USING_R_RHEALSTONE is not set # CONFIG_PKG_USING_HEARTBEAT is not set +# CONFIG_PKG_USING_MICRO_ROS_RTTHREAD_PACKAGE is not set # end of system packages # @@ -954,6 +957,8 @@ CONFIG_RT_PAGE_MAX_ORDER=11 # # HC32 DDL Drivers # +# CONFIG_PKG_USING_HC32F4_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_HC32F4_SERIES_DRIVER is not set # end of HC32 DDL Drivers # @@ -967,6 +972,21 @@ CONFIG_RT_PAGE_MAX_ORDER=11 # CONFIG_PKG_USING_NXP_IMX6UL_DRIVER is not set # CONFIG_PKG_USING_NXP_IMXRT_DRIVER is not set # end of NXP HAL & SDK Drivers + +# +# NUVOTON Drivers +# +# CONFIG_PKG_USING_NUVOTON_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_NUVOTON_SERIES_DRIVER is not set +# CONFIG_PKG_USING_NUVOTON_ARM926_LIB is not set +# end of NUVOTON Drivers + +# +# GD32 Drivers +# +# CONFIG_PKG_USING_GD32_ARM_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_GD32_ARM_SERIES_DRIVER is not set +# end of GD32 Drivers # end of HAL & SDK Drivers # diff --git a/bsp/qemu-vexpress-a9/rtconfig.h b/bsp/qemu-vexpress-a9/rtconfig.h index 13a5d47e73..8125bcebd1 100644 --- a/bsp/qemu-vexpress-a9/rtconfig.h +++ b/bsp/qemu-vexpress-a9/rtconfig.h @@ -61,7 +61,7 @@ /* end of rt_strnlen options */ /* end of klibc options */ -#define RT_NAME_MAX 8 +#define RT_NAME_MAX 16 #define RT_CPUS_NR 1 #define RT_ALIGN_SIZE 8 #define RT_THREAD_PRIORITY_256 @@ -410,6 +410,14 @@ /* NXP HAL & SDK Drivers */ /* end of NXP HAL & SDK Drivers */ + +/* NUVOTON Drivers */ + +/* end of NUVOTON Drivers */ + +/* GD32 Drivers */ + +/* end of GD32 Drivers */ /* end of HAL & SDK Drivers */ /* sensors drivers */ diff --git a/examples/utest/testcases/kernel/Kconfig b/examples/utest/testcases/kernel/Kconfig index ec1054fae8..278de61a29 100644 --- a/examples/utest/testcases/kernel/Kconfig +++ b/examples/utest/testcases/kernel/Kconfig @@ -1,9 +1,5 @@ menu "Kernel Testcase" -config UTEST_OBJECT_TC - bool "object test" - default y - config UTEST_MEMHEAP_TC bool "memheap stability test" default y @@ -14,6 +10,12 @@ config UTEST_SMALL_MEM_TC default y depends on RT_USING_SMALL_MEM +config UTEST_OBJECT_TC + select RT_USING_DEVICE + select RT_USING_SEMAPHORE + bool "object test" + default n + config UTEST_SLAB_TC bool "slab test" default n diff --git a/examples/utest/testcases/kernel/object_tc.c b/examples/utest/testcases/kernel/object_tc.c index 156fd8e730..2afeda3492 100644 --- a/examples/utest/testcases/kernel/object_tc.c +++ b/examples/utest/testcases/kernel/object_tc.c @@ -13,75 +13,293 @@ #include /** - * @brief Test case for verifying object name handling functionality + * @brief Comprehensive test suite for RT-Thread object system * * @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 + * 1. Object name handling (truncation, NULL, exact length) + * 2. Static and dynamic object initialization + * 3. Object finding functionality (rt_object_find, rt_thread_find, rt_device_find) + * 4. Object information and enumeration + * 5. Type checking and system object detection + * 6. Memory safety and boundary conditions */ +/* Define TEST_RT_NAME_MAX for testing purposes */ +#define TEST_RT_NAME_MAX RT_NAME_MAX + +/* Global counter for unique object names */ +static rt_uint32_t name_counter = 0; + +/* Generate unique name to avoid conflicts, respecting TEST_RT_NAME_MAX */ +static rt_err_t generate_unique_name(char *buf, rt_size_t size, const char *prefix) +{ + if (!buf || !prefix || size < TEST_RT_NAME_MAX) + return -RT_EINVAL; + + for (int i = 0; i < 1000; i++) /* Limit attempts to prevent infinite loop */ + { + rt_snprintf(buf, size, "%s%d", prefix, name_counter++); + rt_size_t len = rt_strlen(buf); + if (len >= TEST_RT_NAME_MAX) + { + buf[TEST_RT_NAME_MAX - 1] = '\0'; + len = TEST_RT_NAME_MAX - 1; + } + + /* Check if name (or truncated name) is unique */ + if (rt_object_find(buf, RT_Object_Class_Unknown) == RT_NULL && + rt_thread_find(buf) == RT_NULL && + rt_device_find(buf) == RT_NULL) + { + return RT_EOK; + } + } + return -RT_ENOMEM; +} + static void test_object_name_handling(void) { - struct rt_object static_obj1; - struct rt_object static_obj2; - struct rt_object static_obj3; + struct rt_object static_obj1, static_obj2, static_obj3; rt_object_t dyn_obj = RT_NULL; - char test_name[RT_NAME_MAX + 5]; + char test_name[TEST_RT_NAME_MAX]; + char unique_name[TEST_RT_NAME_MAX]; - for (int i = 0; i < sizeof(test_name) - 1; i++) - { - test_name[i] = 'A' + (i % 26); - } - test_name[sizeof(test_name) - 1] = '\0'; + /* Prepare a test name within TEST_RT_NAME_MAX */ + rt_memset(test_name, 'A', TEST_RT_NAME_MAX - 1); + test_name[TEST_RT_NAME_MAX - 1] = '\0'; - /* Test 1: Static Object Initialization - Extra Long Name */ + /* Test 1: Static Object with Name Within TEST_RT_NAME_MAX */ + uassert_true(generate_unique_name(unique_name, TEST_RT_NAME_MAX, "long") == RT_EOK); 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'); + uassert_true(rt_strlen(static_obj1.name) <= TEST_RT_NAME_MAX - 1); + uassert_true(static_obj1.name[TEST_RT_NAME_MAX - 1] == '\0'); + uassert_true(rt_strncmp(static_obj1.name, test_name, TEST_RT_NAME_MAX - 1) == 0); + uassert_true(rt_object_is_systemobject(&static_obj1)); + rt_object_detach(&static_obj1); - /* Test 2: Dynamic Object Allocation */ + /* Test 2: Dynamic Object with Name Within TEST_RT_NAME_MAX */ + uassert_true(generate_unique_name(unique_name, TEST_RT_NAME_MAX, "dyn") == RT_EOK); 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; - } + uassert_true(rt_strlen(dyn_obj->name) <= TEST_RT_NAME_MAX - 1); + uassert_true(dyn_obj->name[TEST_RT_NAME_MAX - 1] == '\0'); + uassert_true(rt_strncmp(dyn_obj->name, test_name, TEST_RT_NAME_MAX - 1) == 0); + uassert_false(rt_object_is_systemobject(dyn_obj)); + rt_object_delete(dyn_obj); - /* Test 3: NULL Name Handling - Using New Static Object */ + /* Test 3: NULL Name Handling */ + uassert_true(generate_unique_name(unique_name, TEST_RT_NAME_MAX, "null") == RT_EOK); rt_object_init(&static_obj2, RT_Object_Class_Thread, NULL); uassert_true(static_obj2.name[0] == '\0'); + rt_object_detach(&static_obj2); - /* Test 4: Dynamic Object with NULL Name */ + uassert_true(generate_unique_name(unique_name, TEST_RT_NAME_MAX, "dynull") == RT_EOK); 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'; + uassert_true(dyn_obj->name[0] == '\0'); + rt_object_delete(dyn_obj); + /* Test 4: Exact Length Name */ + char exact_name[TEST_RT_NAME_MAX]; + rt_memset(exact_name, 'B', TEST_RT_NAME_MAX - 1); + exact_name[TEST_RT_NAME_MAX - 1] = '\0'; + uassert_true(generate_unique_name(unique_name, TEST_RT_NAME_MAX, "exact") == RT_EOK); 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 void test_object_find_operations(void) +{ + rt_object_t found; + rt_thread_t found_thread; + rt_device_t found_device; + char name[TEST_RT_NAME_MAX]; + rt_err_t ret; + + /* Scenario 1: Object Name Within TEST_RT_NAME_MAX */ + /* Test 1.1: Find static thread object with rt_object_find */ + struct rt_object static_obj; + uassert_true(generate_unique_name(name, TEST_RT_NAME_MAX, "sobj") == RT_EOK); + rt_object_init(&static_obj, RT_Object_Class_Thread, name); + found = rt_object_find(name, RT_Object_Class_Thread); + uassert_not_null(found); + uassert_ptr_equal(found, &static_obj); + uassert_str_equal(found->name, name); + rt_object_detach(&static_obj); + + /* Test 1.2: Find thread object with rt_thread_find */ + uassert_true(generate_unique_name(name, TEST_RT_NAME_MAX, "thr") == RT_EOK); + rt_thread_t thread = rt_thread_create(name, RT_NULL, RT_NULL, 1024, 20, 10); + uassert_not_null(thread); + found_thread = rt_thread_find(name); + uassert_not_null(found_thread); + uassert_ptr_equal(found_thread, thread); + uassert_str_equal(found_thread->parent.name, name); + rt_thread_delete(thread); + +#ifdef RT_USING_DEVICE + /* Test 1.3: Find device object with rt_device_find */ + struct rt_device device; + uassert_true(generate_unique_name(name, TEST_RT_NAME_MAX, "dev") == RT_EOK); + ret = rt_device_register(&device, name, RT_DEVICE_FLAG_RDONLY); + uassert_int_equal(ret, RT_EOK); + found_device = rt_device_find(name); + uassert_not_null(found_device); + uassert_ptr_equal(found_device, &device); + uassert_str_equal(found_device->parent.name, name); + rt_device_unregister(&device); +#endif + + /* Test 2: Same Prefix Within TEST_RT_NAME_MAX */ +#ifdef RT_USING_DEVICE + struct rt_device dev1, dev2; + char name1[TEST_RT_NAME_MAX] = "norflash1"; + char name2[TEST_RT_NAME_MAX] = "norflash2"; + ret = rt_device_register(&dev1, name1, RT_DEVICE_FLAG_RDONLY); + uassert_int_equal(ret, RT_EOK); + ret = rt_device_register(&dev2, name2, RT_DEVICE_FLAG_RDONLY); + uassert_int_equal(ret, RT_EOK); /* Expect success if RT-Thread allows distinct names */ + found_device = rt_device_find(name1); + uassert_not_null(found_device); + uassert_ptr_equal(found_device, &dev1); + uassert_str_equal(found_device->parent.name, name1); + found_device = rt_device_find(name2); + uassert_not_null(found_device); + uassert_ptr_equal(found_device, &dev2); + uassert_str_equal(found_device->parent.name, name2); + rt_device_unregister(&dev1); + rt_device_unregister(&dev2); +#endif + + /* Test 3: Find non-existent object */ + const char *nonexist_name = "nonexist"; + uassert_true(rt_strlen(nonexist_name) <= TEST_RT_NAME_MAX - 1); + found = rt_object_find(nonexist_name, RT_Object_Class_Thread); + uassert_null(found); + + /* Test 4: Find with NULL name */ + found = rt_object_find(NULL, RT_Object_Class_Thread); + uassert_null(found); + found_thread = rt_thread_find(NULL); + uassert_null(found_thread); + +#ifdef RT_USING_DEVICE + found_device = rt_device_find(NULL); + uassert_null(found_device); +#endif +} + +static void test_object_info_enumeration(void) +{ + struct rt_object static_objs[3]; + rt_object_t dyn_objs[2] = {RT_NULL, RT_NULL}; + char names[5][TEST_RT_NAME_MAX]; + + /* Generate unique names */ + for (int i = 0; i < 5; i++) + { + uassert_true(generate_unique_name(names[i], TEST_RT_NAME_MAX, "enum") == RT_EOK); + } + + /* Create test objects */ + for (int i = 0; i < 3; i++) + { + rt_object_init(&static_objs[i], RT_Object_Class_Thread, names[i]); + } + for (int i = 0; i < 2; i++) + { + dyn_objs[i] = rt_object_allocate(RT_Object_Class_Thread, names[i + 3]); + uassert_not_null(dyn_objs[i]); + } + + /* Test 1: Get object information */ + struct rt_object_information *info = rt_object_get_information(RT_Object_Class_Thread); + uassert_not_null(info); + uassert_int_equal(info->type, RT_Object_Class_Thread); + + /* Test 2: Get object count */ + int count = rt_object_get_length(RT_Object_Class_Thread); + uassert_true(count >= 5); + + /* Test 3: Get object pointers with sufficient buffer */ + rt_object_t *objects = (rt_object_t *)rt_malloc((count + 2) * sizeof(rt_object_t)); + uassert_not_null(objects); + int ret = rt_object_get_pointers(RT_Object_Class_Thread, objects, count + 2); + uassert_int_equal(ret, count); + int found_count = 0; + for (int i = 0; i < ret; i++) + { + for (int j = 0; j < 3; j++) + if (objects[i] == &static_objs[j]) found_count++; + for (int j = 0; j < 2; j++) + if (objects[i] == dyn_objs[j]) found_count++; + } + uassert_int_equal(found_count, 5); + rt_free(objects); + + /* Test 4: Get object pointers with small buffer */ + rt_object_t one_object[1]; + ret = rt_object_get_pointers(RT_Object_Class_Thread, one_object, 1); + uassert_true(ret <= 1); + + /* Test 5: Empty container (Semaphore) */ +#ifdef RT_USING_SEMAPHORE + int empty_count = rt_object_get_length(RT_Object_Class_Semaphore); + uassert_true(empty_count >= 0); +#endif + + /* Cleanup */ + for (int i = 0; i < 3; i++) + rt_object_detach(&static_objs[i]); + for (int i = 0; i < 2; i++) + if (dyn_objs[i]) rt_object_delete(dyn_objs[i]); +} + +static void test_object_type_handling(void) +{ + struct rt_object obj; + char name[TEST_RT_NAME_MAX]; + uassert_true(generate_unique_name(name, TEST_RT_NAME_MAX, "typ") == RT_EOK); + rt_object_init(&obj, RT_Object_Class_Thread, name); + + /* Test 1: Get object type */ + uassert_int_equal(rt_object_get_type(&obj), RT_Object_Class_Thread); + + /* Test 2: Check system object */ + uassert_true(rt_object_is_systemobject(&obj)); + + /* Test 3: Get name with sufficient buffer */ + char name_buf[TEST_RT_NAME_MAX]; + rt_err_t ret = rt_object_get_name(&obj, name_buf, sizeof(name_buf)); + uassert_int_equal(ret, RT_EOK); + uassert_str_equal(name_buf, name); + + /* Test 4: Get name with small buffer */ + char small_buf[4] = {0}; + ret = rt_object_get_name(&obj, small_buf, sizeof(small_buf)); + uassert_int_equal(ret, RT_EOK); + uassert_true(rt_strncmp(small_buf, name, sizeof(small_buf) - 1) == 0); + uassert_true(small_buf[sizeof(small_buf) - 1] == '\0'); + + /* Test 5: Get name with invalid parameters */ + ret = rt_object_get_name(RT_NULL, name_buf, sizeof(name_buf)); + uassert_int_equal(ret, -RT_EINVAL); + ret = rt_object_get_name(&obj, NULL, sizeof(name_buf)); + uassert_int_equal(ret, -RT_EINVAL); + ret = rt_object_get_name(&obj, name_buf, 0); + uassert_int_equal(ret, -RT_EINVAL); + + rt_object_detach(&obj); +} + static rt_err_t testcase_init(void) { + if (!rt_scheduler_is_available()) + { + return -RT_ERROR; + } + name_counter = 0; return RT_EOK; } @@ -92,6 +310,13 @@ static rt_err_t testcase_cleanup(void) static void test_object_suite(void) { +#ifdef RT_NAME_MAX < 10 + rt_kprintf("Error: Please increase \'RT_NAME_MAX\' to be greater than 10.\n"); + return; +#endif UTEST_UNIT_RUN(test_object_name_handling); + UTEST_UNIT_RUN(test_object_find_operations); + UTEST_UNIT_RUN(test_object_info_enumeration); + UTEST_UNIT_RUN(test_object_type_handling); } -UTEST_TC_EXPORT(test_object_suite, "testcases.kernel.object_test", testcase_init, testcase_cleanup, 10); +UTEST_TC_EXPORT(test_object_suite, "testcases.kernel.object_test", testcase_init, testcase_cleanup, 20); \ No newline at end of file diff --git a/src/klibc/utest/TC_rt_memcmp.c b/src/klibc/utest/TC_rt_memcmp.c index e8baf556ac..45d4d756cc 100644 --- a/src/klibc/utest/TC_rt_memcmp.c +++ b/src/klibc/utest/TC_rt_memcmp.c @@ -121,7 +121,7 @@ static void TC_rt_memcmp_partial_match(void) uassert_int_not_equal(rt_memcmp(arr1, arr2, sizeof(arr1)), 0); } -#define LARGE_ARRAY_SIZE 1000 +#define LARGE_ARRAY_SIZE 500 static void TC_rt_memcmp_large_array(void) { diff --git a/src/object.c b/src/object.c index 2452001f34..f924f37bc9 100644 --- a/src/object.c +++ b/src/object.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2025, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -29,6 +29,10 @@ #include #endif +#define DBG_TAG "kernel.obj" +#define DBG_LVL DBG_ERROR +#include + struct rt_custom_object { struct rt_object parent; @@ -355,7 +359,7 @@ void rt_object_init(struct rt_object *object, const char *name) { rt_base_t level; - rt_size_t len; + rt_size_t obj_name_len; #ifdef RT_DEBUGING_ASSERT struct rt_list_node *node = RT_NULL; #endif /* RT_DEBUGING_ASSERT */ @@ -393,10 +397,14 @@ void rt_object_init(struct rt_object *object, #if RT_NAME_MAX > 0 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'; + obj_name_len = rt_strlen(name); + if(obj_name_len > RT_NAME_MAX - 1) + { + LOG_E("Object name %s exceeds RT_NAME_MAX=%d, consider increasing RT_NAME_MAX.", name, RT_NAME_MAX); + RT_ASSERT(obj_name_len <= RT_NAME_MAX - 1); + } + rt_memcpy(object->name, name, obj_name_len); + object->name[obj_name_len] = '\0'; } else { @@ -472,7 +480,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; + rt_size_t obj_name_len; struct rt_object_information *information; #ifdef RT_USING_MODULE struct rt_dlmodule *module = dlmodule_self(); @@ -505,10 +513,14 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) #if RT_NAME_MAX > 0 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'; + obj_name_len = rt_strlen(name); + if(obj_name_len > RT_NAME_MAX - 1) + { + LOG_E("Object name %s exceeds RT_NAME_MAX=%d, consider increasing RT_NAME_MAX.", name, RT_NAME_MAX); + RT_ASSERT(obj_name_len <= RT_NAME_MAX - 1); + } + rt_memcpy(object->name, name, obj_name_len); + object->name[obj_name_len] = '\0'; } else { @@ -672,7 +684,13 @@ static rt_err_t _match_name(struct rt_object *obj, void *data) { struct _obj_find_param *param = data; const char *name = param->match_name; - if (rt_strncmp(obj->name, name, RT_NAME_MAX) == 0) + char truncated_name[RT_NAME_MAX]; + + /* Truncate input name to RT_NAME_MAX - 1 to match object name storage */ + rt_strncpy(truncated_name, name, RT_NAME_MAX - 1); + truncated_name[RT_NAME_MAX - 1] = '\0'; + + if (rt_strcmp(obj->name, truncated_name) == 0) { param->matched_obj = obj; @@ -705,7 +723,8 @@ rt_object_t rt_object_find(const char *name, rt_uint8_t type) }; /* parameter check */ - if (name == RT_NULL) return RT_NULL; + if (name == RT_NULL || rt_object_get_information(type) == RT_NULL) + return RT_NULL; /* which is invoke in interrupt status */ RT_DEBUG_NOT_IN_INTERRUPT; @@ -731,7 +750,9 @@ rt_err_t rt_object_get_name(rt_object_t object, char *name, rt_uint8_t name_size if ((object != RT_NULL) && (name != RT_NULL) && (name_size != 0U)) { const char *obj_name = object->name; - (void) rt_strncpy(name, obj_name, (rt_size_t)name_size); + rt_strncpy(name, obj_name, (rt_size_t)name_size); + /* Ensure null-termination */ + name[name_size - 1] = '\0'; result = RT_EOK; } @@ -794,3 +815,4 @@ rt_err_t rt_custom_object_destroy(rt_object_t obj) #endif /**@}*/ +