Mercurial > octave
changeset 23965:6f0c2963674b
allow large ints to be read by C-style scanf (bug #51794)
* oct-stream.cc (base_stream::do_oscanf): For 'd', 'i', 'o', 'u', and
'x' conversions, handle 'h' and 'l' modifiers in the same way as in
do_scanf.
* io.tst: New tests.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 29 Aug 2017 12:21:42 -0400 |
parents | 1a0cbb573a67 |
children | b833c7334308 |
files | libinterp/corefcn/oct-stream.cc test/io.tst |
diffstat | 2 files changed, 92 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/oct-stream.cc Tue Aug 29 18:01:48 2017 +0200 +++ b/libinterp/corefcn/oct-stream.cc Tue Aug 29 12:21:42 2017 -0400 @@ -5057,29 +5057,93 @@ case 'd': case 'i': { - int tmp; - - if (octave_scan (is, *elt, &tmp)) + switch (elt->modifier) { - if (! discard) - retval = tmp; + case 'h': + { + int16_t tmp; + if (octave_scan (is, *elt, &tmp)) + { + if (! discard) + retval = tmp; + } + else + quit = true; + } + break; + + case 'l': + { + int64_t tmp; + if (octave_scan (is, *elt, &tmp)) + { + if (! discard) + retval = tmp; + } + else + quit = true; + } + break; + + default: + { + int32_t tmp; + if (octave_scan (is, *elt, &tmp)) + { + if (! discard) + retval = tmp; + } + else + quit = true; + } + break; } - else - quit = true; } break; case 'o': case 'u': case 'x': { - long int tmp; - - if (octave_scan (is, *elt, &tmp)) + switch (elt->modifier) { - if (! discard) - retval = tmp; + case 'h': + { + uint16_t tmp; + if (octave_scan (is, *elt, &tmp)) + { + if (! discard) + retval = tmp; + } + else + quit = true; + } + break; + + case 'l': + { + uint64_t tmp; + if (octave_scan (is, *elt, &tmp)) + { + if (! discard) + retval = tmp; + } + else + quit = true; + } + break; + + default: + { + uint32_t tmp; + if (octave_scan (is, *elt, &tmp)) + { + if (! discard) + retval = tmp; + } + else + quit = true; + } + break; } - else - quit = true; } break;
--- a/test/io.tst Tue Aug 29 18:01:48 2017 +0200 +++ b/test/io.tst Tue Aug 29 12:21:42 2017 -0400 @@ -312,6 +312,20 @@ %!assert (sscanf ('7777777777777777777777', '%lo'), double (intmax ("uint64"))) %!assert (sscanf ('ffffffffffffffffffffff', '%lx'), double (intmax ("uint64"))) +## bug 51794 +%!assert (sscanf ('2147483647', '%d', 'C'), 2147483647) +%!assert (sscanf ('2147483647', '%i', 'C'), 2147483647) +%!assert (sscanf ('4294967295', '%u', 'C'), 4294967295) +%!assert (sscanf ('37777777777', '%o', 'C'), 4294967295) +%!assert (sscanf ('ffffffff', '%x', 'C'), 4294967295) +## FIXME: scanf should return int64/uint64 if all conversions are %l[dioux]. +## Until then only test values that are within precision range of a double. +%!assert (sscanf ('281474976710655', '%ld', 'C'), 281474976710655) +%!assert (sscanf ('281474976710655', '%li', 'C'), 281474976710655) +%!assert (sscanf ('281474976710655', '%lu', 'C'), 281474976710655) +%!assert (sscanf ('7777777777777777', '%lo', 'C'), 281474976710655) +%!assert (sscanf ('ffffffffffff', '%lx', 'C'), 281474976710655) + %!test %! [val, count, msg, pos] = sscanf ("3I2", "%f"); %! assert (val, 3);