Skip to content

Commit ed0164f

Browse files
committed
utils: Add safer strnlen function
The function searches for the terminating `NULL` character in the given string up to a given maximun length.
1 parent 535230c commit ed0164f

File tree

6 files changed

+131
-0
lines changed

6 files changed

+131
-0
lines changed

core/utils.c

+12
Original file line numberDiff line numberDiff line change
@@ -1155,3 +1155,15 @@ lwm2m_data_type_t utils_depthToDatatype(uri_depth_t depth)
11551155

11561156
return LWM2M_TYPE_UNDEFINED;
11571157
}
1158+
1159+
size_t utils_strnlen(const char *str, size_t max_size) {
1160+
if (str == NULL) {
1161+
return 0;
1162+
}
1163+
const char *pos = memchr(str, '\0', max_size);
1164+
if (pos == NULL) {
1165+
return max_size;
1166+
}
1167+
1168+
return pos - str;
1169+
}

core/utils.h

+10
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,15 @@ lwm2m_server_t *utils_findBootstrapServer(lwm2m_context_t *contextP, void *fromS
4747
#if defined(LWM2M_SERVER_MODE) || defined(LWM2M_BOOTSTRAP_SERVER_MODE)
4848
lwm2m_client_t *utils_findClient(lwm2m_context_t *contextP, void *fromSessionH);
4949
#endif
50+
/** A safer version of `strlen`. Finds the number of chars (bytes) of the given string up to a given max. length.
51+
*
52+
* The behaviour is undefined if the maximum length value is bigger than the actually reserved memory behind the @a str
53+
* buffer.
54+
*
55+
* @param str The null-terminated string to find the length of.
56+
* @param max_size Max size of string.
57+
* @return The size of the string if it is smaller or equal to max_size. Otherwise max_size.
58+
*/
59+
size_t utils_strnlen(const char *str, size_t max_size);
5060

5161
#endif /* WAKAAMA_UTILS_H */

tests/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ set(TEST_SOURCES
1515
core_logging_tests.c
1616
core_registration_tests.c
1717
core_uritests.c
18+
core_utils_tests.c
1819
data_senml_cbor_tests.c
1920
data_senml_json_tests.c
2021
data_tlv_json_lwm2m_data_test.c

tests/core_utils_tests.c

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*******************************************************************************
2+
*
3+
* Copyright (c) 2025 GARDENA GmbH
4+
*
5+
* All rights reserved. This program and the accompanying materials
6+
* are made available under the terms of the Eclipse Public License v2.0
7+
* and Eclipse Distribution License v1.0 which accompany this distribution.
8+
*
9+
* The Eclipse Public License is available at
10+
* http://www.eclipse.org/legal/epl-v20.html
11+
* The Eclipse Distribution License is available at
12+
* http://www.eclipse.org/org/documents/edl-v10.php.
13+
*
14+
* Contributors:
15+
* Lukas Woodtli, GARDENA GmbH - Please refer to git log
16+
*
17+
*******************************************************************************/
18+
#include "CUnit/Basic.h"
19+
#include "tests.h"
20+
#include "utils.h"
21+
22+
void test_strnlen_null(void) {
23+
size_t len = utils_strnlen(NULL, 10);
24+
CU_ASSERT_EQUAL(len, 0);
25+
}
26+
27+
void test_strnlen_0(void) {
28+
const char *string = "";
29+
size_t len = utils_strnlen(string, 10);
30+
CU_ASSERT_EQUAL(len, 0);
31+
}
32+
33+
void test_strnlen_1(void) {
34+
const char *string = "a";
35+
size_t len = utils_strnlen(string, 10);
36+
CU_ASSERT_EQUAL(len, 1);
37+
}
38+
39+
void test_strnlen_2(void) {
40+
const char *string = "ab";
41+
size_t len = utils_strnlen(string, 10);
42+
CU_ASSERT_EQUAL(len, 2);
43+
}
44+
45+
void test_strnlen_max_len_0(void) {
46+
const char *string = "abc";
47+
size_t len = utils_strnlen(string, 0);
48+
CU_ASSERT_EQUAL(len, 0);
49+
}
50+
51+
void test_strnlen_max_len_1(void) {
52+
const char *string = "abc";
53+
size_t len = utils_strnlen(string, 1);
54+
CU_ASSERT_EQUAL(len, 1);
55+
}
56+
57+
void test_strnlen_max_len_2(void) {
58+
const char *string = "abc";
59+
size_t len = utils_strnlen(string, 2);
60+
CU_ASSERT_EQUAL(len, 2);
61+
}
62+
63+
void test_strnlen_max_len_3(void) {
64+
const char *string = "abc";
65+
size_t len = utils_strnlen(string, 3);
66+
CU_ASSERT_EQUAL(len, 3);
67+
}
68+
69+
void test_strnlen_max_len_4(void) {
70+
const char *string = "abc";
71+
size_t len = utils_strnlen(string, 4);
72+
CU_ASSERT_EQUAL(len, 3);
73+
}
74+
75+
void test_strnlen_max_len_5(void) {
76+
const char *string = "abc";
77+
size_t len = utils_strnlen(string, 5);
78+
CU_ASSERT_EQUAL(len, 3);
79+
}
80+
81+
static struct TestTable table[] = {
82+
{"test_strnlen_null()", test_strnlen_null},
83+
{"test_strnlen_0()", test_strnlen_0},
84+
{"test_strnlen_1()", test_strnlen_1},
85+
{"test_strnlen_2()", test_strnlen_2},
86+
{"test_strnlen_max_len_0()", test_strnlen_max_len_0},
87+
{"test_strnlen_max_len_1()", test_strnlen_max_len_1},
88+
{"test_strnlen_max_len_2()", test_strnlen_max_len_2},
89+
{"test_strnlen_max_len_3()", test_strnlen_max_len_3},
90+
{"test_strnlen_max_len_4()", test_strnlen_max_len_4},
91+
{"test_strnlen_max_len_5()", test_strnlen_max_len_5},
92+
{NULL, NULL},
93+
};
94+
95+
CU_ErrorCode create_utils_suit(void) {
96+
CU_pSuite pSuite = NULL;
97+
98+
pSuite = CU_add_suite("Suite_utils", NULL, NULL);
99+
if (NULL == pSuite) {
100+
return CU_get_error();
101+
}
102+
103+
return add_tests(pSuite, table);
104+
}

tests/tests.h

+1
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,5 @@ CU_ErrorCode create_logging_test_suit(void);
5858
#ifdef LWM2M_SERVER_MODE
5959
CU_ErrorCode create_registration_test_suit(void);
6060
#endif
61+
CU_ErrorCode create_utils_suit(void);
6162
#endif /* TESTS_H_ */

tests/unittests.c

+3
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ int main(void) {
107107
goto exit;
108108
#endif
109109

110+
if (CUE_SUCCESS != create_utils_suit())
111+
goto exit;
112+
110113
CU_basic_set_mode(CU_BRM_VERBOSE);
111114
CU_basic_run_tests();
112115
CU_basic_show_failures(CU_get_failure_list());

0 commit comments

Comments
 (0)