Apache HTTPD
teststr.c
Go to the documentation of this file.
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#include "testutil.h"
18
19#include <stdlib.h>
20#include <stdio.h>
21#include <string.h>
22
23#if APR_HAVE_LIMITS_H
24#include <limits.h>
25#endif
26
27#include "apr_general.h"
28#include "apr_strings.h"
29#include "apr_cstr.h"
30#include "apr_errno.h"
31
32/* I haven't bothered to check for APR_ENOTIMPL here, AFAIK, all string
33 * functions exist on all platforms.
34 */
35
36static void test_strtok(abts_case *tc, void *data)
37{
38 struct {
39 char *input;
40 char *sep;
41 }
42 cases[] = {
43 {
44 "",
45 "Z"
46 },
47 {
48 " asdf jkl; 77889909 \r\n\1\2\3Z",
49 " \r\n\3\2\1"
50 },
51 {
52 NULL, /* but who cares if apr_strtok() segfaults? */
53 " \t"
54 },
55#if 0 /* don't do this... you deserve to segfault */
56 {
57 "a b c ",
58 NULL
59 },
60#endif
61 {
62 " a b c ",
63 ""
64 },
65 {
66 "a b c ",
67 " "
68 }
69 };
70 int curtc;
71
72 for (curtc = 0; curtc < sizeof cases / sizeof cases[0]; curtc++) {
73 char *retval1, *retval2;
74 char *str1, *str2;
75 char *state;
76
79
80 do {
81 retval1 = apr_strtok(str1, cases[curtc].sep, &state);
83
84 if (!retval1) {
85 ABTS_TRUE(tc, retval2 == NULL);
86 }
87 else {
88 ABTS_TRUE(tc, retval2 != NULL);
90 }
91
92 str1 = str2 = NULL; /* make sure we pass NULL on subsequent calls */
93 } while (retval1);
94 }
95}
96
97static void snprintf_noNULL(abts_case *tc, void *data)
98{
99 char buff[100];
100 char *testing = apr_palloc(p, 10);
101
102 testing[0] = 't';
103 testing[1] = 'e';
104 testing[2] = 's';
105 testing[3] = 't';
106 testing[4] = 'i';
107 testing[5] = 'n';
108 testing[6] = 'g';
109
110 /* If this test fails, we are going to seg fault. */
111 apr_snprintf(buff, sizeof(buff), "%.*s", 7, testing);
113}
114
115static void snprintf_0NULL(abts_case *tc, void *data)
116{
117 int rv;
118
119 rv = apr_snprintf(NULL, 0, "%sBAR", "FOO");
120 ABTS_INT_EQUAL(tc, 6, rv);
121}
122
123static void snprintf_0nonNULL(abts_case *tc, void *data)
124{
125 int rv;
126 char *buff = "testing";
127
128 rv = apr_snprintf(buff, 0, "%sBAR", "FOO");
129 ABTS_INT_EQUAL(tc, 6, rv);
130 ABTS_ASSERT(tc, "buff unmangled", strcmp(buff, "FOOBAR") != 0);
131}
132
133static void snprintf_underflow(abts_case *tc, void *data)
134{
135 char buf[20];
136 int rv;
137
138 rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.0001);
139 ABTS_INT_EQUAL(tc, 4, rv);
140 ABTS_STR_EQUAL(tc, "0.00", buf);
141
142 rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.001);
143 ABTS_INT_EQUAL(tc, 4, rv);
144 ABTS_STR_EQUAL(tc, "0.00", buf);
145
146 rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.01);
147 ABTS_INT_EQUAL(tc, 4, rv);
148 ABTS_STR_EQUAL(tc, "0.01", buf);
149}
150
151static void string_error(abts_case *tc, void *data)
152{
153 char buf[128], *rv;
155
156 buf[0] = '\0';
157 rv = apr_strerror(APR_ENOENT, buf, sizeof buf);
158 ABTS_PTR_EQUAL(tc, buf, rv);
159 ABTS_TRUE(tc, strlen(buf) > 0);
160
161 rv = apr_strerror(APR_TIMEUP, buf, sizeof buf);
162 ABTS_PTR_EQUAL(tc, buf, rv);
163 ABTS_STR_EQUAL(tc, "The timeout specified has expired", buf);
164
165 /* throw some randomish numbers at it to check for robustness */
166 for (n = 1; n < 1000000; n *= 2) {
167 apr_strerror(n, buf, sizeof buf);
168 }
169}
170
171#define SIZE 180000
172static void string_long(abts_case *tc, void *data)
173{
174 char s[SIZE + 1];
175
176 memset(s, 'A', SIZE);
177 s[SIZE] = '\0';
178
179 apr_psprintf(p, "%s", s);
180}
181
182/* ### FIXME: apr.h/apr_strings.h should provide these! */
183#define MY_LLONG_MAX (APR_INT64_C(9223372036854775807))
184#define MY_LLONG_MIN (-MY_LLONG_MAX - APR_INT64_C(1))
185
186static void string_strtoi64(abts_case *tc, void *data)
187{
188 static const struct {
189 int errnum, base;
190 const char *in, *end;
192 } ts[] = {
193
194 /* base 10 tests */
195 { 0, 10, "123545", NULL, APR_INT64_C(123545) },
196 { 0, 10, " 123545", NULL, APR_INT64_C(123545) },
197 { 0, 10, " +123545", NULL, APR_INT64_C(123545) },
198 { 0, 10, "-123545", NULL, APR_INT64_C(-123545) },
199 { 0, 10, " 00000123545", NULL, APR_INT64_C(123545) },
200 { 0, 10, "123545ZZZ", "ZZZ", APR_INT64_C(123545) },
201 { 0, 10, " 123545 ", " ", APR_INT64_C(123545) },
202
203 /* base 16 tests */
204 { 0, 16, "1E299", NULL, APR_INT64_C(123545) },
205 { 0, 16, "1e299", NULL, APR_INT64_C(123545) },
206 { 0, 16, "0x1e299", NULL, APR_INT64_C(123545) },
207 { 0, 16, "0X1E299", NULL, APR_INT64_C(123545) },
208 { 0, 16, "+1e299", NULL, APR_INT64_C(123545) },
209 { 0, 16, "-1e299", NULL, APR_INT64_C(-123545) },
210 { 0, 16, " -1e299", NULL, APR_INT64_C(-123545) },
211
212 /* automatic base detection tests */
213 { 0, 0, "123545", NULL, APR_INT64_C(123545) },
214 { 0, 0, "0x1e299", NULL, APR_INT64_C(123545) },
215 { 0, 0, " 0x1e299", NULL, APR_INT64_C(123545) },
216 { 0, 0, "+0x1e299", NULL, APR_INT64_C(123545) },
217 { 0, 0, "-0x1e299", NULL, APR_INT64_C(-123545) },
218
219 /* large number tests */
220 { 0, 10, "8589934605", NULL, APR_INT64_C(8589934605) },
221 { 0, 10, "-8589934605", NULL, APR_INT64_C(-8589934605) },
222 { 0, 16, "0x20000000D", NULL, APR_INT64_C(8589934605) },
223 { 0, 16, "-0x20000000D", NULL, APR_INT64_C(-8589934605) },
224 { 0, 16, " 0x20000000D", NULL, APR_INT64_C(8589934605) },
225 { 0, 16, " 0x20000000D", NULL, APR_INT64_C(8589934605) },
226
227 /* error cases */
228 { ERANGE, 10, "999999999999999999999999999999999", "", MY_LLONG_MAX },
229 { ERANGE, 10, "-999999999999999999999999999999999", "", MY_LLONG_MIN },
230
231#if 0
232 /* C99 doesn't require EINVAL for an invalid range. */
233 { EINVAL, 99, "", (void *)-1 /* don't care */, 0 },
234#endif
235
236 /* some strtoll implementations give EINVAL when no conversion
237 * is performed. */
238 { -1 /* don't care */, 10, "zzz", "zzz", APR_INT64_C(0) },
239 { -1 /* don't care */, 10, "", NULL, APR_INT64_C(0) }
240
241 };
242 int n;
243
244 for (n = 0; n < sizeof(ts)/sizeof(ts[0]); n++) {
245 char *end = "end ptr not changed";
247 int errnum;
248
249 errno = 0;
250 result = apr_strtoi64(ts[n].in, &end, ts[n].base);
251 errnum = errno;
252
253 ABTS_ASSERT(tc,
254 apr_psprintf(p, "for '%s': result was %" APR_INT64_T_FMT
255 " not %" APR_INT64_T_FMT, ts[n].in,
256 result, ts[n].result),
257 result == ts[n].result);
258
259 if (ts[n].errnum != -1) {
260 ABTS_ASSERT(tc,
261 apr_psprintf(p, "for '%s': errno was %d not %d", ts[n].in,
262 errnum, ts[n].errnum),
263 ts[n].errnum == errnum);
264 }
265
266 if (ts[n].end == NULL) {
267 /* end must point to NUL terminator of .in */
268 ABTS_PTR_EQUAL(tc, ts[n].in + strlen(ts[n].in), end);
269 } else if (ts[n].end != (void *)-1) {
270 ABTS_ASSERT(tc,
271 apr_psprintf(p, "for '%s', end was '%s' not '%s'",
272 ts[n].in, end, ts[n].end),
273 strcmp(ts[n].end, end) == 0);
274 }
275 }
276}
277
278static void string_strtoff(abts_case *tc, void *data)
279{
281
282 ABTS_ASSERT(tc, "strtoff fails on out-of-range integer",
283 apr_strtoff(&off, "999999999999999999999999999999",
284 NULL, 10) != APR_SUCCESS);
285
286 ABTS_ASSERT(tc, "strtoff failed for 1234",
287 apr_strtoff(&off, "1234", NULL, 10) == APR_SUCCESS);
288
289 ABTS_ASSERT(tc, "strtoff failed to parse 1234", off == 1234);
290}
291
292/* random-ish checks for strfsize buffer overflows */
293static void overflow_strfsize(abts_case *tc, void *data)
294{
296 char buf[7];
297
298 buf[5] = '$';
299 buf[6] = '@';
300
301 for (off = -9999; off < 20000; off++) {
303 }
304 for (; off < 9999999; off += 9) {
306 }
307 for (; off < 999999999; off += 999) {
309 }
310 for (off = LONG_MAX; off > 1; off /= 2) {
312 if (sizeof(apr_off_t) > sizeof(long) || off < LONG_MAX)
313 apr_strfsize(off + 1, buf);
314 apr_strfsize(off - 1, buf);
315 }
316
317 ABTS_ASSERT(tc, "strfsize overflowed", buf[5] == '$');
318 ABTS_ASSERT(tc, "strfsize overflowed", buf[6] == '@');
319}
320
321static void string_strfsize(abts_case *tc, void *data)
322{
323 static const struct {
325 const char *buf;
326 } ts[] = {
327 { -1, " - " },
328 { 0, " 0 " },
329 { 666, "666 " },
330 { 1024, "1.0K" },
331 { 1536, "1.5K" },
332 { 2048, "2.0K" },
333 { 1293874, "1.2M" },
334 { 9999999, "9.5M" },
335 { 103809024, " 99M" },
336 { 1047527424, "1.0G" } /* "999M" would be more correct */
337 };
339
340 for (n = 0; n < sizeof(ts)/sizeof(ts[0]); n++) {
341 char buf[6], *ret;
342
343 buf[5] = '%';
344
345 ret = apr_strfsize(ts[n].size, buf);
346 ABTS_ASSERT(tc, "strfsize returned wrong buffer", ret == buf);
347 ABTS_ASSERT(tc, "strfsize overflowed", buf[5] == '%');
348
349 ABTS_STR_EQUAL(tc, ts[n].buf, ret);
350 }
351}
352
353static void string_cpystrn(abts_case *tc, void *data)
354{
355 char buf[6], *ret;
356
357 buf[5] = 'Z';
358
359 ret = apr_cpystrn(buf, "123456", 5);
360
361 ABTS_STR_EQUAL(tc, "1234", buf);
362 ABTS_PTR_EQUAL(tc, buf + 4, ret);
363 ABTS_TRUE(tc, *ret == '\0');
364 ABTS_TRUE(tc, ret[1] == 'Z');
365}
366
367static void snprintf_overflow(abts_case *tc, void *data)
368{
369 char buf[4];
370 int rv;
371
372 buf[2] = '4';
373 buf[3] = '2';
374
375 rv = apr_snprintf(buf, 2, "%s", "a");
376 ABTS_INT_EQUAL(tc, 1, rv);
377
378 rv = apr_snprintf(buf, 2, "%s", "abcd");
379 ABTS_INT_EQUAL(tc, 1, rv);
380
381 ABTS_STR_EQUAL(tc, "a", buf);
382
383 /* Check the buffer really hasn't been overflowed. */
384 ABTS_TRUE(tc, buf[2] == '4' && buf[3] == '2');
385}
386
387static void skip_prefix(abts_case *tc, void *data)
388{
389 ABTS_STR_EQUAL(tc, apr_cstr_skip_prefix("12345", "12345"), "");
390 ABTS_STR_EQUAL(tc, apr_cstr_skip_prefix("12345", "123"), "45");
391 ABTS_STR_EQUAL(tc, apr_cstr_skip_prefix("12345", ""), "12345");
392 ABTS_STR_EQUAL(tc, apr_cstr_skip_prefix("12345", "23"), NULL);
394 ABTS_STR_EQUAL(tc, apr_cstr_skip_prefix("", ""), "");
396}
397
398static void pstrcat(abts_case *tc, void *data)
399{
400 ABTS_STR_EQUAL(tc, apr_pstrcat(p, "a", "bc", "def", NULL),
401 "abcdef");
402 ABTS_STR_EQUAL(tc, apr_pstrcat(p, NULL), "");
404 "a", "b", "c", "d", "e",
405 "f", "g", "h", "i", "j",
406 "1", "2", "3", "4", "5",
407 NULL),
408 "abcdefghij12345");
409}
410
433
int n
Definition ap_regex.h:278
const char * buff
Definition ap_regex.h:186
void abts_run_test(abts_suite *ts, test_func f, void *value)
Definition abts.c:175
#define ABTS_PTR_EQUAL(a, b, c)
Definition abts.h:126
#define ABTS_TRUE(a, b)
Definition abts.h:127
#define ADD_SUITE(suite)
Definition abts.h:67
#define ABTS_STR_NEQUAL(a, b, c, d)
Definition abts.h:124
#define ABTS_STR_EQUAL(a, b, c)
Definition abts.h:123
#define ABTS_ASSERT(a, b, c)
Definition abts.h:130
#define ABTS_INT_EQUAL(a, b, c)
Definition abts.h:109
C string goodies.
APR Error Codes.
APR Miscellaneous library routines.
APR Strings library.
ap_conf_vector_t * base
const unsigned char * buf
Definition util_md5.h:50
#define APR_TIMEUP
Definition apr_errno.h:450
#define APR_ENOENT
Definition apr_errno.h:662
apr_dbd_t int errnum
Definition apr_dbd.h:353
apr_size_t size
const char * str2
Definition apr_cstr.h:161
const char * input
Definition apr_cstr.h:93
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
void * data
apr_array_header_t ** result
const char * sep
const char char ** end
const char * s
Definition apr_strings.h:95
apr_int32_t in
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
static void snprintf_underflow(abts_case *tc, void *data)
Definition teststr.c:133
static void string_strtoff(abts_case *tc, void *data)
Definition teststr.c:278
#define MY_LLONG_MAX
Definition teststr.c:183
static void test_strtok(abts_case *tc, void *data)
Definition teststr.c:36
static void skip_prefix(abts_case *tc, void *data)
Definition teststr.c:387
static void string_error(abts_case *tc, void *data)
Definition teststr.c:151
static void snprintf_noNULL(abts_case *tc, void *data)
Definition teststr.c:97
#define SIZE
Definition teststr.c:171
static void snprintf_overflow(abts_case *tc, void *data)
Definition teststr.c:367
static void overflow_strfsize(abts_case *tc, void *data)
Definition teststr.c:293
static void snprintf_0NULL(abts_case *tc, void *data)
Definition teststr.c:115
static void string_cpystrn(abts_case *tc, void *data)
Definition teststr.c:353
#define MY_LLONG_MIN
Definition teststr.c:184
static void string_strtoi64(abts_case *tc, void *data)
Definition teststr.c:186
abts_suite * teststr(abts_suite *suite)
Definition teststr.c:411
static void snprintf_0nonNULL(abts_case *tc, void *data)
Definition teststr.c:123
static void pstrcat(abts_case *tc, void *data)
Definition teststr.c:398
static void string_strfsize(abts_case *tc, void *data)
Definition teststr.c:321
static void string_long(abts_case *tc, void *data)
Definition teststr.c:172