Skip to content

Commit ece19e9

Browse files
kurisaWRbb666
authored andcommitted
kernel/testcase: fixed buffer overflow vulnerability in object
1 parent 4423c6f commit ece19e9

File tree

4 files changed

+130
-4
lines changed

4 files changed

+130
-4
lines changed

examples/utest/testcases/kernel/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
menu "Kernel Testcase"
22

3+
config UTEST_OBJECT_TC
4+
bool "object test"
5+
default y
6+
37
config UTEST_MEMHEAP_TC
48
bool "memheap stability test"
59
default y

examples/utest/testcases/kernel/SConscript

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ cwd = GetCurrentDir()
55
src = []
66
CPPPATH = [cwd]
77

8+
if GetDepend(['UTEST_OBJECT_TC']):
9+
src += ['object_tc.c']
10+
811
if GetDepend(['UTEST_MEMHEAP_TC']):
912
src += ['memheap_tc.c']
1013

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2006-2025, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2025-07-18 kurisaW First commit
9+
*/
10+
11+
#include <utest.h>
12+
#include <rtthread.h>
13+
#include <string.h>
14+
15+
/**
16+
* @brief Test case for verifying object name handling functionality
17+
*
18+
* @note This test suite validates:
19+
* 1. Proper truncation of long object names
20+
* 2. Correct NULL name handling
21+
* 3. Exact length name preservation
22+
* 4. Both static and dynamic object initialization
23+
* 5. Memory safety and boundary conditions
24+
*/
25+
26+
static void test_object_name_handling(void)
27+
{
28+
struct rt_object static_obj1;
29+
struct rt_object static_obj2;
30+
struct rt_object static_obj3;
31+
rt_object_t dyn_obj = RT_NULL;
32+
char test_name[RT_NAME_MAX + 5];
33+
34+
for (int i = 0; i < sizeof(test_name) - 1; i++)
35+
{
36+
test_name[i] = 'A' + (i % 26);
37+
}
38+
test_name[sizeof(test_name) - 1] = '\0';
39+
40+
/* Test 1: Static Object Initialization - Extra Long Name */
41+
rt_object_init(&static_obj1, RT_Object_Class_Thread, test_name);
42+
uassert_true(rt_strlen(static_obj1.name) <= RT_NAME_MAX - 1);
43+
uassert_true(static_obj1.name[RT_NAME_MAX - 1] == '\0');
44+
45+
/* Test 2: Dynamic Object Allocation */
46+
dyn_obj = rt_object_allocate(RT_Object_Class_Thread, test_name);
47+
uassert_not_null(dyn_obj);
48+
if (dyn_obj)
49+
{
50+
uassert_true(rt_strlen(dyn_obj->name) <= RT_NAME_MAX - 1);
51+
uassert_true(dyn_obj->name[RT_NAME_MAX - 1] == '\0');
52+
rt_object_delete(dyn_obj);
53+
dyn_obj = RT_NULL;
54+
}
55+
56+
/* Test 3: NULL Name Handling - Using New Static Object */
57+
rt_object_init(&static_obj2, RT_Object_Class_Thread, NULL);
58+
uassert_true(static_obj2.name[0] == '\0');
59+
60+
/* Test 4: Dynamic Object with NULL Name */
61+
dyn_obj = rt_object_allocate(RT_Object_Class_Thread, NULL);
62+
uassert_not_null(dyn_obj);
63+
if (dyn_obj)
64+
{
65+
uassert_true(dyn_obj->name[0] == '\0');
66+
rt_object_delete(dyn_obj);
67+
dyn_obj = RT_NULL;
68+
}
69+
70+
/* Test 5: Fixed-Length Name - Using Third Static Object */
71+
char exact_name[RT_NAME_MAX];
72+
rt_memset(exact_name, 'B', RT_NAME_MAX - 1);
73+
exact_name[RT_NAME_MAX - 1] = '\0';
74+
75+
rt_object_init(&static_obj3, RT_Object_Class_Thread, exact_name);
76+
uassert_str_equal(static_obj3.name, exact_name);
77+
78+
rt_object_detach(&static_obj1);
79+
rt_object_detach(&static_obj2);
80+
rt_object_detach(&static_obj3);
81+
}
82+
83+
static rt_err_t testcase_init(void)
84+
{
85+
return RT_EOK;
86+
}
87+
88+
static rt_err_t testcase_cleanup(void)
89+
{
90+
return RT_EOK;
91+
}
92+
93+
static void test_object_suite(void)
94+
{
95+
UTEST_UNIT_RUN(test_object_name_handling);
96+
}
97+
UTEST_TC_EXPORT(test_object_suite, "testcases.kernel.object_test", testcase_init, testcase_cleanup, 10);

src/object.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ void rt_object_init(struct rt_object *object,
355355
const char *name)
356356
{
357357
rt_base_t level;
358+
rt_size_t len;
358359
#ifdef RT_DEBUGING_ASSERT
359360
struct rt_list_node *node = RT_NULL;
360361
#endif /* RT_DEBUGING_ASSERT */
@@ -390,10 +391,20 @@ void rt_object_init(struct rt_object *object,
390391
/* set object type to static */
391392
object->type = type | RT_Object_Class_Static;
392393
#if RT_NAME_MAX > 0
393-
rt_strncpy(object->name, name, RT_NAME_MAX); /* copy name */
394+
if (name)
395+
{
396+
len = rt_strlen(name);
397+
len = len > RT_NAME_MAX - 1 ? RT_NAME_MAX - 1 : len;
398+
rt_memcpy(object->name, name, len);
399+
object->name[len] = '\0';
400+
}
401+
else
402+
{
403+
object->name[0] = '\0';
404+
}
394405
#else
395406
object->name = name;
396-
#endif /* RT_NAME_MAX > 0 */
407+
#endif
397408

398409
RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
399410

@@ -461,6 +472,7 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
461472
{
462473
struct rt_object *object;
463474
rt_base_t level;
475+
rt_size_t len;
464476
struct rt_object_information *information;
465477
#ifdef RT_USING_MODULE
466478
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)
491503
object->flag = 0;
492504

493505
#if RT_NAME_MAX > 0
494-
rt_strncpy(object->name, name, RT_NAME_MAX - 1); /* copy name */
506+
if (name)
507+
{
508+
len = rt_strlen(name);
509+
len = len > RT_NAME_MAX - 1 ? RT_NAME_MAX - 1 : len;
510+
rt_memcpy(object->name, name, len);
511+
object->name[len] = '\0';
512+
}
513+
else
514+
{
515+
object->name[0] = '\0';
516+
}
495517
#else
496518
object->name = name;
497-
#endif /* RT_NAME_MAX > 0 */
519+
#endif
498520

499521
RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
500522

0 commit comments

Comments
 (0)