Mercurial > octave
changeset 27781:61cc648ab034
prevent crash if dynamic printf field widths are out of range (bug #57368)
* oct-stream.h, oct-stream.cc (printf_value_cache::int_value):
Require value to be in range [0, INT_MAX] before conversion to int.
(base_stream::field_width_error): New function.
(base_stream::do_printf): Call field_width_error if
val_cache::int_value conversion fails.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 06 Dec 2019 14:18:15 -0600 |
parents | 0dad96574d12 |
children | 566adf9d823b |
files | libinterp/corefcn/oct-stream.cc libinterp/corefcn/oct-stream.h |
diffstat | 2 files changed, 29 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/oct-stream.cc Fri Dec 06 11:24:16 2019 -0800 +++ b/libinterp/corefcn/oct-stream.cc Fri Dec 06 14:18:15 2019 -0600 @@ -5444,7 +5444,10 @@ // Get the current value as a double and advance the internal pointer. octave_value get_next_value (char type = 0); - // Get the current value as an int and advance the internal pointer. + // Get the current value as an int and advance the internal + // pointer. Value before conversion to int must be >= 0 and less + // than std::numeric_limits<int>::max (). + int int_value (void); operator bool () const { return (curr_state == ok); } @@ -5584,18 +5587,18 @@ int printf_value_cache::int_value (void) { - int retval = 0; - octave_value val = get_next_value (); double dval = val.double_value (true); - if (math::x_nint (dval) == dval) - retval = math::nint (dval); - else - curr_state = conversion_error; - - return retval; + if (dval < 0 || dval > std::numeric_limits<int>::max () + || math::x_nint (dval) != dval) + { + curr_state = conversion_error; + return -1; + } + + return math::nint (dval); } // Ugh again and again. @@ -5857,6 +5860,13 @@ return retval; } + void + base_stream::field_width_error (const std::string& who) const + { + ::error ("%s: invalid field width, must be integer >= 0 and <= INT_MAX", + who.c_str ()); + } + int base_stream::do_printf (printf_format_list& fmt_list, const octave_value_list& args, @@ -5896,7 +5906,10 @@ sa_1 = val_cache.int_value (); if (! val_cache) - break; + { + field_width_error (who); + break; + } else { if (nsa > 1) @@ -5904,7 +5917,10 @@ sa_2 = val_cache.int_value (); if (! val_cache) - break; + { + field_width_error (who); + break; + } } } }
--- a/libinterp/corefcn/oct-stream.h Fri Dec 06 11:24:16 2019 -0800 +++ b/libinterp/corefcn/oct-stream.h Fri Dec 06 14:18:15 2019 -0600 @@ -229,6 +229,8 @@ const octave_value& val, const std::string& who); + void field_width_error (const std::string& who) const; + int do_printf (printf_format_list& fmt_list, const octave_value_list& args, const std::string& who /* = "printf" */);