#include "internal.h"
+#ifdef __APPLE__
#include <libkern/OSByteOrder.h>
+#elif __linux__
+#include <endian.h>
+#define OSLittleEndian __LITTLE_ENDIAN
+#define OSBigEndian __BIG_ENDIAN
+#define OSSwapLittleToHostInt16 le16toh
+#define OSSwapBigToHostInt16 be16toh
+#define OSSwapHostToLittleInt16 htole16
+#define OSSwapHostToBigInt16 htobe16
+#endif
#if defined(__LITTLE_ENDIAN__)
#define DISPATCH_DATA_FORMAT_TYPE_UTF16_HOST DISPATCH_DATA_FORMAT_TYPE_UTF16LE
#elif defined(__BIG_ENDIAN__)
#define DISPATCH_DATA_FORMAT_TYPE_UTF16_HOST DISPATCH_DATA_FORMAT_TYPE_UTF16BE
#define DISPATCH_DATA_FORMAT_TYPE_UTF16_REV DISPATCH_DATA_FORMAT_TYPE_UTF16LE
+#else
+#error Unsupported Endianness
#endif
enum {
size_t size;
} dispatch_transform_buffer_s;
-static size_t
-_dispatch_transform_sizet_mul(size_t a, size_t b)
-{
- size_t rv = SIZE_MAX;
- if (a == 0 || rv/a >= b) {
- rv = a * b;
- }
- return rv;
-}
-
#define BUFFER_MALLOC_MAX (100*1024*1024)
static bool
DISPATCH_UNUSED dispatch_data_t region,
size_t offset, const void *_buffer, size_t size) {
const uint8_t *src = _buffer;
- size_t i;
+ size_t i, dest_size;
if (offset == 0) {
- size_t dest_size = 2 + _dispatch_transform_sizet_mul(size,
- sizeof(uint16_t));
+ if (os_mul_and_add_overflow(size, sizeof(uint16_t),
+ sizeof(uint16_t), &dest_size)) {
+ return (bool)false;
+ }
if (!_dispatch_transform_buffer_new(&buffer, dest_size, 0)) {
return (bool)false;
}
for (i = 0; i < size;) {
uint32_t wch = 0;
uint8_t byte_size = _dispatch_transform_utf8_length(*src);
+ size_t next;
if (byte_size == 0) {
return (bool)false;
i += byte_size;
}
- size_t next = _dispatch_transform_sizet_mul(size - i, sizeof(uint16_t));
+ if (os_mul_overflow(size - i, sizeof(uint16_t), &next)) {
+ return (bool)false;
+ }
if (wch >= 0xd800 && wch < 0xdfff) {
// Illegal range (surrogate pair)
return (bool)false;
const uint16_t *src = _buffer;
if (offset == 0) {
+ size_t dest_size = howmany(size, 3) * 2;
// Assume first buffer will be mostly single-byte UTF-8 sequences
- size_t dest_size = _dispatch_transform_sizet_mul(size, 2) / 3;
if (!_dispatch_transform_buffer_new(&buffer, dest_size, 0)) {
return (bool)false;
}
for (i = 0; i < max; i++) {
uint32_t wch = 0;
uint16_t ch;
+ size_t next;
if ((i == (max - 1)) && (max > (size / 2))) {
// Last byte of an odd sized range
wch = ch;
}
- size_t next = _dispatch_transform_sizet_mul(max - i, 2);
+ if (os_mul_overflow(max - i, 2, &next)) {
+ return (bool)false;
+ }
if (wch < 0x80) {
if (!_dispatch_transform_buffer_new(&buffer, 1, next)) {
return (bool)false;
bool success = dispatch_data_apply(data, ^(
DISPATCH_UNUSED dispatch_data_t region,
DISPATCH_UNUSED size_t offset, const void *buffer, size_t size) {
- size_t i, dest_size = (size * 5) / 8;
-
+ size_t i, dest_size = howmany(size, 8) * 5;
uint8_t *dest = (uint8_t*)malloc(dest_size * sizeof(uint8_t));
uint8_t *ptr = dest;
if (dest == NULL) {
static dispatch_data_t
_dispatch_transform_to_base32_with_table(dispatch_data_t data, const unsigned char* table)
{
- size_t total = dispatch_data_get_size(data);
+ size_t total = dispatch_data_get_size(data), dest_size;
__block size_t count = 0;
- if (total > SIZE_T_MAX-4 || ((total+4)/5 > SIZE_T_MAX/8)) {
- /* We can't hold larger than size_t in a dispatch_data_t
- * and we want to avoid an integer overflow in the next
- * calculation.
- */
+ dest_size = howmany(total, 5);
+ // <rdar://problem/25676583>
+ // os_mul_overflow(dest_size, 8, &dest_size)
+ if (dest_size > SIZE_T_MAX / 8) {
return NULL;
}
+ dest_size *= 8;
- size_t dest_size = (total + 4) / 5 * 8;
uint8_t *dest = (uint8_t*)malloc(dest_size);
if (dest == NULL) {
return NULL;
bool success = dispatch_data_apply(data, ^(
DISPATCH_UNUSED dispatch_data_t region,
DISPATCH_UNUSED size_t offset, const void *buffer, size_t size) {
- size_t i, dest_size = (size * 3) / 4;
+ size_t i, dest_size = howmany(size, 4) * 3;
uint8_t *dest = (uint8_t*)malloc(dest_size * sizeof(uint8_t));
uint8_t *ptr = dest;
{
// RFC 4648 states that we should not linebreak
// http://tools.ietf.org/html/rfc4648
- size_t total = dispatch_data_get_size(data);
+ size_t total = dispatch_data_get_size(data), dest_size;
__block size_t count = 0;
- if (total > SIZE_T_MAX-2 || ((total+2)/3> SIZE_T_MAX/4)) {
- /* We can't hold larger than size_t in a dispatch_data_t
- * and we want to avoid an integer overflow in the next
- * calculation.
- */
+ dest_size = howmany(total, 3);
+ // <rdar://problem/25676583>
+ // os_mul_overflow(dest_size, 4, &dest_size)
+ if (dest_size > SIZE_T_MAX / 4) {
return NULL;
}
+ dest_size *= 4;
- size_t dest_size = (total + 2) / 3 * 4;
uint8_t *dest = (uint8_t*)malloc(dest_size);
if (dest == NULL) {
return NULL;
if (input->type == _DISPATCH_DATA_FORMAT_UTF_ANY) {
input = _dispatch_transform_detect_utf(data);
if (input == NULL) {
- return NULL;
+ return DISPATCH_BAD_INPUT;
}
}
if ((input->type & ~output->input_mask) != 0) {
- return NULL;
+ return DISPATCH_BAD_INPUT;
}
if ((output->type & ~input->output_mask) != 0) {
- return NULL;
+ return DISPATCH_BAD_INPUT;
}
if (dispatch_data_get_size(data) == 0) {
}
if (!temp1) {
- return NULL;
+ return DISPATCH_BAD_INPUT;
}
dispatch_data_t temp2;