mirror of https://github.com/RT-Thread/rt-thread
kernel/testcase: fixed buffer overflow vulnerability in object
This commit is contained in:
parent
4423c6f01f
commit
ece19e961a
|
@ -1,5 +1,9 @@
|
||||||
menu "Kernel Testcase"
|
menu "Kernel Testcase"
|
||||||
|
|
||||||
|
config UTEST_OBJECT_TC
|
||||||
|
bool "object test"
|
||||||
|
default y
|
||||||
|
|
||||||
config UTEST_MEMHEAP_TC
|
config UTEST_MEMHEAP_TC
|
||||||
bool "memheap stability test"
|
bool "memheap stability test"
|
||||||
default y
|
default y
|
||||||
|
|
|
@ -5,6 +5,9 @@ cwd = GetCurrentDir()
|
||||||
src = []
|
src = []
|
||||||
CPPPATH = [cwd]
|
CPPPATH = [cwd]
|
||||||
|
|
||||||
|
if GetDepend(['UTEST_OBJECT_TC']):
|
||||||
|
src += ['object_tc.c']
|
||||||
|
|
||||||
if GetDepend(['UTEST_MEMHEAP_TC']):
|
if GetDepend(['UTEST_MEMHEAP_TC']):
|
||||||
src += ['memheap_tc.c']
|
src += ['memheap_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 <utest.h>
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
30
src/object.c
30
src/object.c
|
@ -355,6 +355,7 @@ void rt_object_init(struct rt_object *object,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
rt_base_t level;
|
rt_base_t level;
|
||||||
|
rt_size_t len;
|
||||||
#ifdef RT_DEBUGING_ASSERT
|
#ifdef RT_DEBUGING_ASSERT
|
||||||
struct rt_list_node *node = RT_NULL;
|
struct rt_list_node *node = RT_NULL;
|
||||||
#endif /* RT_DEBUGING_ASSERT */
|
#endif /* RT_DEBUGING_ASSERT */
|
||||||
|
@ -390,10 +391,20 @@ void rt_object_init(struct rt_object *object,
|
||||||
/* set object type to static */
|
/* set object type to static */
|
||||||
object->type = type | RT_Object_Class_Static;
|
object->type = type | RT_Object_Class_Static;
|
||||||
#if RT_NAME_MAX > 0
|
#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
|
#else
|
||||||
object->name = name;
|
object->name = name;
|
||||||
#endif /* RT_NAME_MAX > 0 */
|
#endif
|
||||||
|
|
||||||
RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
|
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;
|
struct rt_object *object;
|
||||||
rt_base_t level;
|
rt_base_t level;
|
||||||
|
rt_size_t len;
|
||||||
struct rt_object_information *information;
|
struct rt_object_information *information;
|
||||||
#ifdef RT_USING_MODULE
|
#ifdef RT_USING_MODULE
|
||||||
struct rt_dlmodule *module = dlmodule_self();
|
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;
|
object->flag = 0;
|
||||||
|
|
||||||
#if RT_NAME_MAX > 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
|
#else
|
||||||
object->name = name;
|
object->name = name;
|
||||||
#endif /* RT_NAME_MAX > 0 */
|
#endif
|
||||||
|
|
||||||
RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
|
RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue