PR 52428 Range checking when reading integer values.
gcc/fortran ChangeLog: 2012-05-14 Janne Blomqvist <jb@gcc.gnu.org> PR fortran/52428 * gfortran.texi: Update _gfortran_set_options documentation. * invoke.texi: Remove runtime behavior description of -fno-range-check. * trans-decl.c (create_main_function): Don't pass the range-check setting to the library. libgfortran ChangeLog: 2012-05-14 Janne Blomqvist <jb@gcc.gnu.org> PR fortran/52428 * io/io.h (max_value): Rename to si_max, remove second argument. * io/list_read.c (convert_integer): Use unsigned types when parsing the digits, set max value depending on the sign. * io/read.c (max_value): Rename to si_max, remove second argument, simplify. (read_decimal): Set max value depending on sign, always check overflow. (read_radix): Calculate max unsigned value directly. * libgfortran.h (struct compile_options_t): Remove range_check field. * runtime/compile_options.c (set_options): Skip handling options[7]. (init_compile_options): Don't set removed field. gcc/testsuite ChangeLog: 2012-05-14 Janne Blomqvist <jb@gcc.gnu.org> PR fortran/52428 * gfortran.dg/int_range_io_1.f90: New test. From-SVN: r187478
This commit is contained in:
parent
f62866740b
commit
80b91c0b39
@ -1,3 +1,12 @@
|
|||||||
|
2012-05-14 Janne Blomqvist <jb@gcc.gnu.org>
|
||||||
|
|
||||||
|
PR fortran/52428
|
||||||
|
* gfortran.texi: Update _gfortran_set_options documentation.
|
||||||
|
* invoke.texi: Remove runtime behavior description of
|
||||||
|
-fno-range-check.
|
||||||
|
* trans-decl.c (create_main_function): Don't pass the range-check
|
||||||
|
setting to the library.
|
||||||
|
|
||||||
2012-05-14 Tobias Burnus <burnus@net-b.de>
|
2012-05-14 Tobias Burnus <burnus@net-b.de>
|
||||||
|
|
||||||
PR fortran/49110
|
PR fortran/49110
|
||||||
|
@ -2740,15 +2740,13 @@ Default: enabled.
|
|||||||
are (bitwise or-ed): GFC_RTCHECK_BOUNDS (1), GFC_RTCHECK_ARRAY_TEMPS (2),
|
are (bitwise or-ed): GFC_RTCHECK_BOUNDS (1), GFC_RTCHECK_ARRAY_TEMPS (2),
|
||||||
GFC_RTCHECK_RECURSION (4), GFC_RTCHECK_DO (16), GFC_RTCHECK_POINTER (32).
|
GFC_RTCHECK_RECURSION (4), GFC_RTCHECK_DO (16), GFC_RTCHECK_POINTER (32).
|
||||||
Default: disabled.
|
Default: disabled.
|
||||||
@item @var{option}[7] @tab If non zero, range checking is enabled.
|
|
||||||
Default: enabled. See -frange-check (@pxref{Code Gen Options}).
|
|
||||||
@end multitable
|
@end multitable
|
||||||
|
|
||||||
@item @emph{Example}:
|
@item @emph{Example}:
|
||||||
@smallexample
|
@smallexample
|
||||||
/* Use gfortran 4.7 default options. */
|
/* Use gfortran 4.8 default options. */
|
||||||
static int options[] = @{68, 511, 0, 0, 1, 1, 0, 1@};
|
static int options[] = @{68, 511, 0, 0, 1, 1, 0@};
|
||||||
_gfortran_set_options (8, &options);
|
_gfortran_set_options (7, &options);
|
||||||
@end smallexample
|
@end smallexample
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@ -166,8 +166,7 @@ and warnings}.
|
|||||||
|
|
||||||
@item Runtime Options
|
@item Runtime Options
|
||||||
@xref{Runtime Options,,Options for influencing runtime behavior}.
|
@xref{Runtime Options,,Options for influencing runtime behavior}.
|
||||||
@gccoptlist{-fconvert=@var{conversion} -fmax-subrecord-length=@var{length}
|
@gccoptlist{-fconvert=@var{conversion} -fmax-subrecord-length=@var{length} @gol
|
||||||
-fno-range-check @gol
|
|
||||||
-frecord-marker=@var{length} -fsign-zero
|
-frecord-marker=@var{length} -fsign-zero
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1116,16 +1115,6 @@ representation for unformatted files.
|
|||||||
The @code{CONVERT} specifier and the GFORTRAN_CONVERT_UNIT environment
|
The @code{CONVERT} specifier and the GFORTRAN_CONVERT_UNIT environment
|
||||||
variable override the default specified by @option{-fconvert}.}
|
variable override the default specified by @option{-fconvert}.}
|
||||||
|
|
||||||
|
|
||||||
@item -fno-range-check
|
|
||||||
@opindex @code{fno-range-check}
|
|
||||||
Disable range checking of input values during integer @code{READ} operations.
|
|
||||||
For example, GNU Fortran will give an error if an input value is
|
|
||||||
outside of the relevant range of [@code{-HUGE()}:@code{HUGE()}]. In other words,
|
|
||||||
with @code{INTEGER (kind=4) :: i} , attempting to read @math{-2147483648} will
|
|
||||||
give an error unless @option{-fno-range-check} is given.
|
|
||||||
|
|
||||||
|
|
||||||
@item -frecord-marker=@var{length}
|
@item -frecord-marker=@var{length}
|
||||||
@opindex @code{frecord-marker=}@var{length}
|
@opindex @code{frecord-marker=}@var{length}
|
||||||
Specify the length of record markers for unformatted files.
|
Specify the length of record markers for unformatted files.
|
||||||
|
@ -5039,12 +5039,17 @@ create_main_function (tree fndecl)
|
|||||||
build_int_cst (integer_type_node,
|
build_int_cst (integer_type_node,
|
||||||
(gfc_option.rtcheck
|
(gfc_option.rtcheck
|
||||||
& GFC_RTCHECK_BOUNDS)));
|
& GFC_RTCHECK_BOUNDS)));
|
||||||
|
/* TODO: This is the -frange-check option, which no longer affects
|
||||||
|
library behavior; when bumping the library ABI this slot can be
|
||||||
|
reused for something else. As it is the last element in the
|
||||||
|
array, we can instead leave it out altogether.
|
||||||
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
|
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
|
||||||
build_int_cst (integer_type_node,
|
build_int_cst (integer_type_node,
|
||||||
gfc_option.flag_range_check));
|
gfc_option.flag_range_check));
|
||||||
|
*/
|
||||||
|
|
||||||
array_type = build_array_type (integer_type_node,
|
array_type = build_array_type (integer_type_node,
|
||||||
build_index_type (size_int (7)));
|
build_index_type (size_int (6)));
|
||||||
array = build_constructor (array_type, v);
|
array = build_constructor (array_type, v);
|
||||||
TREE_CONSTANT (array) = 1;
|
TREE_CONSTANT (array) = 1;
|
||||||
TREE_STATIC (array) = 1;
|
TREE_STATIC (array) = 1;
|
||||||
@ -5059,7 +5064,7 @@ create_main_function (tree fndecl)
|
|||||||
|
|
||||||
tmp = build_call_expr_loc (input_location,
|
tmp = build_call_expr_loc (input_location,
|
||||||
gfor_fndecl_set_options, 2,
|
gfor_fndecl_set_options, 2,
|
||||||
build_int_cst (integer_type_node, 8), var);
|
build_int_cst (integer_type_node, 7), var);
|
||||||
gfc_add_expr_to_block (&body, tmp);
|
gfc_add_expr_to_block (&body, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2012-05-14 Janne Blomqvist <jb@gcc.gnu.org>
|
||||||
|
|
||||||
|
PR fortran/52428
|
||||||
|
* gfortran.dg/int_range_io_1.f90: New test.
|
||||||
|
|
||||||
2012-05-14 Andi Kleen <ak@linux.intel.com>
|
2012-05-14 Andi Kleen <ak@linux.intel.com>
|
||||||
Jakub Jelinek <jakub@redhat.com>
|
Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
34
gcc/testsuite/gfortran.dg/int_range_io_1.f90
Normal file
34
gcc/testsuite/gfortran.dg/int_range_io_1.f90
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
! { dg-do run }
|
||||||
|
! { dg-options "-fno-range-check" }
|
||||||
|
! PR 52428 Read IO of integers near the end of range. Note that we
|
||||||
|
! support the two's complement representation even though the Fortran
|
||||||
|
! numerical model has a symmetric range. (The -fno-range-check option
|
||||||
|
! is needed to allow the -2147483648 literal.)
|
||||||
|
program int_range
|
||||||
|
implicit none
|
||||||
|
character(25) :: inputline = "-2147483648"
|
||||||
|
integer(4) :: test
|
||||||
|
integer :: st
|
||||||
|
|
||||||
|
read(inputline,100) test
|
||||||
|
100 format(1i11)
|
||||||
|
if (test /= -2147483648) call abort
|
||||||
|
inputline(1:1) = " "
|
||||||
|
read(inputline, 100, iostat=st) test
|
||||||
|
if (st == 0) call abort
|
||||||
|
inputline(11:11) = "7"
|
||||||
|
read(inputline, 100) test
|
||||||
|
if (test /= 2147483647) call abort
|
||||||
|
|
||||||
|
! Same as above but with list-formatted IO
|
||||||
|
inputline = "-2147483648"
|
||||||
|
read(inputline, *) test
|
||||||
|
if (test /= -2147483648) call abort
|
||||||
|
inputline(1:1) = " "
|
||||||
|
read(inputline, *, iostat=st) test
|
||||||
|
if (st == 0) call abort
|
||||||
|
inputline(11:11) = "7"
|
||||||
|
read(inputline, *) test
|
||||||
|
if (test /= 2147483647) call abort
|
||||||
|
|
||||||
|
end program int_range
|
@ -1,3 +1,20 @@
|
|||||||
|
2012-05-14 Janne Blomqvist <jb@gcc.gnu.org>
|
||||||
|
|
||||||
|
PR fortran/52428
|
||||||
|
* io/io.h (max_value): Rename to si_max, remove second argument.
|
||||||
|
* io/list_read.c (convert_integer): Use unsigned types when
|
||||||
|
parsing the digits, set max value depending on the sign.
|
||||||
|
* io/read.c (max_value): Rename to si_max, remove second argument,
|
||||||
|
simplify.
|
||||||
|
(read_decimal): Set max value depending on sign, always check
|
||||||
|
overflow.
|
||||||
|
(read_radix): Calculate max unsigned value directly.
|
||||||
|
* libgfortran.h (struct compile_options_t): Remove range_check
|
||||||
|
field.
|
||||||
|
* runtime/compile_options.c (set_options): Skip handling
|
||||||
|
options[7].
|
||||||
|
(init_compile_options): Don't set removed field.
|
||||||
|
|
||||||
2012-05-11 Tobias Burnus <burnus@net-b.de>
|
2012-05-11 Tobias Burnus <burnus@net-b.de>
|
||||||
|
|
||||||
PR fortran/53310
|
PR fortran/53310
|
||||||
|
@ -661,8 +661,8 @@ internal_proto(hit_eof);
|
|||||||
extern void set_integer (void *, GFC_INTEGER_LARGEST, int);
|
extern void set_integer (void *, GFC_INTEGER_LARGEST, int);
|
||||||
internal_proto(set_integer);
|
internal_proto(set_integer);
|
||||||
|
|
||||||
extern GFC_UINTEGER_LARGEST max_value (int, int);
|
extern GFC_UINTEGER_LARGEST si_max (int);
|
||||||
internal_proto(max_value);
|
internal_proto(si_max);
|
||||||
|
|
||||||
extern int convert_real (st_parameter_dt *, void *, const char *, int);
|
extern int convert_real (st_parameter_dt *, void *, const char *, int);
|
||||||
internal_proto(convert_real);
|
internal_proto(convert_real);
|
||||||
|
@ -461,12 +461,20 @@ convert_integer (st_parameter_dt *dtp, int length, int negative)
|
|||||||
{
|
{
|
||||||
char c, *buffer, message[MSGLEN];
|
char c, *buffer, message[MSGLEN];
|
||||||
int m;
|
int m;
|
||||||
GFC_INTEGER_LARGEST v, max, max10;
|
GFC_UINTEGER_LARGEST v, max, max10;
|
||||||
|
GFC_INTEGER_LARGEST value;
|
||||||
|
|
||||||
buffer = dtp->u.p.saved_string;
|
buffer = dtp->u.p.saved_string;
|
||||||
v = 0;
|
v = 0;
|
||||||
|
|
||||||
max = (length == -1) ? MAX_REPEAT : max_value (length, 1);
|
if (length == -1)
|
||||||
|
max = MAX_REPEAT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
max = si_max (length);
|
||||||
|
if (negative)
|
||||||
|
max++;
|
||||||
|
}
|
||||||
max10 = max / 10;
|
max10 = max / 10;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
@ -490,8 +498,10 @@ convert_integer (st_parameter_dt *dtp, int length, int negative)
|
|||||||
if (length != -1)
|
if (length != -1)
|
||||||
{
|
{
|
||||||
if (negative)
|
if (negative)
|
||||||
v = -v;
|
value = -v;
|
||||||
set_integer (dtp->u.p.value, v, length);
|
else
|
||||||
|
value = v;
|
||||||
|
set_integer (dtp->u.p.value, value, length);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -87,46 +87,34 @@ set_integer (void *dest, GFC_INTEGER_LARGEST value, int length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* max_value()-- Given a length (kind), return the maximum signed or
|
/* Max signed value of size give by length argument. */
|
||||||
* unsigned value */
|
|
||||||
|
|
||||||
GFC_UINTEGER_LARGEST
|
GFC_UINTEGER_LARGEST
|
||||||
max_value (int length, int signed_flag)
|
si_max (int length)
|
||||||
{
|
{
|
||||||
GFC_UINTEGER_LARGEST value;
|
GFC_UINTEGER_LARGEST value;
|
||||||
#if defined HAVE_GFC_REAL_16 || defined HAVE_GFC_REAL_10
|
|
||||||
int n;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (length)
|
switch (length)
|
||||||
{
|
{
|
||||||
#if defined HAVE_GFC_REAL_16 || defined HAVE_GFC_REAL_10
|
#if defined HAVE_GFC_REAL_16 || defined HAVE_GFC_REAL_10
|
||||||
case 16:
|
case 16:
|
||||||
case 10:
|
case 10:
|
||||||
value = 1;
|
value = 1;
|
||||||
for (n = 1; n < 4 * length; n++)
|
for (int n = 1; n < 4 * length; n++)
|
||||||
value = (value << 2) + 3;
|
value = (value << 2) + 3;
|
||||||
if (! signed_flag)
|
return value;
|
||||||
value = 2*value+1;
|
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
case 8:
|
case 8:
|
||||||
value = signed_flag ? 0x7fffffffffffffff : 0xffffffffffffffff;
|
return GFC_INTEGER_8_HUGE;
|
||||||
break;
|
|
||||||
case 4:
|
case 4:
|
||||||
value = signed_flag ? 0x7fffffff : 0xffffffff;
|
return GFC_INTEGER_4_HUGE;
|
||||||
break;
|
|
||||||
case 2:
|
case 2:
|
||||||
value = signed_flag ? 0x7fff : 0xffff;
|
return GFC_INTEGER_2_HUGE;
|
||||||
break;
|
|
||||||
case 1:
|
case 1:
|
||||||
value = signed_flag ? 0x7f : 0xff;
|
return GFC_INTEGER_1_HUGE;
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
internal_error (NULL, "Bad integer kind");
|
internal_error (NULL, "Bad integer kind");
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -634,11 +622,7 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
maxv = max_value (length, 1);
|
|
||||||
maxv_10 = maxv / 10;
|
|
||||||
|
|
||||||
negative = 0;
|
negative = 0;
|
||||||
value = 0;
|
|
||||||
|
|
||||||
switch (*p)
|
switch (*p)
|
||||||
{
|
{
|
||||||
@ -656,6 +640,11 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxv = si_max (length);
|
||||||
|
if (negative)
|
||||||
|
maxv++;
|
||||||
|
maxv_10 = maxv / 10;
|
||||||
|
|
||||||
/* At this point we have a digit-string */
|
/* At this point we have a digit-string */
|
||||||
value = 0;
|
value = 0;
|
||||||
|
|
||||||
@ -674,20 +663,21 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
|||||||
if (c < '0' || c > '9')
|
if (c < '0' || c > '9')
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
if (value > maxv_10 && compile_options.range_check == 1)
|
if (value > maxv_10)
|
||||||
goto overflow;
|
goto overflow;
|
||||||
|
|
||||||
c -= '0';
|
c -= '0';
|
||||||
value = 10 * value;
|
value = 10 * value;
|
||||||
|
|
||||||
if (value > maxv - c && compile_options.range_check == 1)
|
if (value > maxv - c)
|
||||||
goto overflow;
|
goto overflow;
|
||||||
value += c;
|
value += c;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = value;
|
|
||||||
if (negative)
|
if (negative)
|
||||||
v = -v;
|
v = -value;
|
||||||
|
else
|
||||||
|
v = value;
|
||||||
|
|
||||||
set_integer (dest, v, length);
|
set_integer (dest, v, length);
|
||||||
return;
|
return;
|
||||||
@ -734,7 +724,8 @@ read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
maxv = max_value (length, 0);
|
/* Maximum unsigned value, assuming two's complement. */
|
||||||
|
maxv = 2 * si_max (length) + 1;
|
||||||
maxv_r = maxv / radix;
|
maxv_r = maxv / radix;
|
||||||
|
|
||||||
negative = 0;
|
negative = 0;
|
||||||
|
@ -535,7 +535,6 @@ typedef struct
|
|||||||
size_t record_marker;
|
size_t record_marker;
|
||||||
int max_subrecord_length;
|
int max_subrecord_length;
|
||||||
int bounds_check;
|
int bounds_check;
|
||||||
int range_check;
|
|
||||||
}
|
}
|
||||||
compile_options_t;
|
compile_options_t;
|
||||||
|
|
||||||
|
@ -169,8 +169,10 @@ set_options (int num, int options[])
|
|||||||
compile_options.sign_zero = options[5];
|
compile_options.sign_zero = options[5];
|
||||||
if (num >= 7)
|
if (num >= 7)
|
||||||
compile_options.bounds_check = options[6];
|
compile_options.bounds_check = options[6];
|
||||||
if (num >= 8)
|
/* options[7] is the -frange-check option, which no longer affects
|
||||||
compile_options.range_check = options[7];
|
the library behavior; range checking is now always done when
|
||||||
|
parsing integers. It's place in the options array is retained due
|
||||||
|
to ABI compatibility. Remove when bumping the library ABI. */
|
||||||
|
|
||||||
/* If backtrace is required, we set signal handlers on the POSIX
|
/* If backtrace is required, we set signal handlers on the POSIX
|
||||||
2001 signals with core action. */
|
2001 signals with core action. */
|
||||||
@ -223,7 +225,6 @@ init_compile_options (void)
|
|||||||
compile_options.pedantic = 0;
|
compile_options.pedantic = 0;
|
||||||
compile_options.backtrace = 0;
|
compile_options.backtrace = 0;
|
||||||
compile_options.sign_zero = 1;
|
compile_options.sign_zero = 1;
|
||||||
compile_options.range_check = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function called by the front-end to tell us the
|
/* Function called by the front-end to tell us the
|
||||||
|
Loading…
Reference in New Issue
Block a user