110ff414cSEd Maste /*
210ff414cSEd Maste * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
310ff414cSEd Maste *
410ff414cSEd Maste * libcbor is free software; you can redistribute it and/or modify
510ff414cSEd Maste * it under the terms of the MIT license. See LICENSE for details.
610ff414cSEd Maste */
710ff414cSEd Maste
810ff414cSEd Maste #include "memory_utils.h"
910ff414cSEd Maste #include "cbor/common.h"
1010ff414cSEd Maste
1110ff414cSEd Maste // TODO: Consider builtins
1210ff414cSEd Maste // (https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html)
1310ff414cSEd Maste
1410ff414cSEd Maste /** Highest on bit position */
_cbor_highest_bit(size_t number)1510ff414cSEd Maste size_t _cbor_highest_bit(size_t number) {
1610ff414cSEd Maste size_t bit = 0;
1710ff414cSEd Maste while (number != 0) {
1810ff414cSEd Maste bit++;
1910ff414cSEd Maste number >>= 1;
2010ff414cSEd Maste }
2110ff414cSEd Maste
2210ff414cSEd Maste return bit;
2310ff414cSEd Maste }
2410ff414cSEd Maste
_cbor_safe_to_multiply(size_t a,size_t b)2510ff414cSEd Maste bool _cbor_safe_to_multiply(size_t a, size_t b) {
26*5d3e7166SEd Maste if (a <= 1 || b <= 1) return true;
2710ff414cSEd Maste return _cbor_highest_bit(a) + _cbor_highest_bit(b) <= sizeof(size_t) * 8;
2810ff414cSEd Maste }
2910ff414cSEd Maste
_cbor_safe_to_add(size_t a,size_t b)30*5d3e7166SEd Maste bool _cbor_safe_to_add(size_t a, size_t b) {
31*5d3e7166SEd Maste // Unsigned integer overflow doesn't constitute UB
32*5d3e7166SEd Maste size_t sum = a + b;
33*5d3e7166SEd Maste return sum >= a && sum >= b;
34*5d3e7166SEd Maste }
35*5d3e7166SEd Maste
_cbor_safe_signaling_add(size_t a,size_t b)36*5d3e7166SEd Maste size_t _cbor_safe_signaling_add(size_t a, size_t b) {
37*5d3e7166SEd Maste if (a == 0 || b == 0) return 0;
38*5d3e7166SEd Maste if (_cbor_safe_to_add(a, b)) return a + b;
39*5d3e7166SEd Maste return 0;
40*5d3e7166SEd Maste }
41*5d3e7166SEd Maste
_cbor_alloc_multiple(size_t item_size,size_t item_count)4210ff414cSEd Maste void* _cbor_alloc_multiple(size_t item_size, size_t item_count) {
4310ff414cSEd Maste if (_cbor_safe_to_multiply(item_size, item_count)) {
44*5d3e7166SEd Maste return _cbor_malloc(item_size * item_count);
4510ff414cSEd Maste } else {
4610ff414cSEd Maste return NULL;
4710ff414cSEd Maste }
4810ff414cSEd Maste }
4910ff414cSEd Maste
_cbor_realloc_multiple(void * pointer,size_t item_size,size_t item_count)5010ff414cSEd Maste void* _cbor_realloc_multiple(void* pointer, size_t item_size,
5110ff414cSEd Maste size_t item_count) {
5210ff414cSEd Maste if (_cbor_safe_to_multiply(item_size, item_count)) {
53*5d3e7166SEd Maste return _cbor_realloc(pointer, item_size * item_count);
5410ff414cSEd Maste } else {
5510ff414cSEd Maste return NULL;
5610ff414cSEd Maste }
5710ff414cSEd Maste }
58