| /* |
| * Copyright (c) 2011-2012 Apple Inc. All rights reserved. |
| * |
| * @APPLE_APACHE_LICENSE_HEADER_START@ |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| * @APPLE_APACHE_LICENSE_HEADER_END@ |
| */ |
| |
| #include <bsdtests.h> |
| |
| #if DISPATCH_API_VERSION >= 20111008 && !TARGET_OS_EMBEDDED |
| |
| #include <Security/Security.h> |
| |
| #include <dispatch/dispatch.h> |
| #include <dispatch/private.h> |
| #include <fcntl.h> |
| |
| #define printf_data(p, s) ({ \ |
| __typeof__(s) _i; \ |
| for (_i=0; _i<s; _i++) { \ |
| printf("%c", ((uint8_t *)p)[_i]); \ |
| } \ |
| printf("\n"); \ |
| }) |
| |
| #define test_data_equal(a, b, c) ({ \ |
| const void * ptr, * ptr2; \ |
| size_t size, size2; \ |
| dispatch_data_t map = dispatch_data_create_map(b, &ptr, &size); \ |
| assert(map); \ |
| dispatch_data_t map2 = dispatch_data_create_map(c, &ptr2, &size2); \ |
| assert(map); \ |
| test_long(a ": length", size, size2); \ |
| test_long(a ": memcmp", memcmp(ptr, ptr2, size), 0); \ |
| if (size != size2 || (memcmp(ptr, ptr2, size) != 0)) { \ |
| printf_data(ptr, size); \ |
| printf_data(ptr2, size2); \ |
| } \ |
| dispatch_release(map); \ |
| dispatch_release(map2); \ |
| }) |
| |
| static bool |
| dispatch_data_equal(dispatch_data_t a, dispatch_data_t b) |
| { |
| const void * ptr, * ptr2; |
| size_t size, size2; |
| bool equal = true; |
| |
| dispatch_data_t map = dispatch_data_create_map(a, &ptr, &size); \ |
| assert(map); |
| dispatch_data_t map2 = dispatch_data_create_map(b, &ptr2, &size2); \ |
| assert(map2); |
| |
| if (size == size2) { |
| if (memcmp(ptr, ptr2, size) != 0) { |
| equal = false; |
| } |
| } else { |
| equal = false; |
| } |
| dispatch_release(map); |
| dispatch_release(map2); |
| return equal; |
| } |
| |
| static dispatch_data_t |
| execute_sectransform(SecTransformRef transformRef, dispatch_data_t data) |
| { |
| const void * bytes; |
| size_t size; |
| |
| dispatch_data_t map = dispatch_data_create_map(data, &bytes, &size); |
| assert(map); |
| |
| CFDataRef dataRef = CFDataCreate(kCFAllocatorDefault, bytes, size); |
| assert(dataRef); |
| |
| dispatch_release(map); |
| |
| SecTransformSetAttribute(transformRef, kSecTransformInputAttributeName, dataRef, NULL); |
| |
| CFDataRef transformedDataRef = SecTransformExecute(transformRef, NULL); |
| assert(transformedDataRef); |
| |
| CFRelease(dataRef); |
| |
| dispatch_data_t output = dispatch_data_create(CFDataGetBytePtr(transformedDataRef), CFDataGetLength(transformedDataRef), dispatch_get_main_queue(), DISPATCH_DATA_DESTRUCTOR_DEFAULT); |
| CFRelease(transformedDataRef); |
| |
| return output; |
| } |
| |
| #pragma mark - UTF tests |
| |
| static uint8_t utf8[] = { |
| 0x53, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x6b, 0x73, 0x20, 0x66, 0x6f, |
| 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x2e, 0x20, 0xeb, 0x84, 0x88, 0xeb, 0xac, |
| 0xb4, 0x20, 0xec, 0x98, 0xa4, 0xeb, 0x9e, 0x98, 0x20, 0xea, 0xb7, 0xb8, 0xeb, 0xa6, 0xac, 0xea, 0xb3, 0xa0, 0x20, 0xea, 0xb7, |
| 0xb8, 0x20, 0xeb, 0x8f, 0x99, 0xec, 0x95, 0x88, 0x20, 0xeb, 0xa7, 0x9b, 0xec, 0x9e, 0x88, 0xeb, 0x8a, 0x94, 0x20, 0xec, 0x83, |
| 0x9d, 0xec, 0x84, 0xa0, 0xec, 0x9d, 0x80, 0x20, 0xea, 0xb3, 0xa0, 0xeb, 0xa7, 0x88, 0xec, 0x9b, 0xa0, 0xec, 0x96, 0xb4, 0x2e, |
| 0x20, 0xf0, 0x9f, 0x98, 0x84, 0xf0, 0x9f, 0x98, 0x8a, 0xf0, 0x9f, 0x98, 0x83, 0xe2, 0x98, 0xba, 0xf0, 0x9f, 0x98, 0x89, 0xf0, |
| 0x9f, 0x98, 0x8d, 0xf0, 0x9f, 0x92, 0xa8, 0xf0, 0x9f, 0x92, 0xa9, 0xf0, 0x9f, 0x91, 0x8e, 0x2e, |
| }; |
| |
| static uint16_t utf16[] = { |
| 0xfeff, 0x53, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x6b, 0x73, 0x20, 0x66, |
| 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x2e, 0x20, 0xb108, 0xbb34, 0x20, |
| 0xc624, 0xb798, 0x20, 0xadf8, 0xb9ac, 0xace0, 0x20, 0xadf8, 0x20, 0xb3d9, 0xc548, 0x20, 0xb9db, 0xc788, 0xb294, 0x20, 0xc0dd, |
| 0xc120, 0xc740, 0x20, 0xace0, 0xb9c8, 0xc6e0, 0xc5b4, 0x2e, 0x20, 0xd83d, 0xde04, 0xd83d, 0xde0a, 0xd83d, 0xde03, 0x263a, 0xd83d, |
| 0xde09, 0xd83d, 0xde0d, 0xd83d, 0xdca8, 0xd83d, 0xdca9, 0xd83d, 0xdc4e, 0x2e, |
| }; |
| |
| static uint16_t utf16be[] = { |
| 0xfffe, 0x5300, 0x6f00, 0x2000, 0x6c00, 0x6f00, 0x6e00, 0x6700, 0x2000, 0x6100, 0x6e00, 0x6400, 0x2000, 0x7400, 0x6800, 0x6100, |
| 0x6e00, 0x6b00, 0x7300, 0x2000, 0x6600, 0x6f00, 0x7200, 0x2000, 0x6100, 0x6c00, 0x6c00, 0x2000, 0x7400, 0x6800, 0x6500, 0x2000, |
| 0x6600, 0x6900, 0x7300, 0x6800, 0x2e00, 0x2000, 0x8b1, 0x34bb, 0x2000, 0x24c6, 0x98b7, 0x2000, 0xf8ad, 0xacb9, 0xe0ac, 0x2000, |
| 0xf8ad, 0x2000, 0xd9b3, 0x48c5, 0x2000, 0xdbb9, 0x88c7, 0x94b2, 0x2000, 0xddc0, 0x20c1, 0x40c7, 0x2000, 0xe0ac, 0xc8b9, 0xe0c6, |
| 0xb4c5, 0x2e00, 0x2000, 0x3dd8, 0x4de, 0x3dd8, 0xade, 0x3dd8, 0x3de, 0x3a26, 0x3dd8, 0x9de, 0x3dd8, 0xdde, 0x3dd8, 0xa8dc, |
| 0x3dd8, 0xa9dc, 0x3dd8, 0x4edc, 0x2e00, |
| }; |
| |
| // Invalid due to half missing surrogate |
| static uint16_t utf16le_invalid[] = { |
| 0xfeff, 0x53, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x6b, 0x73, 0x20, 0x66, |
| 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x2e, 0x20, 0xb108, 0xbb34, 0x20, |
| 0xc624, 0xb798, 0x20, 0xadf8, 0xb9ac, 0xace0, 0x20, 0xadf8, 0x20, 0xb3d9, 0xc548, 0x20, 0xb9db, 0xc788, 0xb294, 0x20, 0xc0dd, |
| 0xc120, 0xc740, 0x20, 0xace0, 0xb9c8, 0xc6e0, 0xc5b4, 0x2e, 0x20, 0xd83d, 0xde04, 0xd83d, 0xde0a, 0xd83d, 0xde03, 0x263a, 0xd83d, |
| 0xde09, 0xd83d, 0xde0d, 0xd83d, 0xdca8, 0xd83d, 0xd83d, 0xdc4e, 0x2e, |
| }; |
| |
| void |
| invalid_utf8_test(void * context) |
| { |
| dispatch_data_t utf8_data = dispatch_data_create(utf8 + sizeof(utf8) - 8, 8, NULL, ^{}); |
| |
| dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF8, DISPATCH_DATA_FORMAT_TYPE_UTF16LE); |
| test_ptr_null("dispatch_data_create_with_transform (UTF8 (invalid start) -> UTF16LE)", transformed); |
| |
| dispatch_release(utf8_data); |
| |
| (void)context; |
| } |
| |
| void |
| truncated_utf8_test(void * context) |
| { |
| dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8) - 3, NULL, ^{}); |
| |
| dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF8, DISPATCH_DATA_FORMAT_TYPE_UTF16LE); |
| test_ptr_null("dispatch_data_create_with_transform (UTF8 (truncated) -> UTF16LE)", transformed); |
| |
| dispatch_release(utf8_data); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, invalid_utf8_test); |
| } |
| |
| void |
| invalid_utf16le_surrogate_test(void * context) |
| { |
| dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{}); |
| dispatch_data_t utf16_data = dispatch_data_create(utf16le_invalid, sizeof(utf16le_invalid), NULL, ^{}); |
| |
| dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF16LE, DISPATCH_DATA_FORMAT_TYPE_UTF8); |
| test_ptr_null("dispatch_data_create_with_transform (UTF16LE (missing surrogate) -> UTF8)", transformed); |
| |
| dispatch_release(utf16_data); |
| dispatch_release(utf8_data); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, truncated_utf8_test); |
| } |
| |
| void |
| invalid_utf16le_test(void * context) |
| { |
| dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{}); |
| dispatch_data_t utf16_data = dispatch_data_create(utf16, (sizeof(utf16) % 2) + 1, NULL, ^{}); |
| |
| dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF16LE, DISPATCH_DATA_FORMAT_TYPE_UTF8); |
| test_ptr_null("dispatch_data_create_with_transform (UTF16LE (invalid) -> UTF8)", transformed); |
| |
| dispatch_release(utf16_data); |
| dispatch_release(utf8_data); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, invalid_utf16le_surrogate_test); |
| } |
| |
| void |
| utf16le_bytes_to_utf8_test(void * context) |
| { |
| dispatch_data_t utf16_data = dispatch_data_empty; |
| dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{}); |
| |
| size_t i; |
| for (i=0; i<sizeof(utf16); i++) { |
| dispatch_data_t new = dispatch_data_create((char*)utf16 + i, 1, NULL, ^{}); |
| dispatch_data_t concat = dispatch_data_create_concat(utf16_data, new); |
| dispatch_release(new); |
| dispatch_release(utf16_data); |
| utf16_data = concat; |
| } |
| |
| dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF8); |
| test_ptr_notnull("dispatch_data_create_with_transform (UTF16LE (any, single bytes) -> UTF8)", transformed); |
| test_data_equal("utf16le_bytes_to_utf8_test", transformed, utf8_data); |
| |
| dispatch_release(transformed); |
| dispatch_release(utf8_data); |
| dispatch_release(utf16_data); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, invalid_utf16le_test); |
| } |
| |
| void |
| utf8_bytes_to_utf16le_test(void * context) |
| { |
| dispatch_data_t utf8_data = dispatch_data_empty; |
| dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{}); |
| |
| size_t i; |
| for (i=0; i<sizeof(utf8); i++) { |
| dispatch_data_t new = dispatch_data_create(utf8 + i, 1, NULL, ^{}); |
| dispatch_data_t concat = dispatch_data_create_concat(utf8_data, new); |
| dispatch_release(new); |
| dispatch_release(utf8_data); |
| utf8_data = concat; |
| } |
| |
| dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF16LE); |
| test_ptr_notnull("dispatch_data_create_with_transform (UTF8 (any, single bytes) -> UTF16LE)", transformed); |
| test_data_equal("utf8_bytes_to_utf16le_test", transformed, utf16_data); |
| |
| dispatch_release(transformed); |
| dispatch_release(utf8_data); |
| dispatch_release(utf16_data); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16le_bytes_to_utf8_test); |
| } |
| |
| void |
| utf16be_detect_to_utf16le_test(void * context) |
| { |
| dispatch_data_t utf16be_data = dispatch_data_create(utf16be, sizeof(utf16be), NULL, ^{}); |
| dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{}); |
| |
| dispatch_data_t transformed = dispatch_data_create_with_transform(utf16be_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF16LE); |
| test_ptr_notnull("dispatch_data_create_with_transform (UTF16BE (any) -> UTF16LE)", transformed); |
| test_data_equal("utf16be_detect_to_utf16le_test", transformed, utf16_data); |
| |
| dispatch_release(transformed); |
| dispatch_release(utf16be_data); |
| dispatch_release(utf16_data); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf8_bytes_to_utf16le_test); |
| } |
| |
| void |
| utf16be_detect_to_utf8_test(void * context) |
| { |
| dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{}); |
| dispatch_data_t utf16_data = dispatch_data_create(utf16be, sizeof(utf16be), NULL, ^{}); |
| |
| dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF8); |
| test_ptr_notnull("dispatch_data_create_with_transform (UTF16BE (any) -> UTF8)", transformed); |
| test_data_equal("utf16be_detect_to_utf8_test", transformed, utf8_data); |
| |
| dispatch_release(transformed); |
| dispatch_release(utf16_data); |
| dispatch_release(utf8_data); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16be_detect_to_utf16le_test); |
| } |
| |
| void |
| utf16le_detect_to_utf8_test(void * context) |
| { |
| dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{}); |
| dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{}); |
| |
| dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF8); |
| test_ptr_notnull("dispatch_data_create_with_transform (UTF16LE (any) -> UTF8)", transformed); |
| test_data_equal("utf16le_detect_to_utf8_test", transformed, utf8_data); |
| |
| dispatch_release(transformed); |
| dispatch_release(utf16_data); |
| dispatch_release(utf8_data); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16be_detect_to_utf8_test); |
| } |
| |
| void |
| utf16be_to_utf8_test(void * context) |
| { |
| dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{}); |
| dispatch_data_t utf16_data = dispatch_data_create(utf16be, sizeof(utf16be), NULL, ^{}); |
| |
| dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF16BE, DISPATCH_DATA_FORMAT_TYPE_UTF8); |
| test_ptr_notnull("dispatch_data_create_with_transform (UTF16BE -> UTF8)", transformed); |
| test_data_equal("utf16be_to_utf8_test", transformed, utf8_data); |
| |
| dispatch_release(transformed); |
| dispatch_release(utf16_data); |
| dispatch_release(utf8_data); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16le_detect_to_utf8_test); |
| } |
| |
| void |
| utf16le_to_utf8_test(void * context) |
| { |
| dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{}); |
| dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{}); |
| |
| dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF16LE, DISPATCH_DATA_FORMAT_TYPE_UTF8); |
| test_ptr_notnull("dispatch_data_create_with_transform (UTF16LE -> UTF8)", transformed); |
| test_data_equal("utf16le_to_utf8_test", transformed, utf8_data); |
| |
| dispatch_release(transformed); |
| dispatch_release(utf16_data); |
| dispatch_release(utf8_data); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16be_to_utf8_test); |
| } |
| |
| void |
| utf8_to_utf16be_test(void * context) |
| { |
| dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{}); |
| dispatch_data_t utf16_data = dispatch_data_create(utf16be, sizeof(utf16be), NULL, ^{}); |
| |
| dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF8, DISPATCH_DATA_FORMAT_TYPE_UTF16BE); |
| test_ptr_notnull("dispatch_data_create_with_transform (UTF8 -> UTF16BE)", transformed); |
| test_data_equal("utf8_to_utf16be_test", transformed, utf16_data); |
| |
| dispatch_release(transformed); |
| dispatch_release(utf16_data); |
| dispatch_release(utf8_data); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16le_to_utf8_test); |
| } |
| |
| void |
| utf8_to_utf16le_test(void * context) |
| { |
| dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{}); |
| dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{}); |
| |
| dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF8, DISPATCH_DATA_FORMAT_TYPE_UTF16LE); |
| test_ptr_notnull("dispatch_data_create_with_transform (UTF8 -> UTF16LE)", transformed); |
| test_data_equal("utf8_to_utf16le_test", transformed, utf16_data); |
| |
| dispatch_release(transformed); |
| dispatch_release(utf16_data); |
| dispatch_release(utf8_data); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf8_to_utf16be_test); |
| } |
| |
| #pragma mark - base32 tests |
| |
| void |
| decode32_corrupt_test(void * context) |
| { |
| dispatch_group_enter((dispatch_group_t)context); |
| |
| int fd = open("/dev/random", O_RDONLY); |
| assert(fd >= 0); |
| |
| dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) { |
| assert(error == 0); |
| |
| SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL); |
| assert(transformRef); |
| |
| dispatch_data_t sectransform_data = execute_sectransform(transformRef, data); |
| assert(sectransform_data); |
| CFRelease(transformRef); |
| |
| void * corrupt_buffer = malloc(dispatch_data_get_size(sectransform_data)); |
| const void * source; |
| size_t size; |
| |
| dispatch_data_t map = dispatch_data_create_map(sectransform_data, &source, &size); |
| memcpy(corrupt_buffer, source, size); |
| |
| size_t i; |
| for (i=0; i<size; i += (arc4random() % (int)(size * 0.05))) { |
| char x = arc4random() & 0xff; |
| while ((x >= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x >= '0' && x <= '9') || x == '/' || x == '+' || x == '=') { |
| x = arc4random() & 0xff; |
| } |
| |
| ((char*)corrupt_buffer)[i] = x; |
| } |
| |
| dispatch_release(map); |
| dispatch_release(sectransform_data); |
| |
| dispatch_data_t corrupt_data = dispatch_data_create(corrupt_buffer, size, dispatch_get_main_queue(), DISPATCH_DATA_DESTRUCTOR_FREE); |
| |
| dispatch_data_t transform_data = dispatch_data_create_with_transform(corrupt_data, DISPATCH_DATA_FORMAT_TYPE_BASE32, DISPATCH_DATA_FORMAT_TYPE_NONE); |
| test_ptr_null("decode32_corrupt_test: dispatch_data_create_with_transform", transform_data); |
| |
| dispatch_release(corrupt_data); |
| |
| close(fd); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf8_to_utf16le_test); |
| dispatch_group_leave((dispatch_group_t)context); |
| }); |
| } |
| |
| void |
| chunking_decode32_test(void * context) |
| { |
| (void)context; |
| |
| int fd = open("/dev/random", O_RDONLY); |
| assert(fd >= 0); |
| |
| dispatch_data_t __block data = dispatch_data_empty; |
| |
| int i; |
| dispatch_group_t group = dispatch_group_create(); |
| dispatch_queue_t queue = dispatch_queue_create("read", 0); |
| for (i=0; i<4096; i++) { |
| dispatch_group_enter(group); |
| |
| dispatch_read(fd, 1, queue, ^(dispatch_data_t d, int error) { |
| assert(error == 0); |
| |
| dispatch_data_t concat = dispatch_data_create_concat(data, d); |
| dispatch_release(data); |
| data = concat; |
| dispatch_group_leave(group); |
| }); |
| } |
| dispatch_group_wait(group, DISPATCH_TIME_FOREVER); |
| dispatch_release(queue); |
| dispatch_release(group); |
| |
| SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL); |
| assert(transformRef); |
| |
| dispatch_data_t sectransform_data = execute_sectransform(transformRef, data); |
| assert(sectransform_data); |
| CFRelease(transformRef); |
| |
| dispatch_data_t transformed_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE32, DISPATCH_DATA_FORMAT_TYPE_NONE); |
| test_ptr_notnull("chunking_decode32_test: dispatch_data_create_with_transform", transformed_data); |
| test_data_equal("chunking_decode32_test", transformed_data, data); |
| |
| dispatch_release(sectransform_data); |
| dispatch_release(transformed_data); |
| dispatch_release(data); |
| |
| close(fd); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, decode32_corrupt_test); |
| } |
| |
| void |
| chunking_encode32_test(void * context) |
| { |
| (void)context; |
| |
| int fd = open("/dev/random", O_RDONLY); |
| assert(fd >= 0); |
| |
| dispatch_data_t __block data = dispatch_data_empty; |
| |
| int i; |
| dispatch_group_t group = dispatch_group_create(); |
| dispatch_queue_t queue = dispatch_queue_create("read", 0); |
| for (i=0; i<4096; i++) { |
| dispatch_group_enter(group); |
| |
| dispatch_read(fd, 1, queue, ^(dispatch_data_t d, int error) { |
| assert(error == 0); |
| |
| dispatch_data_t concat = dispatch_data_create_concat(data, d); |
| dispatch_release(data); |
| data = concat; |
| dispatch_group_leave(group); |
| }); |
| } |
| dispatch_group_wait(group, DISPATCH_TIME_FOREVER); |
| dispatch_release(queue); |
| dispatch_release(group); |
| |
| SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL); |
| assert(transformRef); |
| |
| dispatch_data_t sectransform_data = execute_sectransform(transformRef, data); |
| assert(sectransform_data); |
| CFRelease(transformRef); |
| |
| dispatch_data_t transformed_data = dispatch_data_create_with_transform(data, DISPATCH_DATA_FORMAT_TYPE_NONE, DISPATCH_DATA_FORMAT_TYPE_BASE32); |
| test_ptr_notnull("chunking_encode32_test: dispatch_data_create_with_transform", transformed_data); |
| test_data_equal("chunking_encode32_test", transformed_data, sectransform_data); |
| |
| dispatch_release(sectransform_data); |
| dispatch_release(transformed_data); |
| dispatch_release(data); |
| |
| close(fd); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, chunking_decode32_test); |
| } |
| |
| void |
| decode32_test(void * context) |
| { |
| dispatch_group_enter((dispatch_group_t)context); |
| |
| int fd = open("/dev/random", O_RDONLY); |
| assert(fd >= 0); |
| |
| dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) { |
| assert(error == 0); |
| |
| SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL); |
| assert(transformRef); |
| |
| dispatch_data_t sectransform_data = execute_sectransform(transformRef, data); |
| assert(sectransform_data); |
| CFRelease(transformRef); |
| |
| dispatch_data_t transform_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE32, DISPATCH_DATA_FORMAT_TYPE_NONE); |
| test_ptr_notnull("decode32_test: dispatch_data_create_with_transform", transform_data); |
| test_data_equal("decode32_test", transform_data, data); |
| |
| dispatch_release(sectransform_data); |
| dispatch_release(transform_data); |
| |
| close(fd); |
| |
| dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, chunking_encode32_test); |
| dispatch_group_leave((dispatch_group_t)context); |
| }); |
| } |
| |
| void |
| encode32_test(void * context) |
| { |
| dispatch_group_enter((dispatch_group_t)context); |
| |
| int fd = open("/dev/random", O_RDONLY); |
| assert(fd >= 0); |
| |
| dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) { |
| assert(error == 0); |
| |
| SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL); |
| assert(transformRef); |
| |
| dispatch_data_t sectransform_data = execute_sectransform(transformRef, data); |
| assert(sectransform_data); |
| CFRelease(transformRef); |
| |
| dispatch_data_t transformed_data = dispatch_data_create_with_transform(data, DISPATCH_DATA_FORMAT_TYPE_NONE, DISPATCH_DATA_FORMAT_TYPE_BASE32); |
| test_ptr_notnull("encode32_test: dispatch_data_create_with_transform", transformed_data); |
| test_data_equal("encode32_test", transformed_data, sectransform_data); |
| |
| dispatch_release(sectransform_data); |
| dispatch_release(transformed_data); |
| |
| close(fd); |
| |
| dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, decode32_test); |
| dispatch_group_leave((dispatch_group_t)context); |
| }); |
| } |
| |
| #pragma mark - base64 tests |
| |
| void |
| decode64_loop_test(void * context) |
| { |
| if (getenv("LOOP_SKIP") == NULL) |
| { |
| int fd = open("/dev/random", O_RDONLY); |
| assert(fd >= 0); |
| |
| dispatch_semaphore_t sema = dispatch_semaphore_create(0); |
| size_t i, __block tests = 0; |
| |
| for (i=1; i<4097; i++) { |
| dispatch_read(fd, i, dispatch_get_global_queue(0, 0), ^(dispatch_data_t data, int error) { |
| assert(error == 0); |
| |
| SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL); |
| assert(transformRef); |
| |
| dispatch_data_t sectransform_data = execute_sectransform(transformRef, data); |
| assert(sectransform_data); |
| CFRelease(transformRef); |
| |
| dispatch_data_t transform_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE64, DISPATCH_DATA_FORMAT_TYPE_NONE); |
| if (dispatch_data_equal(transform_data, data)) { |
| tests++; |
| } |
| |
| dispatch_release(sectransform_data); |
| dispatch_release(transform_data); |
| |
| dispatch_semaphore_signal(sema); |
| }); |
| dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); |
| } |
| dispatch_release(sema); |
| close(fd); |
| test_long("decode64_loop_test", tests, 4096); |
| } |
| dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, encode32_test); |
| } |
| |
| void |
| decode64_corrupt_test(void * context) |
| { |
| dispatch_group_enter((dispatch_group_t)context); |
| |
| int fd = open("/dev/random", O_RDONLY); |
| assert(fd >= 0); |
| |
| dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) { |
| assert(error == 0); |
| |
| SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL); |
| assert(transformRef); |
| |
| dispatch_data_t sectransform_data = execute_sectransform(transformRef, data); |
| assert(sectransform_data); |
| CFRelease(transformRef); |
| |
| void * corrupt_buffer = malloc(dispatch_data_get_size(sectransform_data)); |
| const void * source; |
| size_t size; |
| |
| dispatch_data_t map = dispatch_data_create_map(sectransform_data, &source, &size); |
| memcpy(corrupt_buffer, source, size); |
| |
| size_t i; |
| for (i=0; i<size; i += (arc4random() % (int)(size * 0.05))) { |
| char x = arc4random() & 0xff; |
| while ((x >= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x >= '0' && x <= '9') || x == '/' || x == '+' || x == '=') { |
| x = arc4random() & 0xff; |
| } |
| |
| ((char*)corrupt_buffer)[i] = x; |
| } |
| |
| dispatch_release(map); |
| dispatch_release(sectransform_data); |
| |
| dispatch_data_t corrupt_data = dispatch_data_create(corrupt_buffer, size, dispatch_get_main_queue(), DISPATCH_DATA_DESTRUCTOR_FREE); |
| |
| dispatch_data_t transform_data = dispatch_data_create_with_transform(corrupt_data, DISPATCH_DATA_FORMAT_TYPE_BASE64, DISPATCH_DATA_FORMAT_TYPE_NONE); |
| test_ptr_null("decode64_corrupt_test: dispatch_data_create_with_transform", transform_data); |
| |
| dispatch_release(corrupt_data); |
| |
| close(fd); |
| |
| dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, decode64_loop_test); |
| dispatch_group_leave((dispatch_group_t)context); |
| }); |
| } |
| |
| void |
| chunking_decode64_test(void * context) |
| { |
| (void)context; |
| |
| int fd = open("/dev/random", O_RDONLY); |
| assert(fd >= 0); |
| |
| dispatch_data_t __block data = dispatch_data_empty; |
| |
| int i; |
| dispatch_group_t group = dispatch_group_create(); |
| dispatch_queue_t queue = dispatch_queue_create("read", 0); |
| for (i=0; i<4096; i++) { |
| dispatch_group_enter(group); |
| |
| dispatch_read(fd, 1, queue, ^(dispatch_data_t d, int error) { |
| assert(error == 0); |
| |
| dispatch_data_t concat = dispatch_data_create_concat(data, d); |
| dispatch_release(data); |
| data = concat; |
| dispatch_group_leave(group); |
| }); |
| } |
| dispatch_group_wait(group, DISPATCH_TIME_FOREVER); |
| dispatch_release(queue); |
| dispatch_release(group); |
| |
| SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL); |
| assert(transformRef); |
| |
| dispatch_data_t sectransform_data = execute_sectransform(transformRef, data); |
| assert(sectransform_data); |
| CFRelease(transformRef); |
| |
| dispatch_data_t transformed_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE64, DISPATCH_DATA_FORMAT_TYPE_NONE); |
| test_ptr_notnull("chunking_decode64_test: dispatch_data_create_with_transform", transformed_data); |
| test_data_equal("chunking_decode64_test", transformed_data, data); |
| |
| dispatch_release(sectransform_data); |
| dispatch_release(transformed_data); |
| dispatch_release(data); |
| |
| close(fd); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, decode64_corrupt_test); |
| } |
| |
| void |
| chunking_encode64_test(void * context) |
| { |
| (void)context; |
| |
| int fd = open("/dev/random", O_RDONLY); |
| assert(fd >= 0); |
| |
| dispatch_data_t __block data = dispatch_data_empty; |
| |
| int i; |
| dispatch_group_t group = dispatch_group_create(); |
| dispatch_queue_t queue = dispatch_queue_create("read", 0); |
| for (i=0; i<4097; i++) { |
| dispatch_group_enter(group); |
| |
| dispatch_read(fd, 1, queue, ^(dispatch_data_t d, int error) { |
| assert(error == 0); |
| |
| dispatch_data_t concat = dispatch_data_create_concat(data, d); |
| dispatch_release(data); |
| data = concat; |
| dispatch_group_leave(group); |
| }); |
| } |
| dispatch_group_wait(group, DISPATCH_TIME_FOREVER); |
| dispatch_release(queue); |
| dispatch_release(group); |
| |
| SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL); |
| assert(transformRef); |
| |
| dispatch_data_t sectransform_data = execute_sectransform(transformRef, data); |
| assert(sectransform_data); |
| CFRelease(transformRef); |
| |
| dispatch_data_t transformed_data = dispatch_data_create_with_transform(data, DISPATCH_DATA_FORMAT_TYPE_NONE, DISPATCH_DATA_FORMAT_TYPE_BASE64); |
| test_ptr_notnull("chunking_encode64_test: dispatch_data_create_with_transform", transformed_data); |
| test_data_equal("chunking_encode64_test", transformed_data, sectransform_data); |
| |
| dispatch_release(sectransform_data); |
| dispatch_release(transformed_data); |
| dispatch_release(data); |
| |
| close(fd); |
| |
| dispatch_group_async_f(context, dispatch_get_main_queue(), context, chunking_decode64_test); |
| } |
| |
| void |
| decode64_test(void * context) |
| { |
| dispatch_group_enter((dispatch_group_t)context); |
| |
| int fd = open("/dev/random", O_RDONLY); |
| assert(fd >= 0); |
| |
| dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) { |
| assert(error == 0); |
| |
| SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL); |
| assert(transformRef); |
| |
| dispatch_data_t sectransform_data = execute_sectransform(transformRef, data); |
| assert(sectransform_data); |
| CFRelease(transformRef); |
| |
| dispatch_data_t transform_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE64, DISPATCH_DATA_FORMAT_TYPE_NONE); |
| test_ptr_notnull("decode64_test: dispatch_data_create_with_transform", transform_data); |
| test_data_equal("decode64_test", transform_data, data); |
| |
| dispatch_release(sectransform_data); |
| dispatch_release(transform_data); |
| |
| close(fd); |
| |
| dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, chunking_encode64_test); |
| dispatch_group_leave((dispatch_group_t)context); |
| }); |
| } |
| |
| void |
| encode64_test(void * context) |
| { |
| dispatch_group_enter((dispatch_group_t)context); |
| |
| int fd = open("/dev/random", O_RDONLY); |
| assert(fd >= 0); |
| |
| dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) { |
| assert(error == 0); |
| |
| SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL); |
| assert(transformRef); |
| |
| dispatch_data_t sectransform_data = execute_sectransform(transformRef, data); |
| assert(sectransform_data); |
| CFRelease(transformRef); |
| |
| dispatch_data_t transformed_data = dispatch_data_create_with_transform(data, DISPATCH_DATA_FORMAT_TYPE_NONE, DISPATCH_DATA_FORMAT_TYPE_BASE64); |
| test_ptr_notnull("encode64_test: dispatch_data_create_with_transform", transformed_data); |
| test_data_equal("encode64_test", transformed_data, sectransform_data); |
| |
| dispatch_release(sectransform_data); |
| dispatch_release(transformed_data); |
| |
| close(fd); |
| |
| dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, decode64_test); |
| dispatch_group_leave((dispatch_group_t)context); |
| }); |
| } |
| |
| #pragma mark - main |
| |
| int |
| main(void) |
| { |
| test_start("Dispatch data transforms test"); |
| |
| dispatch_group_t group = dispatch_group_create(); |
| dispatch_group_async_f(group, dispatch_get_main_queue(), group, encode64_test); |
| |
| dispatch_group_notify(group, dispatch_get_main_queue(), ^{ |
| dispatch_release(group); |
| test_stop(); |
| exit(0); |
| }); |
| |
| dispatch_main(); |
| return 0; |
| } |
| |
| #else |
| |
| int |
| main(void) |
| { |
| test_skip("Dispatch data transforms test"); |
| return 0; |
| } |
| |
| #endif |
| |