Coverage Report

Created: 2025-07-11 06:49

/src/unit/src/nxt_parse.c
Line
Count
Source (jump to first uncovered line)
1
2
/*
3
 * Copyright (C) Igor Sysoev
4
 * Copyright (C) NGINX, Inc.
5
 */
6
7
#include <nxt_main.h>
8
9
10
/*
11
 * nxt_int_parse() returns size_t value >= 0 on success,
12
 * -1 on failure, and -2 on overflow.
13
 */
14
15
nxt_int_t
16
nxt_int_parse(const u_char *p, size_t length)
17
0
{
18
0
    u_char      c;
19
0
    nxt_uint_t  val;
20
21
0
    static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10;
22
0
    static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10;
23
24
0
    if (nxt_fast_path(length != 0)) {
25
26
0
        val = 0;
27
28
0
        do {
29
0
            c = *p++;
30
31
            /* Values below '0' become >= 208. */
32
0
            c = c - '0';
33
34
0
            if (nxt_slow_path(c > 9)) {
35
0
                return -1;
36
0
            }
37
38
0
            if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) {
39
                /* An overflow. */
40
0
                return -2;
41
0
            }
42
43
0
            val = val * 10 + c;
44
45
0
            length--;
46
47
0
        } while (length != 0);
48
49
0
        return val;
50
0
    }
51
52
0
    return -1;
53
0
}
54
55
56
/*
57
 * nxt_size_t_parse() returns size_t value >= 0 on success,
58
 * -1 on failure, and -2 on overflow.
59
 */
60
61
ssize_t
62
nxt_size_t_parse(const u_char *p, size_t length)
63
0
{
64
0
    u_char  c;
65
0
    size_t  val;
66
67
0
    static const size_t cutoff = NXT_SIZE_T_MAX / 10;
68
0
    static const size_t cutlim = NXT_SIZE_T_MAX % 10;
69
70
0
    if (nxt_fast_path(length != 0)) {
71
72
0
        val = 0;
73
74
0
        do {
75
0
            c = *p++;
76
77
            /* Values below '0' become >= 208. */
78
0
            c = c - '0';
79
80
0
            if (nxt_slow_path(c > 9)) {
81
0
                return -1;
82
0
            }
83
84
0
            if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) {
85
                /* An overflow. */
86
0
                return -2;
87
0
            }
88
89
0
            val = val * 10 + c;
90
91
0
            length--;
92
93
0
        } while (length != 0);
94
95
0
        return val;
96
0
    }
97
98
0
    return -1;
99
0
}
100
101
102
/*
103
 * nxt_size_parse() parses size string with optional K or M units and
104
 * returns size_t value >= 0 on success, -1 on failure, and -2 on overflow.
105
 */
106
107
ssize_t
108
nxt_size_parse(const u_char *p, size_t length)
109
0
{
110
0
    u_char      unit;
111
0
    ssize_t     val, max;
112
0
    nxt_uint_t  shift;
113
114
0
    if (nxt_fast_path(length != 0)) {
115
116
0
        length--;
117
118
        /* Upper case. */
119
0
        unit = p[length] & ~0x20;
120
121
0
        switch (unit) {
122
123
0
        case 'G':
124
0
            max = NXT_SIZE_T_MAX >> 30;
125
0
            shift = 30;
126
0
            break;
127
128
0
        case 'M':
129
0
            max = NXT_SIZE_T_MAX >> 20;
130
0
            shift = 20;
131
0
            break;
132
133
0
        case 'K':
134
0
            max = NXT_SIZE_T_MAX >> 10;
135
0
            shift = 10;
136
0
            break;
137
138
0
        default:
139
0
            return nxt_size_t_parse(p, length + 1);
140
0
        }
141
142
0
        val = nxt_size_t_parse(p, length);
143
144
0
        if (nxt_fast_path(val >= 0)) {
145
146
0
            if (nxt_slow_path(val > max)) {
147
                /* An overflow. */
148
0
                return -2;
149
0
            }
150
151
0
            val <<= shift;
152
0
        }
153
154
0
        return val;
155
0
    }
156
157
0
    return -1;
158
0
}
159
160
161
/*
162
 * nxt_off_t_parse() returns nxt_off_t value >= 0 on success,
163
 * -1 on failure, and -2 on overflow.
164
 */
165
166
nxt_off_t
167
nxt_off_t_parse(const u_char *p, size_t length)
168
435
{
169
435
    u_char      c;
170
435
    nxt_uoff_t  val;
171
172
435
    static const nxt_uoff_t cutoff = NXT_OFF_T_MAX / 10;
173
435
    static const nxt_uoff_t cutlim = NXT_OFF_T_MAX % 10;
174
175
435
    if (nxt_fast_path(length != 0)) {
176
177
421
        val = 0;
178
179
4.60k
        do {
180
4.60k
            c = *p++;
181
182
            /* Values below '0' become >= 208. */
183
4.60k
            c = c - '0';
184
185
4.60k
            if (nxt_slow_path(c > 9)) {
186
6
                return -1;
187
6
            }
188
189
4.60k
            if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) {
190
                /* An overflow. */
191
60
                return -2;
192
60
            }
193
194
4.54k
            val = val * 10 + c;
195
196
4.54k
            length--;
197
198
4.54k
        } while (length != 0);
199
200
355
        return val;
201
421
    }
202
203
14
    return -1;
204
435
}
205
206
207
/*
208
 * nxt_str_int_parse() returns nxt_int_t value >= 0 on success,
209
 * -1 on failure, and -2 on overflow and also updates the 's' argument.
210
 */
211
212
nxt_int_t
213
nxt_str_int_parse(nxt_str_t *s)
214
0
{
215
0
    u_char      c, *p;
216
0
    size_t      length;
217
0
    nxt_uint_t  val;
218
219
0
    static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10;
220
0
    static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10;
221
222
0
    length = s->length;
223
224
0
    if (nxt_slow_path(length == 0)) {
225
0
        return -1;
226
0
    }
227
228
0
    p = s->start;
229
0
    val = 0;
230
231
0
    do {
232
0
        c = *p;
233
234
        /* Values below '0' become >= 208. */
235
0
        c = c - '0';
236
237
0
        if (c > 9) {
238
0
            break;
239
0
        }
240
241
0
        if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) {
242
            /* An overflow. */
243
0
            return -2;
244
0
        }
245
246
0
        val = val * 10 + c;
247
248
0
        p++;
249
0
        length--;
250
251
0
    } while (length != 0);
252
253
0
    s->length = length;
254
0
    s->start = p;
255
256
0
    return val;
257
0
}
258
259
260
/*
261
 * nxt_number_parse() returns a double value >= 0 and updates the start
262
 * argument on success, or returns -1 on failure or -2 on overflow.
263
 */
264
265
double
266
nxt_number_parse(const u_char **start, const u_char *end)
267
0
{
268
0
    u_char        c;
269
0
    nxt_bool_t    overflow;
270
0
    nxt_uint_t    integral, frac, power;
271
0
    const u_char  *p;
272
273
0
    static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10;
274
0
    static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10;
275
276
0
    p = *start;
277
0
    integral = 0;
278
279
0
    while (p < end) {
280
0
        c = *p;
281
282
0
        if (c == '.') {
283
0
            goto dot;
284
0
        }
285
286
        /* Values below '0' become >= 208. */
287
0
        c = c - '0';
288
289
0
        if (c > 9) {
290
0
            break;
291
0
        }
292
293
0
        overflow = nxt_expect(0, (integral >= cutoff
294
0
                                  && (integral > cutoff || c > cutlim)));
295
296
0
        if (overflow) {
297
0
            return -2;
298
0
        }
299
300
0
        integral = integral * 10 + c;
301
302
0
        p++;
303
0
    }
304
305
0
    if (nxt_fast_path(p != *start)) {
306
0
        *start = p;
307
0
        return integral;
308
0
    }
309
310
    /* No value. */
311
0
    return -1;
312
313
0
dot:
314
315
0
    if (nxt_slow_path(p == *start)) {
316
        /* No leading digit before dot. */
317
0
        return -1;
318
0
    }
319
320
0
    frac = 0;
321
0
    power = 1;
322
323
0
    for (p++; p < end; p++) {
324
0
        c = *p;
325
326
        /* Values below '0' become >= 208. */
327
0
        c = c - '0';
328
329
0
        if (c > 9) {
330
0
            break;
331
0
        }
332
333
0
        overflow = nxt_expect(0, (frac >= cutoff && (frac > cutoff
334
0
                                                     || c > cutlim))
335
0
                                 || power > cutoff);
336
337
0
        if (overflow) {
338
0
            return -2;
339
0
        }
340
341
0
        frac = frac * 10 + c;
342
0
        power *= 10;
343
0
    }
344
345
0
    *start = p;
346
347
0
    return integral + (double) frac / power;
348
0
}