parse_int.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /* Copyright (c) 2003, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. /**
  6. * \file parse_int.c
  7. * \brief Convert strings into the integers they encode, with bounds checking.
  8. **/
  9. #include "lib/string/parse_int.h"
  10. #include <errno.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. /* Helper: common code to check whether the result of a strtol or strtoul or
  14. * strtoll is correct. */
  15. #define CHECK_STRTOX_RESULT() \
  16. /* Did an overflow occur? */ \
  17. if (errno == ERANGE) \
  18. goto err; \
  19. /* Was at least one character converted? */ \
  20. if (endptr == s) \
  21. goto err; \
  22. /* Were there unexpected unconverted characters? */ \
  23. if (!next && *endptr) \
  24. goto err; \
  25. /* Illogical (max, min) inputs? */ \
  26. if (max < min) \
  27. goto err; \
  28. /* Is r within limits? */ \
  29. if (r < min || r > max) \
  30. goto err; \
  31. if (ok) *ok = 1; \
  32. if (next) *next = endptr; \
  33. return r; \
  34. err: \
  35. if (ok) *ok = 0; \
  36. if (next) *next = endptr; \
  37. return 0
  38. /** Extract a long from the start of <b>s</b>, in the given numeric
  39. * <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal,
  40. * octal, or hex number in the syntax of a C integer literal. If
  41. * there is unconverted data and <b>next</b> is provided, set
  42. * *<b>next</b> to the first unconverted character. An error has
  43. * occurred if no characters are converted; or if there are
  44. * unconverted characters and <b>next</b> is NULL; or if the parsed
  45. * value is not between <b>min</b> and <b>max</b>. When no error
  46. * occurs, return the parsed value and set *<b>ok</b> (if provided) to
  47. * 1. When an error occurs, return 0 and set *<b>ok</b> (if provided)
  48. * to 0.
  49. */
  50. long
  51. tor_parse_long(const char *s, int base, long min, long max,
  52. int *ok, char **next)
  53. {
  54. char *endptr;
  55. long r;
  56. if (base < 0) {
  57. if (ok)
  58. *ok = 0;
  59. return 0;
  60. }
  61. errno = 0;
  62. r = strtol(s, &endptr, base);
  63. CHECK_STRTOX_RESULT();
  64. }
  65. /** As tor_parse_long(), but return an unsigned long. */
  66. unsigned long
  67. tor_parse_ulong(const char *s, int base, unsigned long min,
  68. unsigned long max, int *ok, char **next)
  69. {
  70. char *endptr;
  71. unsigned long r;
  72. if (base < 0) {
  73. if (ok)
  74. *ok = 0;
  75. return 0;
  76. }
  77. errno = 0;
  78. r = strtoul(s, &endptr, base);
  79. CHECK_STRTOX_RESULT();
  80. }
  81. /** As tor_parse_long(), but return a double. */
  82. double
  83. tor_parse_double(const char *s, double min, double max, int *ok, char **next)
  84. {
  85. char *endptr;
  86. double r;
  87. errno = 0;
  88. r = strtod(s, &endptr);
  89. CHECK_STRTOX_RESULT();
  90. }
  91. /** As tor_parse_long, but return a uint64_t. Only base 10 is guaranteed to
  92. * work for now. */
  93. uint64_t
  94. tor_parse_uint64(const char *s, int base, uint64_t min,
  95. uint64_t max, int *ok, char **next)
  96. {
  97. char *endptr;
  98. uint64_t r;
  99. if (base < 0) {
  100. if (ok)
  101. *ok = 0;
  102. return 0;
  103. }
  104. errno = 0;
  105. #ifdef HAVE_STRTOULL
  106. r = (uint64_t)strtoull(s, &endptr, base);
  107. #elif defined(_WIN32)
  108. r = (uint64_t)_strtoui64(s, &endptr, base);
  109. #elif SIZEOF_LONG == 8
  110. r = (uint64_t)strtoul(s, &endptr, base);
  111. #else
  112. #error "I don't know how to parse 64-bit numbers."
  113. #endif /* defined(HAVE_STRTOULL) || ... */
  114. CHECK_STRTOX_RESULT();
  115. }