fork download
  1. #include <errno.h>
  2. #include <assert.h>
  3. #include <inttypes.h>
  4. #include <locale.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8.  
  9. int safe_atou(const char *s, unsigned *ret_u) {
  10. char *x = NULL;
  11. unsigned long l;
  12.  
  13. assert(s);
  14. assert(ret_u);
  15.  
  16. /* strtoul() is happy to parse negative values, and silently
  17.   * converts them to unsigned values without generating an
  18.   * error. We want a clean error, hence let's look for the "-"
  19.   * prefix on our own, and generate an error. But let's do so
  20.   * only after strtoul() validated that the string is clean
  21.   * otherwise, so that we return EINVAL preferably over
  22.   * ERANGE. */
  23.  
  24.  
  25. errno = 0;
  26. l = strtoul(s, &x, 0);
  27. if (errno > 0)
  28. return -errno;
  29. if (!x || x == s || *x)
  30. return -EINVAL;
  31. if (s[0] == '-')
  32. return -ERANGE;
  33. if ((unsigned long) (unsigned) l != l)
  34. return -ERANGE;
  35.  
  36. *ret_u = (unsigned) l;
  37. return 0;
  38. }
  39.  
  40. int main(void) {
  41. unsigned res = 1337;
  42. const char *tests[] = {"0day", "day0", "42", "-0", "-1", "0", "1337", "0p3nn3t", 0};
  43. const char **test = tests;
  44. while (*test) {
  45. int err = safe_atou(*test, &res);
  46. printf("\ninput: %.6s, err: %d, val: %i", *test, err, res);
  47. test++;
  48. }
  49.  
  50. }
  51.  
  52.  
Success #stdin #stdout 0s 9432KB
stdin
Standard input is empty
stdout
input: 0day, err: -22, val: 1337
input: day0, err: -22, val: 1337
input: 42, err: 0, val: 42
input: -0, err: -34, val: 42
input: -1, err: -34, val: 42
input: 0, err: 0, val: 0
input: 1337, err: 0, val: 1337
input: 0p3nn3, err: -22, val: 1337