re PR fortran/45143 ([F2008,corrig1] Endless loop with unlimited edit descriptor)

2010-08-07  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libfortran/45143
	* io/format.c: Remove fnode storage structure definitions, moving these
	to format.h. (parse_format_list): Add check for data descriptors,
	taking care of nested formats. Adjust calling parameters to pass a
	check flag. (parse_format): Likewise.
	* io/format.h: Add structures moved from format.c.

From-SVN: r162978
This commit is contained in:
Jerry DeLisle 2010-08-07 12:03:23 +00:00
parent 17fec01dd4
commit da0747b9b5
3 changed files with 51 additions and 30 deletions

View File

@ -1,3 +1,12 @@
2010-08-07 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libfortran/45143
* io/format.c: Remove fnode storage structure definitions, moving these
to format.h. (parse_format_list): Add check for data descriptors,
taking care of nested formats. Adjust calling parameters to pass a
check flag. (parse_format): Likewise.
* io/format.h: Add structures moved from format.c.
2010-08-02 Janne Blomqvist <jb@gcc.gnu.org> 2010-08-02 Janne Blomqvist <jb@gcc.gnu.org>
* io/unit.c (update_position): Don't update the position flag for * io/unit.c (update_position): Don't update the position flag for

View File

@ -35,28 +35,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#define FARRAY_SIZE 64
typedef struct fnode_array
{
struct fnode_array *next;
fnode array[FARRAY_SIZE];
}
fnode_array;
typedef struct format_data
{
char *format_string, *string;
const char *error;
char error_element;
format_token saved_token;
int value, format_string_len, reversion_ok;
fnode *avail;
const fnode *saved_format;
fnode_array *last;
fnode_array array;
}
format_data;
static const fnode colon_node = { FMT_COLON, 0, NULL, NULL, {{ 0, 0, 0 }}, 0, static const fnode colon_node = { FMT_COLON, 0, NULL, NULL, {{ 0, 0, 0 }}, 0,
NULL }; NULL };
@ -612,13 +590,13 @@ format_lex (format_data *fmt)
* parenthesis node which contains the rest of the list. */ * parenthesis node which contains the rest of the list. */
static fnode * static fnode *
parse_format_list (st_parameter_dt *dtp, bool *save_ok) parse_format_list (st_parameter_dt *dtp, bool *save_ok, bool *seen_dd)
{ {
fnode *head, *tail; fnode *head, *tail;
format_token t, u, t2; format_token t, u, t2;
int repeat; int repeat;
format_data *fmt = dtp->u.p.fmt; format_data *fmt = dtp->u.p.fmt;
bool saveit; bool saveit, seen_data_desc = false;
head = tail = NULL; head = tail = NULL;
saveit = *save_ok; saveit = *save_ok;
@ -638,10 +616,14 @@ parse_format_list (st_parameter_dt *dtp, bool *save_ok)
} }
get_fnode (fmt, &head, &tail, FMT_LPAREN); get_fnode (fmt, &head, &tail, FMT_LPAREN);
tail->repeat = -2; /* Signifies unlimited format. */ tail->repeat = -2; /* Signifies unlimited format. */
tail->u.child = parse_format_list (dtp, &saveit); tail->u.child = parse_format_list (dtp, &saveit, &seen_data_desc);
if (fmt->error != NULL) if (fmt->error != NULL)
goto finished; goto finished;
if (!seen_data_desc)
{
fmt->error = "'*' requires at least one associated data descriptor";
goto finished;
}
goto between_desc; goto between_desc;
case FMT_POSINT: case FMT_POSINT:
@ -653,7 +635,8 @@ parse_format_list (st_parameter_dt *dtp, bool *save_ok)
case FMT_LPAREN: case FMT_LPAREN:
get_fnode (fmt, &head, &tail, FMT_LPAREN); get_fnode (fmt, &head, &tail, FMT_LPAREN);
tail->repeat = repeat; tail->repeat = repeat;
tail->u.child = parse_format_list (dtp, &saveit); tail->u.child = parse_format_list (dtp, &saveit, &seen_data_desc);
*seen_dd = seen_data_desc;
if (fmt->error != NULL) if (fmt->error != NULL)
goto finished; goto finished;
@ -680,7 +663,8 @@ parse_format_list (st_parameter_dt *dtp, bool *save_ok)
case FMT_LPAREN: case FMT_LPAREN:
get_fnode (fmt, &head, &tail, FMT_LPAREN); get_fnode (fmt, &head, &tail, FMT_LPAREN);
tail->repeat = 1; tail->repeat = 1;
tail->u.child = parse_format_list (dtp, &saveit); tail->u.child = parse_format_list (dtp, &saveit, &seen_data_desc);
*seen_dd = seen_data_desc;
if (fmt->error != NULL) if (fmt->error != NULL)
goto finished; goto finished;
@ -821,6 +805,7 @@ parse_format_list (st_parameter_dt *dtp, bool *save_ok)
case FMT_F: case FMT_F:
case FMT_G: case FMT_G:
repeat = 1; repeat = 1;
*seen_dd = true;
goto data_desc; goto data_desc;
case FMT_H: case FMT_H:
@ -1217,7 +1202,7 @@ void
parse_format (st_parameter_dt *dtp) parse_format (st_parameter_dt *dtp)
{ {
format_data *fmt; format_data *fmt;
bool format_cache_ok; bool format_cache_ok, seen_data_desc = false;
/* Don't cache for internal units and set an arbitrary limit on the size of /* Don't cache for internal units and set an arbitrary limit on the size of
format strings we will cache. (Avoids memory issues.) */ format strings we will cache. (Avoids memory issues.) */
@ -1266,7 +1251,8 @@ parse_format (st_parameter_dt *dtp)
fmt->avail++; fmt->avail++;
if (format_lex (fmt) == FMT_LPAREN) if (format_lex (fmt) == FMT_LPAREN)
fmt->array.array[0].u.child = parse_format_list (dtp, &format_cache_ok); fmt->array.array[0].u.child = parse_format_list (dtp, &format_cache_ok,
&seen_data_desc);
else else
fmt->error = "Missing initial left parenthesis in format"; fmt->error = "Missing initial left parenthesis in format";

View File

@ -92,6 +92,32 @@ struct fnode
}; };
/* A storage structures for format node data. */
#define FARRAY_SIZE 64
typedef struct fnode_array
{
struct fnode_array *next;
fnode array[FARRAY_SIZE];
}
fnode_array;
typedef struct format_data
{
char *format_string, *string;
const char *error;
char error_element;
format_token saved_token;
int value, format_string_len, reversion_ok;
fnode *avail;
const fnode *saved_format;
fnode_array *last;
fnode_array array;
}
format_data;
extern void parse_format (st_parameter_dt *); extern void parse_format (st_parameter_dt *);
internal_proto(parse_format); internal_proto(parse_format);