commit: 8b3ca2ff9a235e980663cbd3cd6d30598f3745e2
parent 6db49bc56848ccf9d23ff5940b87084545160267
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sat,  3 Jun 2023 13:26:52 +0200
lib/iso_parse: Set max digits for nsecs
Diffstat:
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/lib/iso_parse.c b/lib/iso_parse.c
@@ -6,6 +6,7 @@
 #define _XOPEN_SOURCE 700       // strptime (NetBSD)
 #define _POSIX_C_SOURCE 200809L // st_atim/st_mtim
 
+#include <ctype.h>  /* isdigit */
 #include <errno.h>  /* errno */
 #include <stdio.h>  /* perror, sscanf */
 #include <stdlib.h> /* exit */
@@ -48,15 +49,18 @@ iso_parse(char *arg)
 
 	if(s[0] == ',' || s[0] == '.')
 	{
-		float fraction = 0.0;
-		int parsed     = 0;
+		double fraction = 0.0;
+		int parsed      = 0;
 
 		if(s[0] == ',') s[0] = '.';
 
-		if(sscanf(s, "%f%n", &fraction, &parsed) < 1) exit(EXIT_FAILURE);
+		if(sscanf(s, "%10lf%n", &fraction, &parsed) < 1) exit(EXIT_FAILURE);
 
 		time.tv_nsec = fraction * 1000000000;
 		s += parsed;
+
+		// too many digits
+		if(isdigit(s[0])) exit(EXIT_FAILURE);
 	}
 
 	if(s[0] == 'Z')
diff --git a/test-cmd/touch b/test-cmd/touch
@@ -168,6 +168,12 @@ optd_frac_body() {
 	atf_check -o "not-inline:${mtime}\n" ./stat_mtime ./foo
 	atf_check -o 'match:^2003-06-02[T ]13:37:42.7130+ ?(Z|[\+\-]00:?00)$' ./stat_atime ./foo
 	atf_check -o 'match:^2003-06-02[T ]13:37:42.7130+ ?(Z|[\+\-]00:?00)$' ./stat_mtime ./foo
+
+	atf_check ../cmd/touch -d 2003-06-02T13:37:42.123456789Z ./foo
+	atf_check -o 'match:^2003-06-02[T ]13:37:42.123456789 ?(Z|[\+\-]00:?00)$' ./stat_atime ./foo
+	atf_check -o 'match:^2003-06-02[T ]13:37:42.123456789 ?(Z|[\+\-]00:?00)$' ./stat_mtime ./foo
+
+	atf_check -s 'exit:1' ../cmd/touch -d 2003-06-02T13:37:42.1234567890Z ./foo
 }
 
 atf_init_test_cases() {