Coverage Report

Created: 2023-03-26 06:28

/src/httpd/srclib/apr/strings/apr_strings.c
Line
Count
Source (jump to first uncovered line)
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
 * contributor license agreements.  See the NOTICE file distributed with
3
 * this work for additional information regarding copyright ownership.
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
5
 * (the "License"); you may not use this file except in compliance with
6
 * the License.  You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
/*
17
 * Copyright (c) 1990, 1993
18
 *  The Regents of the University of California.  All rights reserved.
19
 *
20
 * Redistribution and use in source and binary forms, with or without
21
 * modification, are permitted provided that the following conditions
22
 * are met:
23
 * 1. Redistributions of source code must retain the above copyright
24
 *    notice, this list of conditions and the following disclaimer.
25
 * 2. Redistributions in binary form must reproduce the above copyright
26
 *    notice, this list of conditions and the following disclaimer in the
27
 *    documentation and/or other materials provided with the distribution.
28
 * 3. All advertising materials mentioning features or use of this software
29
 *    must display the following acknowledgement:
30
 *  This product includes software developed by the University of
31
 *  California, Berkeley and its contributors.
32
 * 4. Neither the name of the University nor the names of its contributors
33
 *    may be used to endorse or promote products derived from this software
34
 *    without specific prior written permission.
35
 *
36
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
37
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
40
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
42
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
44
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
45
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46
 * SUCH DAMAGE.
47
 */
48
49
#include "apr.h"
50
#include "apr_strings.h"
51
#include "apr_general.h"
52
#include "apr_private.h"
53
#include "apr_lib.h"
54
#define APR_WANT_STDIO
55
#define APR_WANT_STRFUNC
56
#include "apr_want.h"
57
58
#ifdef HAVE_STDDEF_H
59
#include <stddef.h> /* NULL */
60
#endif
61
62
#ifdef HAVE_STDLIB_H
63
#include <stdlib.h> /* strtol and strtoll */
64
#endif
65
66
/** this is used to cache lengths in apr_pstrcat */
67
8.48k
#define MAX_SAVED_LENGTHS  6
68
69
APR_DECLARE(char *) apr_pstrdup(apr_pool_t *a, const char *s)
70
41.9k
{
71
41.9k
    char *res;
72
41.9k
    apr_size_t len;
73
74
41.9k
    if (s == NULL) {
75
0
        return NULL;
76
0
    }
77
41.9k
    len = strlen(s) + 1;
78
41.9k
    res = apr_pmemdup(a, s, len);
79
41.9k
    return res;
80
41.9k
}
81
82
APR_DECLARE(char *) apr_pstrndup(apr_pool_t *a, const char *s, apr_size_t n)
83
199
{
84
199
    char *res;
85
199
    const char *end;
86
87
199
    if (s == NULL) {
88
0
        return NULL;
89
0
    }
90
199
    end = memchr(s, '\0', n);
91
199
    if (end != NULL)
92
0
        n = end - s;
93
199
    res = apr_palloc(a, n + 1);
94
199
    memcpy(res, s, n);
95
199
    res[n] = '\0';
96
199
    return res;
97
199
}
98
99
APR_DECLARE(char *) apr_pstrmemdup(apr_pool_t *a, const char *s, apr_size_t n)
100
6.67k
{
101
6.67k
    char *res;
102
103
6.67k
    if (s == NULL) {
104
0
        return NULL;
105
0
    }
106
6.67k
    res = apr_palloc(a, n + 1);
107
6.67k
    memcpy(res, s, n);
108
6.67k
    res[n] = '\0';
109
6.67k
    return res;
110
6.67k
}
111
112
APR_DECLARE(void *) apr_pmemdup(apr_pool_t *a, const void *m, apr_size_t n)
113
80.6k
{
114
80.6k
    void *res;
115
116
80.6k
    if (m == NULL)
117
0
  return NULL;
118
80.6k
    res = apr_palloc(a, n);
119
80.6k
    memcpy(res, m, n);
120
80.6k
    return res;
121
80.6k
}
122
123
APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *a, ...)
124
888
{
125
888
    char *cp, *argp, *res;
126
888
    apr_size_t saved_lengths[MAX_SAVED_LENGTHS];
127
888
    int nargs = 0;
128
129
    /* Pass one --- find length of required string */
130
131
888
    apr_size_t len = 0;
132
888
    va_list adummy;
133
134
888
    va_start(adummy, a);
135
136
5.12k
    while ((cp = va_arg(adummy, char *)) != NULL) {
137
4.24k
        apr_size_t cplen = strlen(cp);
138
4.24k
        if (nargs < MAX_SAVED_LENGTHS) {
139
4.10k
            saved_lengths[nargs++] = cplen;
140
4.10k
        }
141
4.24k
        len += cplen;
142
4.24k
    }
143
144
888
    va_end(adummy);
145
146
    /* Allocate the required string */
147
148
888
    res = (char *) apr_palloc(a, len + 1);
149
888
    cp = res;
150
151
    /* Pass two --- copy the argument strings into the result space */
152
153
888
    va_start(adummy, a);
154
155
888
    nargs = 0;
156
5.12k
    while ((argp = va_arg(adummy, char *)) != NULL) {
157
4.24k
        if (nargs < MAX_SAVED_LENGTHS) {
158
4.10k
            len = saved_lengths[nargs++];
159
4.10k
        }
160
141
        else {
161
141
            len = strlen(argp);
162
141
        }
163
164
4.24k
        memcpy(cp, argp, len);
165
4.24k
        cp += len;
166
4.24k
    }
167
168
888
    va_end(adummy);
169
170
    /* Return the result string */
171
172
888
    *cp = '\0';
173
174
888
    return res;
175
888
}
176
177
APR_DECLARE(char *) apr_pstrcatv(apr_pool_t *a, const struct iovec *vec,
178
                                 apr_size_t nvec, apr_size_t *nbytes)
179
0
{
180
0
    apr_size_t i;
181
0
    apr_size_t len;
182
0
    const struct iovec *src;
183
0
    char *res;
184
0
    char *dst;
185
186
    /* Pass one --- find length of required string */
187
0
    len = 0;
188
0
    src = vec;
189
0
    for (i = nvec; i; i--) {
190
0
        len += src->iov_len;
191
0
        src++;
192
0
    }
193
0
    if (nbytes) {
194
0
        *nbytes = len;
195
0
    }
196
197
    /* Allocate the required string */
198
0
    res = (char *) apr_palloc(a, len + 1);
199
200
    /* Pass two --- copy the argument strings into the result space */
201
0
    src = vec;
202
0
    dst = res;
203
0
    for (i = nvec; i; i--) {
204
0
        memcpy(dst, src->iov_base, src->iov_len);
205
0
        dst += src->iov_len;
206
0
        src++;
207
0
    }
208
209
    /* Return the result string */
210
0
    *dst = '\0';
211
212
0
    return res;
213
0
}
214
215
#if defined(HAVE_WEAK_SYMBOLS)
216
void apr__memzero_explicit(void *buffer, apr_size_t size);
217
218
__attribute__ ((weak))
219
void apr__memzero_explicit(void *buffer, apr_size_t size)
220
0
{
221
0
    memset(buffer, 0, size);
222
0
}
223
#endif
224
225
APR_DECLARE(apr_status_t) apr_memzero_explicit(void *buffer, apr_size_t size)
226
0
{
227
#if defined(WIN32)
228
    SecureZeroMemory(buffer, size);
229
#elif defined(HAVE_EXPLICIT_BZERO)
230
0
    explicit_bzero(buffer, size);
231
#elif defined(HAVE_MEMSET_S)
232
    if (size) {
233
        return memset_s(buffer, (rsize_t)size, 0, (rsize_t)size);
234
    }
235
#elif defined(HAVE_WEAK_SYMBOLS)
236
    apr__memzero_explicit(buffer, size);
237
#else
238
    apr_size_t i;
239
    volatile unsigned char *volatile ptr = buffer;
240
    for (i = 0; i < size; ++i) {
241
        ptr[i] = 0;
242
    }
243
#endif
244
0
    return APR_SUCCESS;
245
0
}
246
247
#if (!APR_HAVE_MEMCHR)
248
void *memchr(const void *s, int c, size_t n)
249
{
250
    const char *cp;
251
252
    for (cp = s; n > 0; n--, cp++) {
253
        if (*cp == c)
254
            return (char *) cp; /* Casting away the const here */
255
    }
256
257
    return NULL;
258
}
259
#endif
260
261
#ifndef INT64_MAX
262
#define INT64_MAX  APR_INT64_C(0x7fffffffffffffff)
263
#endif
264
#ifndef INT64_MIN
265
#define INT64_MIN (-APR_INT64_C(0x7fffffffffffffff) - APR_INT64_C(1))
266
#endif
267
268
APR_DECLARE(apr_status_t) apr_strtoff(apr_off_t *offset, const char *nptr,
269
                                      char **endptr, int base)
270
0
{
271
0
    errno = 0;
272
0
    *offset = APR_OFF_T_STRFN(nptr, endptr, base);
273
0
    return APR_FROM_OS_ERROR(errno);
274
0
}
275
276
APR_DECLARE(apr_int64_t) apr_strtoi64(const char *nptr, char **endptr, int base)
277
1.26k
{
278
1.26k
#ifdef APR_INT64_STRFN
279
1.26k
    errno = 0;
280
1.26k
    return APR_INT64_STRFN(nptr, endptr, base);
281
#else
282
    const char *s;
283
    apr_int64_t acc;
284
    apr_int64_t val;
285
    int neg, any;
286
    char c;
287
288
    errno = 0;
289
    /*
290
     * Skip white space and pick up leading +/- sign if any.
291
     * If base is 0, allow 0x for hex and 0 for octal, else
292
     * assume decimal; if base is already 16, allow 0x.
293
     */
294
    s = nptr;
295
    do {
296
  c = *s++;
297
    } while (apr_isspace(c));
298
    if (c == '-') {
299
  neg = 1;
300
  c = *s++;
301
    } else {
302
  neg = 0;
303
  if (c == '+')
304
      c = *s++;
305
    }
306
    if ((base == 0 || base == 16) &&
307
  c == '0' && (*s == 'x' || *s == 'X')) {
308
      c = s[1];
309
      s += 2;
310
      base = 16;
311
    }
312
    if (base == 0)
313
  base = c == '0' ? 8 : 10;
314
    acc = any = 0;
315
    if (base < 2 || base > 36) {
316
  errno = EINVAL;
317
        if (endptr != NULL)
318
      *endptr = (char *)(any ? s - 1 : nptr);
319
        return acc;
320
    }
321
322
    /* The classic bsd implementation requires div/mod operators
323
     * to compute a cutoff.  Benchmarking proves that is very, very
324
     * evil to some 32 bit processors.  Instead, look for underflow
325
     * in both the mult and add/sub operation.  Unlike the bsd impl,
326
     * we also work strictly in a signed int64 word as we haven't
327
     * implemented the unsigned type in win32.
328
     *
329
     * Set 'any' if any `digits' consumed; make it negative to indicate
330
     * overflow.
331
     */
332
    val = 0;
333
    for ( ; ; c = *s++) {
334
        if (c >= '0' && c <= '9')
335
      c -= '0';
336
#if (('Z' - 'A') == 25)
337
  else if (c >= 'A' && c <= 'Z')
338
      c -= 'A' - 10;
339
  else if (c >= 'a' && c <= 'z')
340
      c -= 'a' - 10;
341
#elif APR_CHARSET_EBCDIC
342
  else if (c >= 'A' && c <= 'I')
343
      c -= 'A' - 10;
344
  else if (c >= 'J' && c <= 'R')
345
      c -= 'J' - 19;
346
  else if (c >= 'S' && c <= 'Z')
347
      c -= 'S' - 28;
348
  else if (c >= 'a' && c <= 'i')
349
      c -= 'a' - 10;
350
  else if (c >= 'j' && c <= 'r')
351
      c -= 'j' - 19;
352
  else if (c >= 's' && c <= 'z')
353
      c -= 'z' - 28;
354
#else
355
#error "CANNOT COMPILE apr_strtoi64(), only ASCII and EBCDIC supported"
356
#endif
357
  else
358
      break;
359
  if (c >= base)
360
      break;
361
  val *= base;
362
        if ( (any < 0)  /* already noted an over/under flow - short circuit */
363
           || (neg && (val > acc || (val -= c) > acc)) /* underflow */
364
           || (!neg && (val < acc || (val += c) < acc))) {       /* overflow */
365
            any = -1; /* once noted, over/underflows never go away */
366
#ifdef APR_STRTOI64_OVERFLOW_IS_BAD_CHAR
367
            break;
368
#endif
369
        } else {
370
            acc = val;
371
      any = 1;
372
        }
373
    }
374
375
    if (any < 0) {
376
  acc = neg ? INT64_MIN : INT64_MAX;
377
  errno = ERANGE;
378
    } else if (!any) {
379
  errno = EINVAL;
380
    }
381
    if (endptr != NULL)
382
  *endptr = (char *)(any ? s - 1 : nptr);
383
    return (acc);
384
#endif
385
1.26k
}
386
387
APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf)
388
0
{
389
0
    return apr_strtoi64(buf, NULL, 10);
390
0
}
391
392
APR_DECLARE(char *) apr_itoa(apr_pool_t *p, int n)
393
0
{
394
0
    const int BUFFER_SIZE = sizeof(int) * 3 + 2;
395
0
    char *buf = apr_palloc(p, BUFFER_SIZE);
396
0
    char *start = buf + BUFFER_SIZE - 1;
397
0
    unsigned int un;
398
0
    int negative;
399
0
    if (n < 0) {
400
0
  negative = 1;
401
0
  un = -n;
402
0
    }
403
0
    else {
404
0
  negative = 0;
405
0
        un = n;
406
0
    }
407
0
    *start = 0;
408
0
    do {
409
0
  *--start = '0' + (un % 10);
410
0
  un /= 10;
411
0
    } while (un);
412
0
    if (negative) {
413
0
  *--start = '-';
414
0
    }
415
0
    return start;
416
0
}
417
418
APR_DECLARE(char *) apr_ltoa(apr_pool_t *p, long n)
419
0
{
420
0
    const int BUFFER_SIZE = sizeof(long) * 3 + 2;
421
0
    char *buf = apr_palloc(p, BUFFER_SIZE);
422
0
    char *start = buf + BUFFER_SIZE - 1;
423
0
    int negative;
424
0
    unsigned int un;
425
0
    if (n < 0) {
426
0
  negative = 1;
427
0
  un = -n;
428
0
    }
429
0
    else {
430
0
  negative = 0;
431
0
        un = n;
432
0
    }
433
0
    *start = 0;
434
0
    do {
435
0
  *--start = (char)('0' + (un % 10));
436
0
  un /= 10;
437
0
    } while (un);
438
0
    if (negative) {
439
0
  *--start = '-';
440
0
    }
441
0
    return start;
442
0
}
443
444
APR_DECLARE(char *) apr_off_t_toa(apr_pool_t *p, apr_off_t n)
445
0
{
446
0
    const int BUFFER_SIZE = sizeof(apr_off_t) * 3 + 2;
447
0
    char *buf = apr_palloc(p, BUFFER_SIZE);
448
0
    char *start = buf + BUFFER_SIZE - 1;
449
0
    int negative;
450
0
    if (n < 0) {
451
0
  negative = 1;
452
0
  n = -n;
453
0
    }
454
0
    else {
455
0
  negative = 0;
456
0
    }
457
0
    *start = 0;
458
0
    do {
459
0
  *--start = '0' + (char)(n % 10);
460
0
  n /= 10;
461
0
    } while (n);
462
0
    if (negative) {
463
0
  *--start = '-';
464
0
    }
465
0
    return start;
466
0
}
467
468
APR_DECLARE(char *) apr_strfsize(apr_off_t size, char *buf)
469
0
{
470
0
    const char ord[] = "KMGTPE";
471
0
    const char *o = ord;
472
0
    int remain;
473
474
0
    if (size < 0) {
475
0
        return strcpy(buf, "  - ");
476
0
    }
477
0
    if (size < 973) {
478
0
        if (apr_snprintf(buf, 5, "%3d ", (int) size) < 0)
479
0
            return strcpy(buf, "****");
480
0
        return buf;
481
0
    }
482
0
    do {
483
0
        remain = (int)(size & 1023);
484
0
        size >>= 10;
485
0
        if (size >= 973) {
486
0
            ++o;
487
0
            continue;
488
0
        }
489
0
        if (size < 9 || (size == 9 && remain < 973)) {
490
0
            if ((remain = ((remain * 5) + 256) / 512) >= 10)
491
0
                ++size, remain = 0;
492
0
            if (apr_snprintf(buf, 5, "%d.%d%c", (int) size, remain, *o) < 0)
493
0
                return strcpy(buf, "****");
494
0
            return buf;
495
0
        }
496
0
        if (remain >= 512)
497
0
            ++size;
498
0
        if (apr_snprintf(buf, 5, "%3d%c", (int) size, *o) < 0)
499
0
            return strcpy(buf, "****");
500
0
        return buf;
501
0
    } while (1);
502
0
}
503