/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 | | |