]> git.ipfire.org Git - thirdparty/json-c.git/commitdiff
Use strtoll to parse ints
authorJason King <jason.brian.king@gmail.com>
Thu, 7 Sep 2017 17:21:14 +0000 (17:21 +0000)
committerJason King <jason.brian.king@gmail.com>
Thu, 7 Sep 2017 17:21:14 +0000 (17:21 +0000)
json_util.c

index 4624668891bdcde908136168d3a28ea1d9b3465a..00cdc300430943dd6b7992bc3f576c322db9ca3b 100644 (file)
 #include "json_tokener.h"
 #include "json_util.h"
 
-static int sscanf_is_broken = 0;
-static int sscanf_is_broken_testdone = 0;
-static void sscanf_is_broken_test(void);
-
 static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename);
 
 static char _last_err[256] = "";
@@ -195,119 +191,16 @@ int json_parse_double(const char *buf, double *retval)
   return end == buf ? 1 : 0;
 }
 
-/*
- * Not all implementations of sscanf actually work properly.
- * Check whether the one we're currently using does, and if
- * it's broken, enable the workaround code.
- */
-static void sscanf_is_broken_test()
-{
-       int64_t num64;
-       int ret_errno, is_int64_min, ret_errno2, is_int64_max;
-
-       (void)sscanf(" -01234567890123456789012345", "%" SCNd64, &num64);
-       ret_errno = errno;
-       is_int64_min = (num64 == INT64_MIN);
-
-       (void)sscanf(" 01234567890123456789012345", "%" SCNd64, &num64);
-       ret_errno2 = errno;
-       is_int64_max = (num64 == INT64_MAX);
-
-       if (ret_errno != ERANGE || !is_int64_min ||
-           ret_errno2 != ERANGE || !is_int64_max)
-       {
-               MC_DEBUG("sscanf_is_broken_test failed, enabling workaround code\n");
-               sscanf_is_broken = 1;
-       }
-}
-
 int json_parse_int64(const char *buf, int64_t *retval)
 {
-       int64_t num64;
-       const char *buf_sig_digits;
-       int orig_has_neg;
-       int saved_errno;
-
-       if (!sscanf_is_broken_testdone)
-       {
-               sscanf_is_broken_test();
-               sscanf_is_broken_testdone = 1;
-       }
-
-       // Skip leading spaces
-       while (isspace((int)*buf) && *buf)
-               buf++;
-
-       errno = 0; // sscanf won't always set errno, so initialize
-       if (sscanf(buf, "%" SCNd64, &num64) != 1)
-       {
-               MC_DEBUG("Failed to parse, sscanf != 1\n");
-               return 1;
-       }
-
-       saved_errno = errno;
-       buf_sig_digits = buf;
-       orig_has_neg = 0;
-       if (*buf_sig_digits == '-')
-       {
-               buf_sig_digits++;
-               orig_has_neg = 1;
-       }
-
-       // Not all sscanf implementations actually work
-       if (sscanf_is_broken && saved_errno != ERANGE)
-       {
-               char buf_cmp[100];
-               char *buf_cmp_start = buf_cmp;
-               int recheck_has_neg = 0;
-               int buf_cmp_len;
-
-               // Skip leading zeros, but keep at least one digit
-               while (buf_sig_digits[0] == '0' && buf_sig_digits[1] != '\0')
-                       buf_sig_digits++;
-               // Can't check num64==0 because some sscanf impl's parse
-               //  non-zero values to 0.  (e.g. Illumos with UINT64_MAX)
-               if (buf_sig_digits[0] == '0' && buf_sig_digits[1] == '\0')
-                       orig_has_neg = 0; // "-0" is the same as just plain "0"
-
-               snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64);
-               if (*buf_cmp_start == '-')
-               {
-                       recheck_has_neg = 1;
-                       buf_cmp_start++;
-               }
-               // No need to skip leading spaces or zeros here.
-
-               buf_cmp_len = strlen(buf_cmp_start);
-               /**
-                * If the sign is different, or
-                * some of the digits are different, or
-                * there is another digit present in the original string
-                * then we have NOT successfully parsed the value.
-                */
-               if (orig_has_neg != recheck_has_neg ||
-                   strncmp(buf_sig_digits, buf_cmp_start, strlen(buf_cmp_start)) != 0 ||
-                       ((int)strlen(buf_sig_digits) != buf_cmp_len &&
-                        isdigit((int)buf_sig_digits[buf_cmp_len])
-                   )
-                  )
-               {
-                       saved_errno = ERANGE;
-               }
-       }
-
-       // Not all sscanf impl's set the value properly when out of range.
-       // Always do this, even for properly functioning implementations,
-       // since it shouldn't slow things down much.
-       if (saved_errno == ERANGE)
-       {
-               if (orig_has_neg)
-                       num64 = INT64_MIN;
-               else
-                       num64 = INT64_MAX;
-       }
-       *retval = num64;
-       return 0;
+       char *end = NULL;
+       int64_t val;
+
+       errno = 0;
+       val = strtoll(buf, &end, 10);
+       if (end != buf)
+               *retval = val;
+       return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0;
 }
 
 #ifndef HAVE_REALLOC