[tz] [PATCH 1/2] zdump: remove unportable assumption about sscanf and overflow

Paul Eggert eggert at cs.ucla.edu
Mon Oct 21 05:43:42 UTC 2013


* zdump.c (strtoimax) [!INTMAX_MAX]: Define like private.h does.
(SCNdMAX): Remove; no longer used.
(main): Use strtoimax, not sscanf with SCNdMAX, as strtoimax has
well-defined behavior when the input number is out of numeric range.
---
 zdump.c | 29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/zdump.c b/zdump.c
index 2a9860c..209b79d 100644
--- a/zdump.c
+++ b/zdump.c
@@ -59,6 +59,7 @@ typedef int int_fast32_t;
 #ifndef INTMAX_MAX
 # if defined LLONG_MAX || defined __LONG_LONG_MAX__
 typedef long long intmax_t;
+#  define strtoimax strtoll
 #  define PRIdMAX "lld"
 #  ifdef LLONG_MAX
 #   define INTMAX_MAX LLONG_MAX
@@ -67,13 +68,11 @@ typedef long long intmax_t;
 #  endif
 # else
 typedef long intmax_t;
+#  define strtoimax strtol
 #  define PRIdMAX "ld"
 #  define INTMAX_MAX LONG_MAX
 # endif
 #endif
-#ifndef SCNdMAX
-# define SCNdMAX PRIdMAX
-#endif
 
 
 #ifndef ZDUMP_LO_YEAR
@@ -368,16 +367,19 @@ main(int argc, char *argv[])
 	if (vflag | Vflag) {
 		intmax_t	lo;
 		intmax_t	hi;
-		char		dummy;
+		char *loend, *hiend;
 		register intmax_t cutloyear = ZDUMP_LO_YEAR;
 		register intmax_t cuthiyear = ZDUMP_HI_YEAR;
 		if (cutarg != NULL) {
-			if (sscanf(cutarg, "%"SCNdMAX"%c", &hi, &dummy) == 1) {
+			lo = strtoimax(cutarg, &loend, 10);
+			if (cutarg != loend && !*loend) {
+				hi = lo;
+				cuthiyear = hi;
+			} else if (cutarg != loend && *loend == ','
+				   && (hi = strtoimax(loend + 1, &hiend, 10),
+				       loend + 1 != hiend && !*hiend)) {
+				cutloyear = lo;
 				cuthiyear = hi;
-			} else if (sscanf(cutarg, "%"SCNdMAX",%"SCNdMAX"%c",
-				&lo, &hi, &dummy) == 2) {
-					cutloyear = lo;
-					cuthiyear = hi;
 			} else {
 (void) fprintf(stderr, _("%s: wild -c argument %s\n"),
 					progname, cutarg);
@@ -389,14 +391,17 @@ main(int argc, char *argv[])
 			cuthitime = yeartot(cuthiyear);
 		}
 		if (cuttimes != NULL) {
-			if (sscanf(cuttimes, "%"SCNdMAX"%c", &hi, &dummy) == 1) {
+			lo = strtoimax(cuttimes, &loend, 10);
+			if (cuttimes != loend && !*loend) {
+				hi = lo;
 				if (hi < cuthitime) {
 					if (hi < absolute_min_time)
 						hi = absolute_min_time;
 					cuthitime = hi;
 				}
-			} else if (sscanf(cuttimes, "%"SCNdMAX",%"SCNdMAX"%c",
-					  &lo, &hi, &dummy) == 2) {
+			} else if (cuttimes != loend && *loend == ','
+				   && (hi = strtoimax(loend + 1, &hiend, 10),
+				       loend + 1 != hiend && !*hiend)) {
 				if (cutlotime < lo) {
 					if (absolute_max_time < lo)
 						lo = absolute_max_time;
-- 
1.8.3.2



More information about the tz mailing list