xref: /freebsd-src/contrib/libcbor/src/cbor/internal/memory_utils.c (revision 5d3e7166f6a0187fa3f8831b16a06bd9955c21ff)
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