This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] Fix undefined behaviour inconsistent for strtok
- From: Adhemerval Zanella <adhemerval dot zanella at linaro dot org>
- To: libc-alpha at sourceware dot org
- Date: Tue, 25 Oct 2016 08:58:33 -0200
- Subject: [PATCH] Fix undefined behaviour inconsistent for strtok
- Authentication-results: sourceware.org; auth=none
Although not stated in any standard how strtok should return if you
pass a null argument if the previous argument is also null, this patch
changes the default implementation to follow this idea.
The original bug report comment #1 states glibc code convention [6]
should not allow it, however for this specific function its contract
does not expect failure even if the returned is ignored (since it
would be a no-op). Also, patch idea is more focuses on implementation
portability , since it aligns glibc with other implementation that
follows the same idea for strtok:
- FreeBSD [1], OpenBSD [2], NetBSD [3];
- uclibc and uclibc-ng [4]
- musl [5]
I see little value to either assert on null input (as stated in comment
2 from original bug report), change both x86_64 and powerpc64le
implementation to fault on such input, or to keep a different behavior
compared to other libc implementations.
Checked on x86_64, aarch64, and powerpc64le.
* string/strtok.c (strtok): Return null is previous input is also
null.
* string/tst-strtok.c (do_test): Add more strtok coverage.
[1] https://github.com/freebsd/freebsd/blob/386ddae58459341ec567604707805814a2128a57/lib/libc/string/strtok.c
[2] http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/string/strtok_r.c?rev=1.10&content-type=text/x-cvsweb-markup&only_with_tag=MAIN
[3] https://github.com/openbsd/src/blob/5271000b44abe23907b73bbb3aa38ddf4a0bce08/lib/libc/string/strtok.c
[4] http://www.uclibc-ng.org/browser/uclibc-ng/libc/string/strtok_r.c
[5] https://git.musl-libc.org/cgit/musl/tree/src/string/strtok.c
[6] https://sourceware.org/glibc/wiki/Style_and_Conventions#Invalid_pointers
---
ChangeLog | 7 +++++++
string/strtok.c | 4 ++--
string/tst-strtok.c | 23 ++++++++++++-----------
3 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/string/strtok.c b/string/strtok.c
index 7a4574d..5c4b309 100644
--- a/string/strtok.c
+++ b/string/strtok.c
@@ -40,8 +40,8 @@ STRTOK (char *s, const char *delim)
{
char *token;
- if (s == NULL)
- s = olds;
+ if ((s == NULL) && ((s = olds) == NULL))
+ return NULL;
/* Scan leading delimiters. */
s += strspn (s, delim);
diff --git a/string/tst-strtok.c b/string/tst-strtok.c
index 6fbef9f..d9180a4 100644
--- a/string/tst-strtok.c
+++ b/string/tst-strtok.c
@@ -2,25 +2,26 @@
#include <stdio.h>
#include <string.h>
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
static int
do_test (void)
{
char buf[1] = { 0 };
int result = 0;
+ if (strtok (NULL, " ") != NULL)
+ FAIL_RET ("first strtok call did not return NULL");
+ if (strtok (NULL, " ") != NULL)
+ FAIL_RET ("second strtok call did not return NULL");
+
if (strtok (buf, " ") != NULL)
- {
- puts ("first strtok call did not return NULL");
- result = 1;
- }
+ FAIL_RET ("third strtok call did not return NULL");
else if (strtok (NULL, " ") != NULL)
- {
- puts ("second strtok call did not return NULL");
- result = 1;
- }
+ FAIL_RET ("forth strtok call did not return NULL");
return result;
}
-
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
--
2.7.4