]>
Commit | Line | Data |
---|---|---|
997358a6 MW |
1 | /* |
2 | * convert from text form of unsigned long to binary | |
3 | * Copyright (C) 2000 Henry Spencer. | |
4 | * | |
5 | * This library is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU Library General Public License as published by | |
7 | * the Free Software Foundation; either version 2 of the License, or (at your | |
8 | * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. | |
9 | * | |
10 | * This library is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public | |
13 | * License for more details. | |
14 | * | |
15 | * RCSID $Id: ttoul.c,v 1.1 2004/03/15 20:35:26 as Exp $ | |
16 | */ | |
17 | #include "internal.h" | |
18 | #include "freeswan.h" | |
19 | ||
20 | /* | |
21 | - ttoul - convert text substring to unsigned long number | |
22 | */ | |
23 | const char * /* NULL for success, else string literal */ | |
24 | ttoul(src, srclen, base, resultp) | |
25 | const char *src; | |
26 | size_t srclen; /* 0 means strlen(src) */ | |
27 | int base; /* 0 means figure it out */ | |
28 | unsigned long *resultp; | |
29 | { | |
30 | const char *stop; | |
31 | static char hex[] = "0123456789abcdef"; | |
32 | static char uchex[] = "0123456789ABCDEF"; | |
33 | int d; | |
34 | char c; | |
35 | char *p; | |
36 | unsigned long r; | |
37 | unsigned long rlimit; | |
38 | int dlimit; | |
39 | ||
40 | if (srclen == 0) | |
41 | srclen = strlen(src); | |
42 | if (srclen == 0) | |
43 | return "empty string"; | |
44 | ||
45 | if (base == 0) { | |
46 | if (srclen > 2 && *src == '0' && | |
47 | (*(src+1) == 'x' || *(src+1) == 'X')) | |
48 | return ttoul(src+2, srclen-2, 16, resultp); | |
49 | if (srclen > 1 && *src == '0') | |
50 | return ttoul(src+1, srclen-1, 8, resultp); | |
51 | return ttoul(src, srclen, 10, resultp); | |
52 | } | |
53 | if (base != 8 && base != 10 && base != 16) | |
54 | return "unsupported number base"; | |
55 | ||
56 | r = 0; | |
57 | stop = src + srclen; | |
58 | if (base == 16) { | |
59 | while (src < stop) { | |
60 | c = *src++; | |
61 | p = strchr(hex, c); | |
62 | if (p != NULL) | |
63 | d = p - hex; | |
64 | else { | |
65 | p = strchr(uchex, c); | |
66 | if (p == NULL) | |
67 | return "non-hex digit in hex number"; | |
68 | d = p - uchex; | |
69 | } | |
70 | r = (r << 4) | d; | |
71 | } | |
72 | /* defer length check to catch invalid digits first */ | |
73 | if (srclen > sizeof(unsigned long) * 2) | |
74 | return "hex number too long"; | |
75 | } else { | |
76 | rlimit = ULONG_MAX / base; | |
77 | dlimit = (int)(ULONG_MAX - rlimit*base); | |
78 | while (src < stop) { | |
79 | c = *src++; | |
80 | d = c - '0'; | |
81 | if (d < 0 || d >= base) | |
82 | return "non-digit in number"; | |
83 | if (r > rlimit || (r == rlimit && d > dlimit)) | |
84 | return "unsigned-long overflow"; | |
85 | r = r*base + d; | |
86 | } | |
87 | } | |
88 | ||
89 | *resultp = r; | |
90 | return NULL; | |
91 | } |