]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ntp/libntp/mstolfp.c
Fix multiple denial of service in ntpd.
[FreeBSD/FreeBSD.git] / contrib / ntp / libntp / mstolfp.c
1 /*
2  * mstolfp - convert an ascii string in milliseconds to an l_fp number
3  */
4 #include <config.h>
5 #include <stdio.h>
6 #include <ctype.h>
7
8 #include "ntp_fp.h"
9 #include "ntp_stdlib.h"
10
11 int
12 mstolfp(
13         const char *str,
14         l_fp *lfp
15         )
16 {
17         register const char *cp;
18         register char *bp;
19         register const char *cpdec;
20         char buf[100];
21
22         /*
23          * We understand numbers of the form:
24          *
25          * [spaces][-|+][digits][.][digits][spaces|\n|\0]
26          *
27          * This is one enormous hack.  Since I didn't feel like
28          * rewriting the decoding routine for milliseconds, what
29          * is essentially done here is to make a copy of the string
30          * with the decimal moved over three places so the seconds
31          * decoding routine can be used.
32          */
33         bp = buf;
34         cp = str;
35         while (isspace((unsigned char)*cp))
36             cp++;
37         
38         if (*cp == '-' || *cp == '+') {
39                 *bp++ = *cp++;
40         }
41
42         if (*cp != '.' && !isdigit((unsigned char)*cp))
43             return 0;
44
45
46         /*
47          * Search forward for the decimal point or the end of the string.
48          */
49         cpdec = cp;
50         while (isdigit((unsigned char)*cpdec))
51             cpdec++;
52
53         /*
54          * Found something.  If we have more than three digits copy the
55          * excess over, else insert a leading 0.
56          */
57         if ((cpdec - cp) > 3) {
58                 do {
59                         *bp++ = (char)*cp++;
60                 } while ((cpdec - cp) > 3);
61         } else {
62                 *bp++ = '0';
63         }
64
65         /*
66          * Stick the decimal in.  If we've got less than three digits in
67          * front of the millisecond decimal we insert the appropriate number
68          * of zeros.
69          */
70         *bp++ = '.';
71         if ((cpdec - cp) < 3) {
72                 size_t i = 3 - (cpdec - cp);
73                 do {
74                         *bp++ = '0';
75                 } while (--i > 0);
76         }
77
78         /*
79          * Copy the remainder up to the millisecond decimal.  If cpdec
80          * is pointing at a decimal point, copy in the trailing number too.
81          */
82         while (cp < cpdec)
83             *bp++ = (char)*cp++;
84         
85         if (*cp == '.') {
86                 cp++;
87                 while (isdigit((unsigned char)*cp))
88                     *bp++ = (char)*cp++;
89         }
90         *bp = '\0';
91
92         /*
93          * Check to make sure the string is properly terminated.  If
94          * so, give the buffer to the decoding routine.
95          */
96         if (*cp != '\0' && !isspace((unsigned char)*cp))
97             return 0;
98         return atolfp(buf, lfp);
99 }