Browse Source

[libc] Prevent strndup() from reading beyond the end of the string

strndup() may be called on a string which is not NUL-terminated.  Use
strnlen() instead of strlen() to ensure that we do not read beyond the
end of such a string.

Add self-tests for strndup(), including a test case with an
unterminated string.

Originally-fixed-by: Marin Hannache <git@mareo.fr>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
2b4be69eee
2 changed files with 21 additions and 3 deletions
  1. 1
    3
      src/core/string.c
  2. 20
    0
      src/tests/string_test.c

+ 1
- 3
src/core/string.c View File

@@ -337,11 +337,9 @@ void * memchr(const void *s, int c, size_t n)
337 337
 
338 338
 char * strndup(const char *s, size_t n)
339 339
 {
340
-        size_t len = strlen(s);
340
+        size_t len = strnlen(s,n);
341 341
         char *new;
342 342
 
343
-        if (len>n)
344
-                len = n;
345 343
         new = malloc(len+1);
346 344
         if (new) {
347 345
                 new[len] = '\0';

+ 20
- 0
src/tests/string_test.c View File

@@ -134,6 +134,26 @@ static void string_test_exec ( void ) {
134 134
 		ok ( strcmp ( dup, orig ) == 0 );
135 135
 		free ( dup );
136 136
 	}
137
+
138
+	/* Test strndup() */
139
+	{
140
+		const char *normal = "testing testing";
141
+		const char unterminated[6] = { 'h', 'e', 'l', 'l', 'o', '!' };
142
+		char *dup;
143
+		dup = strndup ( normal, 32 );
144
+		ok ( dup != NULL );
145
+		ok ( dup != normal );
146
+		ok ( strcmp ( dup, normal ) == 0 );
147
+		free ( dup );
148
+		dup = strndup ( normal, 4 );
149
+		ok ( dup != NULL );
150
+		ok ( strcmp ( dup, "test" ) == 0 );
151
+		free ( dup );
152
+		dup = strndup ( unterminated, 5 );
153
+		ok ( dup != NULL );
154
+		ok ( strcmp ( dup, "hello" ) == 0 );
155
+		free ( dup );
156
+	}
137 157
 }
138 158
 
139 159
 /** String self-test */

Loading…
Cancel
Save