diff options
author | Yann Ylavic <ylavic@apache.org> | 2022-06-27 15:26:09 +0000 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2022-06-27 15:26:09 +0000 |
commit | 622905ddfa7b45dfca350e13442892de3c1f48e9 (patch) | |
tree | 90ce50291110845d9fa861dd6ec6d801c50179fc /test | |
parent | fc17ab1e8415581b23416caa8925602d1e40d100 (diff) | |
download | apr-622905ddfa7b45dfca350e13442892de3c1f48e9.tar.gz |
encoding: Better check inputs of apr_{encode,decode}_* functions.
Check that the given sources can be encoded without overflowing.
Return APR_EINVAL if the given "slen" is negative, APR_NOTFOUND if "dest" is
not NULL and "src" is NULL, or APR_ENOSPC if "dest" is NULL and the source
length (based on "slen" or APR_ENCODE_STRING) is too big to encode.
* include/private/apr_encode_private.h():
Rename ENCODE_TO_ASCII() and ENCODE_TO_NATIVE() to respectively TO_ASCII()
and TO_ENCODE(), and make them return an unsigned char.
* encoding/apr_escape.c():
Use the new TO_ASCII() and TO_NATIVE().
* encoding/apr_encode.c(apr_encode_*, apr_decode_*):
Forbid negative "slen" but APR_ENCODE_STRING, and use apr_size_t arithmetics
to check for overflows when encoding.
When "dest" is NULL, "src" can be NULL too.
Better check for trailing '='s or base16's APR_ENCODE_COLON ':' separators.
Rename ENCODE_TO_ASCII and ENCODE_TO_NATIVE to their new names, and remove
casts to (unsigned char) now unnecessary.
* include/apr_encode.h():
Update dox about acceptable inputs and returned errors.
* test/testencode.c():
Tests for error conditions.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1902281 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'test')
-rw-r--r-- | test/testencode.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/test/testencode.c b/test/testencode.c index b5e11566e..28d5b07f5 100644 --- a/test/testencode.c +++ b/test/testencode.c @@ -905,6 +905,162 @@ static void test_decode_base16_binary(abts_case * tc, void *data) apr_pool_destroy(pool); } +typedef apr_status_t (*encdec_fn)(char*, const char*, apr_ssize_t, int, apr_size_t*); + +static void test_encode_errors(abts_case * tc, void *data) +{ + char dest[1]; + apr_size_t len; + apr_status_t rv; + + const encdec_fn *enc, encs[] = { + (encdec_fn)apr_encode_base64, + (encdec_fn)apr_encode_base64_binary, + (encdec_fn)apr_encode_base32, + (encdec_fn)apr_encode_base32_binary, + (encdec_fn)apr_encode_base16, + (encdec_fn)apr_encode_base16_binary, + NULL + }; + for (enc = encs; *enc; ++enc) { + rv = (*enc)(dest, "", -2, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINVAL, rv); + + rv = (*enc)(dest, NULL, APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_NOTFOUND, rv); + +#if 0 + /* Can't test APR_ENOSPC without a NUL terminated buffer of + * length APR_SIZE_MAX / 4 * 3 and passing APR_ENCODE_STRING, + * which we won't even think about :) + */ + { + static char huge_buffer[APR_SIZE_MAX / 4 * 3 + 1]; + memset(huge_buffer, !0, sizeof(huge_buffer) - 1); + rv = (*enc)(NULL, huge_buffer, APR_ENCODE_STRING, &len); + ABTS_INT_EQUAL(tc, APR_ENOSPC, rv); + } +#endif + } +} + +static void test_decode_errors(abts_case * tc, void *data) +{ + char dest[64]; + unsigned char *udest = (unsigned char *)dest; + apr_size_t len; + apr_status_t rv; + + const encdec_fn *dec, decs[] = { + (encdec_fn)apr_decode_base64, + (encdec_fn)apr_decode_base64_binary, + (encdec_fn)apr_decode_base32, + (encdec_fn)apr_decode_base32_binary, + (encdec_fn)apr_decode_base16, + (encdec_fn)apr_decode_base16_binary, + NULL + }; + for (dec = decs; *dec; ++dec) { + rv = (*dec)(dest, "", -2, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINVAL, rv); + + rv = (*dec)(dest, NULL, APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_NOTFOUND, rv); + + /* No possible APR_ENOSPC when decoding */ + } + + /* base64 */ + rv = apr_decode_base64(NULL, NULL, 5, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base64(dest, "ABCDE", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base64(dest, "ABCD*EF", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_BADCH, rv); + rv = apr_decode_base64(dest, "ABCD*EF", APR_ENCODE_STRING, + APR_ENCODE_RELAXED, &len); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_SIZE_EQUAL(tc, 3, len); + + /* base64_binary */ + rv = apr_decode_base64_binary(NULL, NULL, 5, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base64_binary(udest, "ABCDE", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base64_binary(udest, "ABCD*EF", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_BADCH, rv); + rv = apr_decode_base64_binary(udest, "ABCD*EF", APR_ENCODE_STRING, + APR_ENCODE_RELAXED, &len); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_SIZE_EQUAL(tc, 3, len); + + /* base32 */ + rv = apr_decode_base32(NULL, NULL, 9, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base32(NULL, NULL, 11, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base32(NULL, NULL, 14, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base32(dest, "ABCDEFGHI", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base32(dest, "ABCDEFGHIJK", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base32(dest, "ABCDEFGHIJKLMN", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base32(dest, "ABCDEFGH*IJ", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_BADCH, rv); + rv = apr_decode_base32(dest, "ABCEEFGH*IJ", APR_ENCODE_STRING, + APR_ENCODE_RELAXED, &len); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_SIZE_EQUAL(tc, 5, len); + + /* base32_binary */ + rv = apr_decode_base32_binary(NULL, NULL, 9, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base32_binary(NULL, NULL, 11, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base32_binary(NULL, NULL, 14, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base32_binary(udest, "ABCDEFGHI", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base32_binary(udest, "ABCDEFGHIJK", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base32_binary(udest, "ABCDEFGHIJKLMN", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base32_binary(udest, "ABCDEFGH*IJ", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_BADCH, rv); + rv = apr_decode_base32_binary(udest, "ABCEEFGH*IJ", APR_ENCODE_STRING, + APR_ENCODE_RELAXED, &len); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_SIZE_EQUAL(tc, 5, len); + + /* base16 */ + rv = apr_decode_base16(NULL, NULL, 3, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base16(dest, "ABC", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base16(dest, "ABCD*EF", APR_ENCODE_STRING, 0, &len); + ABTS_INT_EQUAL(tc, APR_BADCH, rv); + rv = apr_decode_base16(dest, "ABCD*EF", APR_ENCODE_STRING, + APR_ENCODE_RELAXED, &len); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_SIZE_EQUAL(tc, 2, len); + /* base16 with colon */ + rv = apr_decode_base16(dest, "AB:", APR_ENCODE_STRING, + APR_ENCODE_COLON, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base16(dest, "AB:C", APR_ENCODE_STRING, + APR_ENCODE_COLON, &len); + ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv); + rv = apr_decode_base16(dest, "AB:CD*EF", APR_ENCODE_STRING, + APR_ENCODE_COLON, &len); + ABTS_INT_EQUAL(tc, APR_BADCH, rv); + rv = apr_decode_base16(dest, "AB:CD*EF", APR_ENCODE_STRING, + APR_ENCODE_COLON|APR_ENCODE_RELAXED, &len); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_SIZE_EQUAL(tc, 2, len); +} + abts_suite *testencode(abts_suite * suite) { suite = ADD_SUITE(suite); @@ -921,6 +1077,8 @@ abts_suite *testencode(abts_suite * suite) abts_run_test(suite, test_encode_base16_binary, NULL); abts_run_test(suite, test_decode_base16, NULL); abts_run_test(suite, test_decode_base16_binary, NULL); + abts_run_test(suite, test_encode_errors, NULL); + abts_run_test(suite, test_decode_errors, NULL); return suite; } |