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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 #include "apr_general.h"
28 #include "apr_strings.h"
29 #include "apr_errno.h"
31 /* I haven't bothered to check for APR_ENOTIMPL here, AFAIK, all string
32 * functions exist on all platforms.
35 static void test_strtok(abts_case *tc, void *data)
47 " asdf jkl; 77889909 \r\n\1\2\3Z",
51 NULL, /* but who cares if apr_strtok() segfaults? */
54 #if 0 /* don't do this... you deserve to segfault */
71 for (curtc = 0; curtc < sizeof cases / sizeof cases[0]; curtc++) {
72 char *retval1, *retval2;
76 str1 = apr_pstrdup(p, cases[curtc].input);
77 str2 = apr_pstrdup(p, cases[curtc].input);
80 retval1 = apr_strtok(str1, cases[curtc].sep, &state);
81 retval2 = strtok(str2, cases[curtc].sep);
84 ABTS_TRUE(tc, retval2 == NULL);
87 ABTS_TRUE(tc, retval2 != NULL);
88 ABTS_STR_EQUAL(tc, retval2, retval1);
91 str1 = str2 = NULL; /* make sure we pass NULL on subsequent calls */
96 static void snprintf_noNULL(abts_case *tc, void *data)
99 char *testing = apr_palloc(p, 10);
109 /* If this test fails, we are going to seg fault. */
110 apr_snprintf(buff, sizeof(buff), "%.*s", 7, testing);
111 ABTS_STR_NEQUAL(tc, buff, testing, 7);
114 static void snprintf_0NULL(abts_case *tc, void *data)
118 rv = apr_snprintf(NULL, 0, "%sBAR", "FOO");
119 ABTS_INT_EQUAL(tc, 6, rv);
122 static void snprintf_0nonNULL(abts_case *tc, void *data)
125 char *buff = "testing";
127 rv = apr_snprintf(buff, 0, "%sBAR", "FOO");
128 ABTS_INT_EQUAL(tc, 6, rv);
129 ABTS_ASSERT(tc, "buff unmangled", strcmp(buff, "FOOBAR") != 0);
132 static void snprintf_underflow(abts_case *tc, void *data)
137 rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.0001);
138 ABTS_INT_EQUAL(tc, 4, rv);
139 ABTS_STR_EQUAL(tc, "0.00", buf);
141 rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.001);
142 ABTS_INT_EQUAL(tc, 4, rv);
143 ABTS_STR_EQUAL(tc, "0.00", buf);
145 rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.01);
146 ABTS_INT_EQUAL(tc, 4, rv);
147 ABTS_STR_EQUAL(tc, "0.01", buf);
150 static void string_error(abts_case *tc, void *data)
156 rv = apr_strerror(APR_ENOENT, buf, sizeof buf);
157 ABTS_PTR_EQUAL(tc, buf, rv);
158 ABTS_TRUE(tc, strlen(buf) > 0);
160 rv = apr_strerror(APR_TIMEUP, buf, sizeof buf);
161 ABTS_PTR_EQUAL(tc, buf, rv);
162 ABTS_STR_EQUAL(tc, "The timeout specified has expired", buf);
164 /* throw some randomish numbers at it to check for robustness */
165 for (n = 1; n < 1000000; n *= 2) {
166 apr_strerror(n, buf, sizeof buf);
171 static void string_long(abts_case *tc, void *data)
175 memset(s, 'A', SIZE);
178 apr_psprintf(p, "%s", s);
181 /* ### FIXME: apr.h/apr_strings.h should provide these! */
182 #define MY_LLONG_MAX (APR_INT64_C(9223372036854775807))
183 #define MY_LLONG_MIN (-MY_LLONG_MAX - APR_INT64_C(1))
185 static void string_strtoi64(abts_case *tc, void *data)
187 static const struct {
189 const char *in, *end;
194 { 0, 10, "123545", NULL, APR_INT64_C(123545) },
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, " 00000123545", NULL, APR_INT64_C(123545) },
199 { 0, 10, "123545ZZZ", "ZZZ", APR_INT64_C(123545) },
200 { 0, 10, " 123545 ", " ", APR_INT64_C(123545) },
203 { 0, 16, "1E299", NULL, APR_INT64_C(123545) },
204 { 0, 16, "1e299", NULL, APR_INT64_C(123545) },
205 { 0, 16, "0x1e299", NULL, APR_INT64_C(123545) },
206 { 0, 16, "0X1E299", NULL, APR_INT64_C(123545) },
207 { 0, 16, "+1e299", NULL, APR_INT64_C(123545) },
208 { 0, 16, "-1e299", NULL, APR_INT64_C(-123545) },
209 { 0, 16, " -1e299", NULL, APR_INT64_C(-123545) },
211 /* automatic base detection tests */
212 { 0, 0, "123545", NULL, APR_INT64_C(123545) },
213 { 0, 0, "0x1e299", 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) },
218 /* large number tests */
219 { 0, 10, "8589934605", NULL, APR_INT64_C(8589934605) },
220 { 0, 10, "-8589934605", NULL, APR_INT64_C(-8589934605) },
221 { 0, 16, "0x20000000D", 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) },
227 { ERANGE, 10, "999999999999999999999999999999999", "", MY_LLONG_MAX },
228 { ERANGE, 10, "-999999999999999999999999999999999", "", MY_LLONG_MIN },
231 /* C99 doesn't require EINVAL for an invalid range. */
232 { EINVAL, 99, "", (void *)-1 /* don't care */, 0 },
235 /* some strtoll implementations give EINVAL when no conversion
237 { -1 /* don't care */, 10, "zzz", "zzz", APR_INT64_C(0) },
238 { -1 /* don't care */, 10, "", NULL, APR_INT64_C(0) }
243 for (n = 0; n < sizeof(ts)/sizeof(ts[0]); n++) {
244 char *end = "end ptr not changed";
249 result = apr_strtoi64(ts[n].in, &end, ts[n].base);
253 apr_psprintf(p, "for '%s': result was %" APR_INT64_T_FMT
254 " not %" APR_INT64_T_FMT, ts[n].in,
255 result, ts[n].result),
256 result == ts[n].result);
258 if (ts[n].errnum != -1) {
260 apr_psprintf(p, "for '%s': errno was %d not %d", ts[n].in,
261 errnum, ts[n].errnum),
262 ts[n].errnum == errnum);
265 if (ts[n].end == NULL) {
266 /* end must point to NUL terminator of .in */
267 ABTS_PTR_EQUAL(tc, ts[n].in + strlen(ts[n].in), end);
268 } else if (ts[n].end != (void *)-1) {
270 apr_psprintf(p, "for '%s', end was '%s' not '%s'",
271 ts[n].in, end, ts[n].end),
272 strcmp(ts[n].end, end) == 0);
277 static void string_strtoff(abts_case *tc, void *data)
281 ABTS_ASSERT(tc, "strtoff fails on out-of-range integer",
282 apr_strtoff(&off, "999999999999999999999999999999",
283 NULL, 10) != APR_SUCCESS);
285 ABTS_ASSERT(tc, "strtoff failed for 1234",
286 apr_strtoff(&off, "1234", NULL, 10) == APR_SUCCESS);
288 ABTS_ASSERT(tc, "strtoff failed to parse 1234", off == 1234);
291 /* random-ish checks for strfsize buffer overflows */
292 static void overflow_strfsize(abts_case *tc, void *data)
300 for (off = -9999; off < 20000; off++) {
301 apr_strfsize(off, buf);
303 for (; off < 9999999; off += 9) {
304 apr_strfsize(off, buf);
306 for (; off < 999999999; off += 999) {
307 apr_strfsize(off, buf);
309 for (off = 1; off < LONG_MAX && off > 0; off *= 2) {
310 apr_strfsize(off, buf);
311 apr_strfsize(off + 1, buf);
312 apr_strfsize(off - 1, buf);
315 ABTS_ASSERT(tc, "strfsize overflowed", buf[5] == '$');
316 ABTS_ASSERT(tc, "strfsize overflowed", buf[6] == '@');
319 static void string_strfsize(abts_case *tc, void *data)
321 static const struct {
333 { 103809024, " 99M" },
334 { 1047527424, "1.0G" } /* "999M" would be more correct */
338 for (n = 0; n < sizeof(ts)/sizeof(ts[0]); n++) {
343 ret = apr_strfsize(ts[n].size, buf);
344 ABTS_ASSERT(tc, "strfsize returned wrong buffer", ret == buf);
345 ABTS_ASSERT(tc, "strfsize overflowed", buf[5] == '%');
347 ABTS_STR_EQUAL(tc, ts[n].buf, ret);
351 static void string_cpystrn(abts_case *tc, void *data)
357 ret = apr_cpystrn(buf, "123456", 5);
359 ABTS_STR_EQUAL(tc, "1234", buf);
360 ABTS_PTR_EQUAL(tc, buf + 4, ret);
361 ABTS_TRUE(tc, *ret == '\0');
362 ABTS_TRUE(tc, ret[1] == 'Z');
365 static void snprintf_overflow(abts_case *tc, void *data)
373 rv = apr_snprintf(buf, 2, "%s", "a");
374 ABTS_INT_EQUAL(tc, 1, rv);
376 rv = apr_snprintf(buf, 2, "%s", "abcd");
377 ABTS_INT_EQUAL(tc, 1, rv);
379 ABTS_STR_EQUAL(tc, "a", buf);
381 /* Check the buffer really hasn't been overflowed. */
382 ABTS_TRUE(tc, buf[2] == '4' && buf[3] == '2');
385 abts_suite *teststr(abts_suite *suite)
387 suite = ADD_SUITE(suite)
389 abts_run_test(suite, snprintf_0NULL, NULL);
390 abts_run_test(suite, snprintf_0nonNULL, NULL);
391 abts_run_test(suite, snprintf_noNULL, NULL);
392 abts_run_test(suite, snprintf_underflow, NULL);
393 abts_run_test(suite, test_strtok, NULL);
394 abts_run_test(suite, string_error, NULL);
395 abts_run_test(suite, string_long, NULL);
396 abts_run_test(suite, string_strtoi64, NULL);
397 abts_run_test(suite, string_strtoff, NULL);
398 abts_run_test(suite, overflow_strfsize, NULL);
399 abts_run_test(suite, string_strfsize, NULL);
400 abts_run_test(suite, string_cpystrn, NULL);
401 abts_run_test(suite, snprintf_overflow, NULL);