|
sanisizer
Sanitize sizes to avoid integer overflow
|
Sanitize sizes to avoid integer overflow. More...
Classes | |
| struct | Bounded |
| Bound the maximum possible value of an integer. More... | |
| class | Cast |
| Cast an integer in a function call. More... | |
| struct | Constant |
| Integer constant. More... | |
| class | Exact |
| Do not cast an integer in a function call. More... | |
| struct | is_Bounded |
| struct | is_Bounded< Bounded< Integer_, max_ > > |
| struct | is_Constant |
| struct | is_Constant< Constant< Integer_, value_ > > |
Functions | |
| template<typename Max_ , Max_ new_max_, typename Value_ > | |
| constexpr auto | set_bound (Value_ x) |
| template<typename MaxType_ , typename Value_ > | |
| constexpr auto | set_bound_by_type (Value_ x) |
| template<typename Max_ , Max_ new_max_, typename Value_ > | |
| constexpr auto | set_bound_unsafe (Value_ x) |
| template<typename MaxType_ , typename Value_ > | |
| constexpr auto | set_bound_by_type_unsafe (Value_ x) |
| template<typename Dest_ , typename Value_ > | |
| constexpr Dest_ | cap (Value_ x) |
| template<typename Dest_ , typename Value_ > | |
| constexpr bool | can_cast (Value_ x) |
| template<typename Dest_ , typename Value_ > | |
| constexpr Dest_ | cast (Value_ x) |
| template<typename Left_ , typename Right_ > | |
| constexpr bool | is_equal (Left_ left, Right_ right) |
| template<typename Left_ , typename Right_ > | |
| constexpr bool | is_less_than (Left_ left, Right_ right) |
| template<typename Left_ , typename Right_ > | |
| constexpr bool | is_less_than_or_equal (Left_ left, Right_ right) |
| template<typename Left_ , typename Right_ > | |
| constexpr bool | is_greater_than (Left_ left, Right_ right) |
| template<typename Left_ , typename Right_ > | |
| constexpr bool | is_greater_than_or_equal (Left_ left, Right_ right) |
| template<typename First_ , typename Second_ > | |
| constexpr auto | min (First_ first, Second_ second) |
| template<typename First_ , typename Second_ > | |
| constexpr auto | max (First_ first, Second_ second) |
| template<typename Container_ , typename Value_ > | |
| constexpr auto | as_size_type (Value_ x) |
| template<class Container_ , typename Value_ , typename ... Args_> | |
| Container_ | create (Value_ x, Args_ &&... args) |
| template<class Container_ , typename Value_ , typename ... Args_> | |
| void | resize (Container_ &container, Value_ x, Args_ &&... args) |
| template<class Container_ , typename Value_ , typename ... Args_> | |
| void | reserve (Container_ &container, Value_ x, Args_ &&... args) |
| template<typename Float_ > | |
| int | required_bits_for_float (Float_ x) |
| template<typename Integer_ , typename Float_ > | |
| Integer_ | from_float (Float_ x) |
| template<typename Float_ , typename Value_ > | |
| Float_ | to_float (Value_ x) |
| template<typename Value_ > | |
| constexpr auto | get_value (const Value_ x) |
| template<typename Value_ > | |
| constexpr auto | get_max () |
| template<typename Size_ , typename FirstIndex_ , typename FirstExtent_ , typename SecondIndex_ , typename... Remaining_> | |
| constexpr Size_ | nd_offset (FirstIndex_ x1, FirstExtent_ extent1, SecondIndex_ x2, Remaining_... remaining) |
| template<typename Dest_ , typename First_ , typename ... Args_> | |
| constexpr std::optional< Dest_ > | product_maybe (First_ first, Args_... more) |
| template<typename Dest_ , typename First_ , typename ... Args_> | |
| constexpr Dest_ | product (First_ first, Args_... more) |
| template<typename Dest_ , typename First_ , typename ... Args_> | |
| constexpr Dest_ | product_unsafe (First_ first, Args_... more) |
| template<typename Dest_ , typename First_ , typename ... Args_> | |
| constexpr std::optional< Dest_ > | sum_maybe (First_ first, Args_... more) |
| template<typename Dest_ , typename First_ , typename ... Args_> | |
| constexpr Dest_ | sum (First_ first, Args_... more) |
| template<typename Dest_ , typename Value_ > | |
| Dest_ | plus_one (Value_ x) |
| template<typename Integer_ > | |
| Integer_ & | increment (Integer_ &x) |
| template<typename Dest_ , typename First_ , typename ... Args_> | |
| constexpr Dest_ | sum_unsafe (First_ first, Args_... more) |
Sanitize sizes to avoid integer overflow.
|
constexpr |
Cast an integer to the size type of a container. This protects against overflow/wraparound when using this integer in the container's constructor or resize()/reserve() methods.
| Container_ | Container class with a size() method and a constructor that accepts the size as the first argument. |
| Value_ | Integer type of the input size. |
| x | Non-negative value representing the desired container size. |
x as the container's size's type.
|
constexpr |
|
constexpr |
Cap a non-negative integer at the largest value of a destination type. This is primarily intended for setting appropriate default values of function arguments and class variables.
| x | Non-negative value to be capped. |
x if it can be represented in Dest_, otherwise the maximum value of Dest_.
|
constexpr |
Cast a non-negative integer to a destination type, typically the size type of a C-style array or STL container. This avoids accidental overflow/wraparound from an implicit cast when x is used in new or the container's constructor.
| x | Non-negative value to be casted. |
x as a Dest_. An error is thrown if overflow/wraparound would occur. | Container_ sanisizer::create | ( | Value_ | x, |
| Args_ &&... | args ) |
Create a new container of a specified size. This protects against overflow/wraparound when casting the integer size to the container's size type, see as_size_type() for details.
| Container_ | Container class with a size() method and a constructor that accepts the size as the first argument. |
| Value_ | Integer type of the input size. |
| Args_ | Further arguments to pass to the container's constructor. |
| x | Non-negative value representing the desired container size. |
| args | Additional arguments to pass to the Container_ constructor after the size. |
x. | Integer_ sanisizer::from_float | ( | Float_ | x | ) |
Cast a non-negative floating-point number to an integer. This checks that the conversion is possible, otherwise it throws an exception. Such a cast is occasionally necessary when floating-point calculations are used to derive the size of a container, number of loop iterations, etc.
| Integer_ | Integer type. |
| Float_ | Floating-point type. |
| x | Floating-point number, usually holding some kind of size. |
x as an integer, after truncation.| std::domain_error | Thrown if x is negative or non-finite. |
| std::overflow_error | Thrown if x is too large to be stored in Integer_. |
|
constexpr |
|
constexpr |
| x | Integer value or an Bounded about an integer. |
x if it is already an integer, otherwise Bounded::value. | Integer_ & sanisizer::increment | ( | Integer_ & | x | ) |
Convenience wrapper for x = plus_one<Dest_>(x), i.e., ++x with an exception if overflow/wraparound is detected.
| Dest_ | Integer type of the destination. |
| Value_ | Integer type of the value. |
| x | Non-negative value. On output, this is incremented by 1. |
x after increment.
|
constexpr |
| Left_ | Integer type of the value on the left hand side of the comparison. This may also be a Constant or Bounded. |
| Right_ | Integer type of the value on the right hand side of the comparison. This may also be a Constant or Bounded. |
| left | Non-negative value on the left hand side of the comparison. |
| right | Non-negative value on the right hand side of the comparison. |
left is equal to right.
|
constexpr |
| Left_ | Integer type of the value on the left hand side of the comparison. This may also be a Constant or Bounded. |
| Right_ | Integer type of the value on the right hand side of the comparison. This may also be a Constant or Bounded. |
| left | Non-negative value on the left hand side of the comparison. |
| right | Non-negative value on the right hand side of the comparison. |
left is greater than right.
|
constexpr |
| Left_ | Integer type of the value on the left hand side of the comparison. This may also be a Constant or Bounded. |
| Right_ | Integer type of the value on the right hand side of the comparison. This may also be a Constant or Bounded. |
| left | Non-negative value on the left hand side of the comparison. |
| right | Non-negative value on the right hand side of the comparison. |
left is greater than or equal to right.
|
constexpr |
| Left_ | Integer type of the value on the left hand side of the comparison. This may also be a Constant or Bounded. |
| Right_ | Integer type of the value on the right hand side of the comparison. This may also be a Constant or Bounded. |
| left | Non-negative value on the left hand side of the comparison. |
| right | Non-negative value on the right hand side of the comparison. |
left is less than right.
|
constexpr |
| Left_ | Integer type of the value on the left hand side of the comparison. This may also be a Constant or Bounded. |
| Right_ | Integer type of the value on the right hand side of the comparison. This may also be a Constant or Bounded. |
| left | Non-negative value on the left hand side of the comparison. |
| right | Non-negative value on the right hand side of the comparison. |
left is less than or equal to right.
|
constexpr |
| First_ | Integer type of the first value. This may also be a Bounded or Constant. |
| Second_ | Integer type of the second value. This may also be a Bounded or Constant. |
| first | First non-negative value. |
| second | Second non-negative value. |
first and second, in the larger integer type of First_ and Second_.
|
constexpr |
| First_ | Integer type of the first value. This may also be a Bounded or Constant. |
| Second_ | Integer type of the second value. This may also be a Bounded or Constant. |
| first | First non-negative value. |
| second | Second non-negative value. |
first and second, in the smaller integer type of First_ and Second_.
|
constexpr |
Compute offsets for accessing elements in a flattened N-dimensional array (for N > 1). The first dimension is assumed to be the fastest-changing, followed by the second dimension, and so on.
| Size_ | Integer type to represent the size of the flattened array. |
| FirstIndex_ | Type of the index on the first dimension. This may be an integer type, Bounded or Constant. It is assumed that this can be safely cast to Size_, as overflow/wraparound checks should have been performed during array allocation, e.g., via product(). |
| FirstExtent_ | Type of the extent of the first dimension. This may be an integer type, Bounded or Constant. It is assumed that this can be safely cast to Size_, as overflow/wraparound checks should have been performed during array allocation, e.g., via product(). |
| SecondIndex_ | Type of the index on the second dimension. This may be an integer type, Bounded or Constant. It is assumed that this can be safely cast to Size_, as overflow/wraparound checks should have been performed during array allocation, e.g., via product(). |
| Remaining_ | Additional arguments for further dimensions. Each argument should should be either an integer type, Bounded or Constant. It is assumed that all types can be safely cast to Size_, as overflow/wraparound checks should have been performed during array allocation, e.g., product(). |
| x1 | Position on the first dimension. |
| extent1 | Extent of the first dimension. |
| x2 | Position on the second dimension. |
| remaining | Additional arguments for further dimensions. These should be (extentP, xQ) pairs where extentP is the extent of the P-th dimension and xQ is the position on the Q = P + 1-th dimension. For example, for a 3-dimensional array, we would expect an extent2 and x3 argument. |
(x1, x2, ...). | Dest_ sanisizer::plus_one | ( | Value_ | x | ) |
Convenience wrapper for sum<Dest_>(x, 1), i.e., get_value(x) + 1 with an exception if overflow/wraparound is detected.
| Dest_ | Integer type of the destination. |
| Value_ | Integer type of the value. This may also be a Bounded or Constant. |
| x | Non-negative value. |
x plus 1.
|
constexpr |
Multiply two or more non-negative values, e.g., to compute the size of a flattened N-dimensional array as the product of its dimension extents. If overflow/wraparound in the destination type is detected, an exception is thrown. (See also product_maybe() to return an empty object upon overflow/wraparound.)
For consistency, this function will also check that each input value can be cast to Dest_. This ensures that per-dimension indices/extents can be safely represented as Dest_ in later steps (e.g., nd_offset()). These checks are necessary as the product may fit in Dest_ but not the input values if any one of the inputs is zero.
| Dest_ | Integer type of the destination. |
| First_ | Integer type of the first value. This may be also be a Bounded or Constant. |
| Args_ | Integer types of additional values. Any number of these may also be Bounded or Constant. |
| first | Non-negative value to multiply. |
| more | Additional non-negative values to multiply. |
Dest_.| std::overflow_error | Thrown if an overflow/wraparound would occur. |
|
constexpr |
Multiply two or more non-negative values. If overflow/wraparound in the destination type is detected, an empty object is returned. See also product() to throw an exception upon overflow/wraparound.
For consistency, this function will also check that each input value can be cast to Dest_. See product() for more details.
| Dest_ | Integer type of the destination. |
| First_ | Integer type of the first value. This may be also be a Bounded or Constant. |
| Args_ | Integer types of additional values. Any number of these may also be Bounded or Constant. |
| first | Non-negative value to multiply. |
| more | Additional non-negative values to multiply. |
Dest_.| std::overflow_error | Thrown if an overflow/wraparound would occur. |
|
constexpr |
Unsafe alternative to product() that casts its arguments to Dest_ but does not check for overflow/wraparound. This is more efficent than product() if it is already known that the product will not overflow, e.g., when computing std::size_t offsets into a pre-allocated array.
| Dest_ | Integer type of the destination. |
| First_ | Type of the first multiplication term. This should be an integer type, Bounded or Constant. |
| Args_ | Types of additional terms. Each of these should be either an integer type, Bounded or Constant. |
| first | Non-negative term to multiply. |
| more | Additional non-negative terms to multiply. |
Dest_. | int sanisizer::required_bits_for_float | ( | Float_ | x | ) |
| Float_ | Floating-point type. |
| x | A finite non-negative integer. Specifically, a floating-point number for which the following is true: std::isfinite(x), x >= 0 and x == std::trunc(x). |
x exactly in a (two's complement) integer type.The return value can be compared to std::numeric_limits<Integer_>::digits to determine if Integer_ is large enough to store x.
| void sanisizer::reserve | ( | Container_ & | container, |
| Value_ | x, | ||
| Args_ &&... | args ) |
Reserve a container to the desired size. This protects against overflow/wraparound when casting the integer size to the container's size type, see as_size_type() for details.
In most cases involving std::vector, this protection is not necessary as the size type is unsigned and x would harmlessly wrap around to some smaller non-negative value. The reserved size would be smaller than x but would silently reallocate as necessary upon push_back() or insert() operations beyond that size. However, this function becomes useful when the user wants to ensure that no reallocations occur, either for performance reasons or to maintain iterator/pointer validity.
| Container_ | Container class with a size() method and a reserve() method that accepts the size as the first argument. |
| Value_ | Integer type of the input size. |
| Args_ | Further arguments to pass to the container's reserve() method. |
| container | An existing instance of the container. On return, its allocation is set to x. |
| x | Non-negative value representing the desired container size. |
| args | Additional arguments to pass to reserve() after the size. |
| void sanisizer::resize | ( | Container_ & | container, |
| Value_ | x, | ||
| Args_ &&... | args ) |
Resize a container to the desired size. This protects against overflow/wraparound when casting the integer size to the container's size type, see as_size_type() for details.
| Container_ | Container class with a size() method and a resize() method that accepts the size as the first argument. |
| Value_ | Integer type of the input size. |
| Args_ | Further arguments to pass to the container's resize() method. |
| container | An existing instance of the container. This is resized to size x. |
| x | Non-negative value representing the desired container size. |
| args | Additional arguments to pass to resize() after the size. |
|
constexpr |
| Max_ | Integer type of the new compile-time maximum. |
| new_max_ | The new compile-time maximum. |
| Value_ | Integer type, Bounded or Constant. |
| x | Representation of an integer value. |
x if its maximum value is less than or equal to new_max_. Otherwise, an Bounded that declares this constraint.| std::domain_error | Thrown if the value of x is greater than new_max_. |
If x is known to be less than or equal to max_, users can call set_bound_unsafe() to avoid the check.
|
constexpr |
Variant of set_bound() that uses the maximum value of an integer type.
| MaxType_ | Integer type of the new compile-time maximum. |
| Value_ | Integer type, Bounded or Constant. |
| x | Representation of an integer value. |
x if its maximum value is less than or equal to that of MaxType_. Otherwise, an Bounded that declares this constraint.If x is known to be less than or equal to max_, users can call set_bound_by_type_unsafe() to avoid the check.
|
constexpr |
Variant of set_bound_unsafe() that uses the maximum value of an integer type.
| MaxType_ | Integer type of the new compile-time maximum. |
| Value_ | Integer type, Bounded or Constant. |
| x | Representation of an integer value. This should be less than or equal to the maximum value of MaxType_. |
x if its maximum value is less than or equal to that of MaxType_. Otherwise, an Bounded that declares this constraint.
|
constexpr |
Variant of set_bound() that assumes x <= new_max_ and does not throw exceptions.
| Max_ | Integer type of the new compile-time maximum. |
| new_max_ | The new compile-time maximum. |
| Value_ | Integer type, Bounded or Constant. |
| x | Representation of an integer value. This should be no greater than new_max_. |
x if its maximum value is less than or equal to new_max_. Otherwise, an Bounded that declares this constraint.
|
constexpr |
Add two or more non-negative values, e.g., to compute the size of an array that is a concatenation of smaller arrays. If overflow/wraparound in the destination type is detected, an exception is thrown. (See also sum_maybe() to return an empty object upon overflow/wraparound.)
| Dest_ | Integer type of the destination. |
| First_ | Integer type of the first value. This may also be a Bounded or Constant. |
| Args_ | Integer types of additional values. Any number of these may also be Bounded or Constant. |
| first | First non-negative value to add. |
| more | Additional non-negative values to add. |
Dest_.| std::overflow_error | Thrown if an overflow/wraparound occurs at any summation step. |
|
constexpr |
Add two or more non-negative values. If overflow/wraparound in the destination type is detected, an empty object is returned. (See also sum() to throw an exception upon overflow/wraparound.)
| Dest_ | Integer type of the destination. |
| First_ | Integer type of the first value. This may also be a Bounded or Constant. |
| Args_ | Integer types of additional values. Any number of these may also be Bounded or Constant. |
| first | First non-negative value to add. |
| more | Additional non-negative values to add. |
Dest_, wrapped in a std::optional. An empty object is returned if overflow/wraparound is detected in the destination type at any step of the summation.
|
constexpr |
Unsafe alternative to sum() that casts its arguments to Dest_ before summation but does not check for overflow/wraparound. This is more efficent than sum() if it is already known that the sum will not overflow, e.g., when computing std::size_t offsets into a pre-allocated array.
| Dest_ | Integer type of the destination. |
| First_ | Type of the first summation term. This should be an integer type, Bounded or Constant. |
| Args_ | Types of additional terms. Each of these should be either an integer type, Bounded or Constant. |
| first | Non-negative term to sum. |
| more | Additional non-negative terms to add. |
Dest_. | Float_ sanisizer::to_float | ( | Value_ | x | ) |
Cast a non-negative integer into a (IEE-754 compliant) floating-point number. This checks that (i) there is no loss of precision and (ii) all integers smaller than the input can also be represented by the specified floating-point type.
This is motivated by the fact that some environments do not have a dedicated integer type (e.g., Javascript). In such cases, array lengths need to be stored as floating-point values. Our checks ensure that both the array length and all valid array indices can be exactly represented in the floating-point type.
Note that the purpose of this function is to preserve precision rather than to avoid undefined behavior. For IEEE-754 floats, very large integers already have a well-defined cast to positive infinity.
| Float_ | Floating-point type. This should be one of the IEEE-754 binary formats. |
| Value_ | Integer type, Bounded or Constant. |
| x | Non-negative integer, usually holding some kind of size. |
x as a floating-point number.| std::overflow_error | Thrown if Float_ cannot exactly represent all non-negative integers less than or equal to x. |