[PATCH v5 1/8] lib/string_kunit: add correctness test for strlen()

Feng Jiang posted 8 patches 2 weeks ago
There is a newer version of this series
[PATCH v5 1/8] lib/string_kunit: add correctness test for strlen()
Posted by Feng Jiang 2 weeks ago
Add a KUnit test for strlen() to verify correctness across
different string lengths and memory alignments.

Signed-off-by: Feng Jiang <jiangfeng@kylinos.cn>
Acked-by: Andy Shevchenko <andy@kernel.org>
Tested-by: Joel Stanley <joel@jms.id.au>
---
 lib/tests/string_kunit.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/lib/tests/string_kunit.c b/lib/tests/string_kunit.c
index f9a8e557ba77..bc5130c6e5e9 100644
--- a/lib/tests/string_kunit.c
+++ b/lib/tests/string_kunit.c
@@ -17,6 +17,9 @@
 #define STRCMP_TEST_EXPECT_LOWER(test, fn, ...) KUNIT_EXPECT_LT(test, fn(__VA_ARGS__), 0)
 #define STRCMP_TEST_EXPECT_GREATER(test, fn, ...) KUNIT_EXPECT_GT(test, fn(__VA_ARGS__), 0)
 
+#define STRING_TEST_MAX_LEN	128
+#define STRING_TEST_MAX_OFFSET	16
+
 static void string_test_memset16(struct kunit *test)
 {
 	unsigned i, j, k;
@@ -104,6 +107,28 @@ static void string_test_memset64(struct kunit *test)
 	}
 }
 
+static void string_test_strlen(struct kunit *test)
+{
+	const size_t buf_size = STRING_TEST_MAX_LEN + STRING_TEST_MAX_OFFSET + 1;
+	size_t len, offset;
+	char *s;
+
+	s = kunit_kzalloc(test, buf_size, GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, s);
+
+	memset(s, 'A', buf_size);
+	s[buf_size - 1] = '\0';
+
+	for (offset = 0; offset < STRING_TEST_MAX_OFFSET; offset++) {
+		for (len = 0; len <= STRING_TEST_MAX_LEN; len++) {
+			s[offset + len] = '\0';
+			KUNIT_EXPECT_EQ_MSG(test, strlen(s + offset), len,
+				"offset:%zu len:%zu", offset, len);
+			s[offset + len] = 'A';
+		}
+	}
+}
+
 static void string_test_strchr(struct kunit *test)
 {
 	const char *test_string = "abcdefghijkl";
@@ -618,6 +643,7 @@ static struct kunit_case string_test_cases[] = {
 	KUNIT_CASE(string_test_memset16),
 	KUNIT_CASE(string_test_memset32),
 	KUNIT_CASE(string_test_memset64),
+	KUNIT_CASE(string_test_strlen),
 	KUNIT_CASE(string_test_strchr),
 	KUNIT_CASE(string_test_strnchr),
 	KUNIT_CASE(string_test_strspn),
-- 
2.25.1
Re: [PATCH v5 1/8] lib/string_kunit: add correctness test for strlen()
Posted by Kees Cook 1 week, 5 days ago
On Tue, Jan 27, 2026 at 09:25:51AM +0800, Feng Jiang wrote:
> Add a KUnit test for strlen() to verify correctness across
> different string lengths and memory alignments.
> 
> Signed-off-by: Feng Jiang <jiangfeng@kylinos.cn>
> Acked-by: Andy Shevchenko <andy@kernel.org>
> Tested-by: Joel Stanley <joel@jms.id.au>
> ---
>  lib/tests/string_kunit.c | 26 ++++++++++++++++++++++++++
>  1 file changed, 26 insertions(+)
> 
> diff --git a/lib/tests/string_kunit.c b/lib/tests/string_kunit.c
> index f9a8e557ba77..bc5130c6e5e9 100644
> --- a/lib/tests/string_kunit.c
> +++ b/lib/tests/string_kunit.c
> @@ -17,6 +17,9 @@
>  #define STRCMP_TEST_EXPECT_LOWER(test, fn, ...) KUNIT_EXPECT_LT(test, fn(__VA_ARGS__), 0)
>  #define STRCMP_TEST_EXPECT_GREATER(test, fn, ...) KUNIT_EXPECT_GT(test, fn(__VA_ARGS__), 0)
>  
> +#define STRING_TEST_MAX_LEN	128
> +#define STRING_TEST_MAX_OFFSET	16
> +
>  static void string_test_memset16(struct kunit *test)
>  {
>  	unsigned i, j, k;
> @@ -104,6 +107,28 @@ static void string_test_memset64(struct kunit *test)
>  	}
>  }
>  
> +static void string_test_strlen(struct kunit *test)
> +{
> +	const size_t buf_size = STRING_TEST_MAX_LEN + STRING_TEST_MAX_OFFSET + 1;
> +	size_t len, offset;
> +	char *s;
> +
> +	s = kunit_kzalloc(test, buf_size, GFP_KERNEL);

One aspect of "correctness" that we might want to include here is making
sure we don't have any implementations that over-read. To that end,
perhaps this test can put the string at the end of a vmalloc allocation
(so that the end of the string is right up against an unallocated memory
space).

> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, s);
> +
> +	memset(s, 'A', buf_size);
> +	s[buf_size - 1] = '\0';
> +
> +	for (offset = 0; offset < STRING_TEST_MAX_OFFSET; offset++) {
> +		for (len = 0; len <= STRING_TEST_MAX_LEN; len++) {
> +			s[offset + len] = '\0';
> +			KUNIT_EXPECT_EQ_MSG(test, strlen(s + offset), len,
> +				"offset:%zu len:%zu", offset, len);
> +			s[offset + len] = 'A';
> +		}
> +	}
> +}

It would require building the string backwards here. Or maybe we just
need a separate test for the over-read concerns?

Thoughts?

-Kees

-- 
Kees Cook
Re: [PATCH v5 1/8] lib/string_kunit: add correctness test for strlen()
Posted by Feng Jiang 1 week, 4 days ago
On 2026/1/29 06:39, Kees Cook wrote:
> On Tue, Jan 27, 2026 at 09:25:51AM +0800, Feng Jiang wrote:
>> Add a KUnit test for strlen() to verify correctness across
>> different string lengths and memory alignments.
>>
>> Signed-off-by: Feng Jiang <jiangfeng@kylinos.cn>
>> Acked-by: Andy Shevchenko <andy@kernel.org>
>> Tested-by: Joel Stanley <joel@jms.id.au>
>> ---
>>  lib/tests/string_kunit.c | 26 ++++++++++++++++++++++++++
>>  1 file changed, 26 insertions(+)
>>
>> diff --git a/lib/tests/string_kunit.c b/lib/tests/string_kunit.c
>> index f9a8e557ba77..bc5130c6e5e9 100644
>> --- a/lib/tests/string_kunit.c
>> +++ b/lib/tests/string_kunit.c
>> @@ -17,6 +17,9 @@
>>  #define STRCMP_TEST_EXPECT_LOWER(test, fn, ...) KUNIT_EXPECT_LT(test, fn(__VA_ARGS__), 0)
>>  #define STRCMP_TEST_EXPECT_GREATER(test, fn, ...) KUNIT_EXPECT_GT(test, fn(__VA_ARGS__), 0)
>>  
>> +#define STRING_TEST_MAX_LEN	128
>> +#define STRING_TEST_MAX_OFFSET	16
>> +
>>  static void string_test_memset16(struct kunit *test)
>>  {
>>  	unsigned i, j, k;
>> @@ -104,6 +107,28 @@ static void string_test_memset64(struct kunit *test)
>>  	}
>>  }
>>  
>> +static void string_test_strlen(struct kunit *test)
>> +{
>> +	const size_t buf_size = STRING_TEST_MAX_LEN + STRING_TEST_MAX_OFFSET + 1;
>> +	size_t len, offset;
>> +	char *s;
>> +
>> +	s = kunit_kzalloc(test, buf_size, GFP_KERNEL);
> 
> One aspect of "correctness" that we might want to include here is making
> sure we don't have any implementations that over-read. To that end,
> perhaps this test can put the string at the end of a vmalloc allocation
> (so that the end of the string is right up against an unallocated memory
> space).
> 
>> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, s);
>> +
>> +	memset(s, 'A', buf_size);
>> +	s[buf_size - 1] = '\0';
>> +
>> +	for (offset = 0; offset < STRING_TEST_MAX_OFFSET; offset++) {
>> +		for (len = 0; len <= STRING_TEST_MAX_LEN; len++) {
>> +			s[offset + len] = '\0';
>> +			KUNIT_EXPECT_EQ_MSG(test, strlen(s + offset), len,
>> +				"offset:%zu len:%zu", offset, len);
>> +			s[offset + len] = 'A';
>> +		}
>> +	}
>> +}
> 
> It would require building the string backwards here. Or maybe we just
> need a separate test for the over-read concerns?
> 
> Thoughts?

Thanks for the suggestion! That is a very effective way to catch potential
over-reads in optimized implementations.

I will refactor the correctness tests in v6 to use a vmalloc-allocated page
and ensure the NUL character is positioned at the very end of the allocation
boundary.

I'll send out the v6 patch set shortly with these changes.

-- 
With Best Regards,
Feng Jiang