# HG changeset patch # User John W. Eaton # Date 1631196492 14400 # Node ID a4d1c080e445c52987c965db84db992dd4b1324e # Parent 58f043641a78229dbdbef9affdb647a93a7c514f fix construction of ranges with extreme integer values (bug #61132) * ov.cc (check_colon_operand): New template. (make_range): Use it. * range.tst: New test. diff -r 58f043641a78 -r a4d1c080e445 libinterp/octave-value/ov.cc --- a/libinterp/octave-value/ov.cc Wed Sep 08 16:02:04 2021 -0700 +++ b/libinterp/octave-value/ov.cc Thu Sep 09 10:08:12 2021 -0400 @@ -27,6 +27,8 @@ # include "config.h" #endif +#include + #include "data-conv.h" #include "quit.h" #include "str-vec.h" @@ -3001,7 +3003,26 @@ return get_colon_op_type (typ, limit.builtin_type ()); } - // Templated version used for various integer types (int8, uint16, ...) + // This check depends on the type of VAL either being the expected + // integer type or a double value. + + template + static void + check_colon_operand (const octave_value& val, const char *op_str) + { + if (! val.is_double_type ()) + return; + + double dval = val.double_value (); + double intpart; + + if (dval > std::numeric_limits::max () + || dval < std::numeric_limits::min () + || std::modf (dval, &intpart) != 0.0) + error ("colon operator %s invalid (not an integer or out of range for given integer type)", op_str); + } + +// Templated version used for various integer types (int8, uint16, ...) template octave_value make_range (const octave_value& base, const octave_value& increment, @@ -3010,22 +3031,15 @@ if (base.isempty () || increment.isempty () || limit.isempty ()) return octave_value (range (), for_cmd_expr); - double dval; + check_colon_operand (base, "lower bound"); + check_colon_operand (increment, "increment"); + check_colon_operand (limit, "upper bound"); T base_val = octave_value_extract (base); - dval = base.double_value (); - if (base_val != dval) - error ("colon operator lower bound invalid (not an integer or out of range for given integer type)"); T increment_val = octave_value_extract (increment); - dval = increment.double_value (); - if (increment_val != dval) - error ("colon operator increment invalid (not an integer or out of range for given integer type)"); T limit_val = octave_value_extract (limit); - dval = limit.double_value (); - if (limit_val != dval) - error ("colon operator upper bound invalid (not an integer or out of range for given integer type)"); range r (base_val, increment_val, limit_val); diff -r 58f043641a78 -r a4d1c080e445 test/range.tst --- a/test/range.tst Wed Sep 08 16:02:04 2021 -0700 +++ b/test/range.tst Thu Sep 09 10:08:12 2021 -0400 @@ -79,6 +79,9 @@ %!assert ([ r ; uint32(z) ], uint32 (expect)) %!assert ([ r ; uint64(z) ], uint64 (expect)) + + + ## Test corner cases of ranges (base and limit) %!shared r, rrev, rneg @@ -483,6 +486,7 @@ %!error (1:1:{5}) %!error (int8(1):int16(1):5) %!error (int8(1):1:int16(5)) + ## Tests with mixed integer/floating point values %!error (1.5:uint8(1):5) %!error (-1:uint8(1):5) @@ -490,3 +494,20 @@ %!error (uint8(1):-1:5) %!error (uint8(1):1:5.5) %!error (uint8(1):1:256) + +## Extreme integer values. +%!test <61132> +%! types = {"int8", "int16", "int32", "int64", ... +%! "uint8", "uint16", "uint32", "uint64"}; +%! for i = 1:numel (types) +%! cls = types{i}; +%! lo = intmin (cls); +%! hi = intmax (cls); +%! n = 99; +%! rlo = lo:(lo+n); +%! rhi = (hi-n):hi; +%! assert (class (rlo), cls); +%! assert (class (rhi), cls); +%! assert (numel (rlo), n+1); +%! assert (numel (rhi), n+1); +%! endfor