mirror of https://github.com/ecmwf/eccodes.git
ECC-1930: Fix overflow using compile-time code
This commit is contained in:
parent
51c717e75d
commit
39641acf3b
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* (C) Copyright 2005- ECMWF.
|
||||
*
|
||||
* This software is licensed under the terms of the Apache Licence Version 2.0
|
||||
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
|
||||
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
template <typename ValueType>
|
||||
struct NumericLimits
|
||||
{
|
||||
static_assert(std::is_integral<ValueType>::value, "ValueType must be an integral type");
|
||||
|
||||
private:
|
||||
using S = std::make_signed_t<ValueType>;
|
||||
using U = std::make_unsigned_t<ValueType>;
|
||||
static constexpr int MaxN = 8 * sizeof(ValueType);
|
||||
|
||||
static constexpr std::array<ValueType, MaxN> max_ = []() {
|
||||
if constexpr (std::is_signed<ValueType>::value) {
|
||||
std::array<S, MaxN> max{};
|
||||
for (int i = 1; i < MaxN; ++i) {
|
||||
auto ones = ~(static_cast<U>(0));
|
||||
max[i] = static_cast<S>(ones >> (MaxN - i));
|
||||
}
|
||||
return max;
|
||||
}
|
||||
else {
|
||||
std::array<U, MaxN> max{};
|
||||
for (int i = 1; i < MaxN; ++i) {
|
||||
auto ones = ~(static_cast<U>(0));
|
||||
max[i] = ones >> (MaxN - i - 1);
|
||||
}
|
||||
return max;
|
||||
}
|
||||
}();
|
||||
|
||||
static constexpr std::array<ValueType, MaxN> min_ = []() {
|
||||
if constexpr (std::is_signed<ValueType>::value) {
|
||||
std::array<S, MaxN> min{};
|
||||
for (int i = 1; i < MaxN; ++i) {
|
||||
min[i] = ~max_[i];
|
||||
}
|
||||
return min;
|
||||
}
|
||||
else {
|
||||
return std::array<U, MaxN>{};
|
||||
}
|
||||
}();
|
||||
|
||||
public:
|
||||
static constexpr ValueType min(int nbits)
|
||||
{
|
||||
if constexpr (std::is_signed<ValueType>::value)
|
||||
return min_[nbits - 1];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static constexpr ValueType max(int nbits)
|
||||
{
|
||||
return max_[nbits - 1];
|
||||
}
|
||||
};
|
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
|
||||
#include "grib_accessor_class_signed.h"
|
||||
#include "NumericLimits.h"
|
||||
|
||||
grib_accessor_signed_t _grib_accessor_signed{};
|
||||
grib_accessor* grib_accessor_signed = &_grib_accessor_signed;
|
||||
|
@ -118,8 +119,8 @@ int grib_accessor_signed_t::pack_long(const long* val, size_t* len)
|
|||
else {
|
||||
// ECC-1605: Check overflow/underflow
|
||||
const int nbits = nbytes_ * 8;
|
||||
const long minval = -(1L << (nbits - 1)) + 1;
|
||||
const long maxval = (1L << (nbits - 1)) - 1;
|
||||
const long minval = NumericLimits<long>::min(nbits);
|
||||
const long maxval = NumericLimits<long>::max(nbits);
|
||||
// printf(" key=%s: v=%ld (minval=%ld maxval=%ld)\n", name_ , v, minval, maxval);
|
||||
if (v > maxval || v < minval) {
|
||||
grib_context_log(context_, GRIB_LOG_ERROR,
|
||||
|
|
Loading…
Reference in New Issue