[PATCH v4][BZ #15346] Allow leading and trailing spaces in getdate
Siddhesh Poyarekar
siddhesh@redhat.com
Tue Apr 9 20:17:00 GMT 2013
On Tue, Apr 09, 2013 at 09:39:19AM -0700, Roland McGrath wrote:
> Let's avoid the copy when it's unnecessary. So, start incrementing STRING
> itself for the leading whitespace (and don't do strlen til after that).
> Then only do the copy if the trailing whitespace check found anything to trim.
OK, how's this?
Siddhesh
commit 295c48bdfcc113bfd1c2c867cfcf8ffa04f004c5
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date: Tue Apr 9 22:44:09 2013 +0530
Accept leading and trailing spaces in getdate input string
Fixes #15346.
The POSIX description of getdate allows for extra spaces in the
getdate input string. __getdate_r uses strptime internally, which
works fine with extra spaces between format strings (and hence within
an input string) but not with leading and trailing spaces. So we trim
off the leading and trailing spaces before we pass it on to strptime.
---
[BZ #15346]
* time/getdate.c: Include ctype.h and alloca.h.
(__getdate_r): Trim leading and trailing spaces of input.
* time/tst-getdate.c (tests): Add tests with leading and
trailing spaces.
diff --git a/time/getdate.c b/time/getdate.c
index 637dd18..e013d9b 100644
--- a/time/getdate.c
+++ b/time/getdate.c
@@ -25,6 +25,8 @@
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
+#include <ctype.h>
+#include <alloca.h>
#define TM_YEAR_BASE 1900
@@ -135,6 +137,41 @@ __getdate_r (const char *string, struct tm *tp)
/* No threads reading this stream. */
__fsetlocking (fp, FSETLOCKING_BYCALLER);
+ size_t inlen, oldlen;
+ bool free_instr = false;
+
+ /* Skip leading whitespace. */
+ while (isspace (*string))
+ string++;
+
+ oldlen = inlen = strlen (string);
+
+ /* Skip trailing whitespace. */
+ while (inlen > 0 && isspace (string[inlen - 1]))
+ inlen--;
+
+ char *instr;
+
+ if (inlen == oldlen)
+ instr = (char *) string;
+ else
+ {
+ if (__libc_use_alloca (inlen + 1))
+ instr = alloca (inlen + 1);
+ else
+ {
+ instr = malloc (inlen + 1);
+ if (instr == NULL)
+ {
+ fclose (fp);
+ return 6;
+ }
+ free_instr = true;
+ }
+ memcpy (instr, string, inlen);
+ instr[inlen] = '\0';
+ }
+
line = NULL;
len = 0;
do
@@ -153,12 +190,15 @@ __getdate_r (const char *string, struct tm *tp)
tp->tm_isdst = -1;
tp->tm_gmtoff = 0;
tp->tm_zone = NULL;
- result = strptime (string, line, tp);
+ result = strptime (instr, line, tp);
if (result && *result == '\0')
break;
}
while (!feof_unlocked (fp));
+ if (free_instr)
+ free (instr);
+
/* Free the buffer. */
free (line);
diff --git a/time/tst-getdate.c b/time/tst-getdate.c
index 7604e83..dc8ecf4 100644
--- a/time/tst-getdate.c
+++ b/time/tst-getdate.c
@@ -31,6 +31,10 @@ static const struct
} tests [] =
{
{"21:01:10 1999-1-31", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}},
+ {"21:01:10 1999-1-31", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}},
+ {" 21:01:10 1999-1-31", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}},
+ {"21:01:10 1999-1-31 ", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}},
+ {" 21:01:10 1999-1-31 ", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}},
{"21:01:10 1999-2-28", "Universal", 0, {10, 1, 21, 28, 1, 99, 0, 0, 0}},
{"16:30:46 2000-2-29", "Universal", 0, {46, 30,16, 29, 1, 100, 0, 0, 0}},
{"01-08-2000 05:06:07", "Europe/Berlin", 0, {7, 6, 5, 1, 7, 100, 0, 0, 0}}
More information about the Libc-alpha
mailing list