Commit 45dfbe77 by Jerry DeLisle

re PR libfortran/33672 (Additional runtime checks needed for namelist reads)

2007-10-14  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libfortran/33672
	* io/list_read.c (nml_parse_qualifier): Add character specific error
	messages.  Check for proper form of sub-string qualifiers.  Return the
	parsed_rank flag indicating a non-zero rank qualifier.
	(nml_get_obj_data):  Count the instances of non-zero rank qualifiers.
	Issue an error if more that one non-zero rank qualifier is found.

From-SVN: r129309
parent 422e5664
2007-10-14 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libfortran/33672
* io/list_read.c (nml_parse_qualifier): Add character specific error
messages. Check for proper form of sub-string qualifiers. Return the
parsed_rank flag indicating a non-zero rank qualifier.
(nml_get_obj_data): Count the instances of non-zero rank qualifiers.
Issue an error if more that one non-zero rank qualifier is found.
2007-10-04 Jerry DeLisle <jvdelisle@gcc.gnu.org> 2007-10-04 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libfortran/33253 PR libfortran/33253
......
...@@ -1713,18 +1713,27 @@ calls: ...@@ -1713,18 +1713,27 @@ calls:
static try static try
nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad, nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
array_loop_spec *ls, int rank, char *parse_err_msg) array_loop_spec *ls, int rank, char *parse_err_msg,
int *parsed_rank)
{ {
int dim; int dim;
int indx; int indx;
int neg; int neg;
int null_flag; int null_flag;
int is_array_section; int is_array_section, is_char;
char c; char c;
is_char = 0;
is_array_section = 0; is_array_section = 0;
dtp->u.p.expanded_read = 0; dtp->u.p.expanded_read = 0;
/* See if this is a character substring qualifier we are looking for. */
if (rank == -1)
{
rank = 1;
is_char = 1;
}
/* The next character in the stream should be the '('. */ /* The next character in the stream should be the '('. */
c = next_char (dtp); c = next_char (dtp);
...@@ -1770,8 +1779,10 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad, ...@@ -1770,8 +1779,10 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
if ((c==',' && dim == rank -1) if ((c==',' && dim == rank -1)
|| (c==')' && dim < rank -1)) || (c==')' && dim < rank -1))
{ {
sprintf (parse_err_msg, if (is_char)
"Bad number of index fields"); sprintf (parse_err_msg, "Bad substring qualifier");
else
sprintf (parse_err_msg, "Bad number of index fields");
goto err_ret; goto err_ret;
} }
break; break;
...@@ -1786,6 +1797,10 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad, ...@@ -1786,6 +1797,10 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
break; break;
default: default:
if (is_char)
sprintf (parse_err_msg,
"Bad character in substring qualifier");
else
sprintf (parse_err_msg, "Bad character in index"); sprintf (parse_err_msg, "Bad character in index");
goto err_ret; goto err_ret;
} }
...@@ -1793,6 +1808,9 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad, ...@@ -1793,6 +1808,9 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
if ((c == ',' || c == ')') && indx == 0 if ((c == ',' || c == ')') && indx == 0
&& dtp->u.p.saved_string == 0) && dtp->u.p.saved_string == 0)
{ {
if (is_char)
sprintf (parse_err_msg, "Null substring qualifier");
else
sprintf (parse_err_msg, "Null index field"); sprintf (parse_err_msg, "Null index field");
goto err_ret; goto err_ret;
} }
...@@ -1800,7 +1818,17 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad, ...@@ -1800,7 +1818,17 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
if ((c == ':' && indx == 1 && dtp->u.p.saved_string == 0) if ((c == ':' && indx == 1 && dtp->u.p.saved_string == 0)
|| (indx == 2 && dtp->u.p.saved_string == 0)) || (indx == 2 && dtp->u.p.saved_string == 0))
{ {
sprintf(parse_err_msg, "Bad index triplet"); if (is_char)
sprintf (parse_err_msg, "Bad substring qualifier");
else
sprintf (parse_err_msg, "Bad index triplet");
goto err_ret;
}
if (is_char && !is_array_section)
{
sprintf (parse_err_msg,
"Missing colon in substring qualifier");
goto err_ret; goto err_ret;
} }
...@@ -1816,6 +1844,9 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad, ...@@ -1816,6 +1844,9 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
/* Now read the index. */ /* Now read the index. */
if (convert_integer (dtp, sizeof(ssize_t), neg)) if (convert_integer (dtp, sizeof(ssize_t), neg))
{ {
if (is_char)
sprintf (parse_err_msg, "Bad integer substring qualifier");
else
sprintf (parse_err_msg, "Bad integer in index"); sprintf (parse_err_msg, "Bad integer in index");
goto err_ret; goto err_ret;
} }
...@@ -1848,6 +1879,11 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad, ...@@ -1848,6 +1879,11 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
else else
dtp->u.p.expanded_read = 1; dtp->u.p.expanded_read = 1;
} }
/* Check for non-zero rank. */
if (is_array_section == 1 && ls[dim].start != ls[dim].end)
*parsed_rank = 1;
break; break;
} }
} }
...@@ -1858,9 +1894,13 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad, ...@@ -1858,9 +1894,13 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
|| (ls[dim].end > (ssize_t)ad[dim].ubound) || (ls[dim].end > (ssize_t)ad[dim].ubound)
|| (ls[dim].end < (ssize_t)ad[dim].lbound)) || (ls[dim].end < (ssize_t)ad[dim].lbound))
{ {
if (is_char)
sprintf (parse_err_msg, "Substring out of range");
else
sprintf (parse_err_msg, "Index %d out of range", dim + 1); sprintf (parse_err_msg, "Index %d out of range", dim + 1);
goto err_ret; goto err_ret;
} }
if (((ls[dim].end - ls[dim].start ) * ls[dim].step < 0) if (((ls[dim].end - ls[dim].start ) * ls[dim].step < 0)
|| (ls[dim].step == 0)) || (ls[dim].step == 0))
{ {
...@@ -1995,7 +2035,6 @@ nml_query (st_parameter_dt *dtp, char c) ...@@ -1995,7 +2035,6 @@ nml_query (st_parameter_dt *dtp, char c)
else else
{ {
/* "&namelist_name\n" */ /* "&namelist_name\n" */
len = dtp->namelist_name_len; len = dtp->namelist_name_len;
...@@ -2015,7 +2054,6 @@ nml_query (st_parameter_dt *dtp, char c) ...@@ -2015,7 +2054,6 @@ nml_query (st_parameter_dt *dtp, char c)
#endif #endif
for (nl = dtp->u.p.ionml; nl; nl = nl->next) for (nl = dtp->u.p.ionml; nl; nl = nl->next)
{ {
/* " var_name\n" */ /* " var_name\n" */
len = strlen (nl->var_name); len = strlen (nl->var_name);
...@@ -2081,7 +2119,6 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info * nl, index_type offset, ...@@ -2081,7 +2119,6 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info * nl, index_type offset,
namelist_info **pprev_nl, char *nml_err_msg, namelist_info **pprev_nl, char *nml_err_msg,
index_type clow, index_type chigh) index_type clow, index_type chigh)
{ {
namelist_info * cmp; namelist_info * cmp;
char * obj_name; char * obj_name;
int nml_carry; int nml_carry;
...@@ -2103,7 +2140,6 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info * nl, index_type offset, ...@@ -2103,7 +2140,6 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info * nl, index_type offset,
len = nl->len; len = nl->len;
switch (nl->type) switch (nl->type)
{ {
case GFC_DTYPE_INTEGER: case GFC_DTYPE_INTEGER:
case GFC_DTYPE_LOGICAL: case GFC_DTYPE_LOGICAL:
dlen = len; dlen = len;
...@@ -2127,7 +2163,6 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info * nl, index_type offset, ...@@ -2127,7 +2163,6 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info * nl, index_type offset,
do do
{ {
/* Update the pointer to the data, using the current index vector */ /* Update the pointer to the data, using the current index vector */
pdata = (void*)(nl->mem_pos + offset); pdata = (void*)(nl->mem_pos + offset);
...@@ -2333,10 +2368,11 @@ nml_get_obj_data (st_parameter_dt *dtp, namelist_info **pprev_nl, ...@@ -2333,10 +2368,11 @@ nml_get_obj_data (st_parameter_dt *dtp, namelist_info **pprev_nl,
namelist_info * nl; namelist_info * nl;
namelist_info * first_nl = NULL; namelist_info * first_nl = NULL;
namelist_info * root_nl = NULL; namelist_info * root_nl = NULL;
int dim; int dim, parsed_rank;
int component_flag; int component_flag;
char parse_err_msg[30]; char parse_err_msg[30];
index_type clow, chigh; index_type clow, chigh;
int non_zero_rank_count;
/* Look for end of input or object name. If '?' or '=?' are encountered /* Look for end of input or object name. If '?' or '=?' are encountered
in stdin, print the node names or the namelist to stdout. */ in stdin, print the node names or the namelist to stdout. */
...@@ -2388,6 +2424,7 @@ nml_get_obj_data (st_parameter_dt *dtp, namelist_info **pprev_nl, ...@@ -2388,6 +2424,7 @@ nml_get_obj_data (st_parameter_dt *dtp, namelist_info **pprev_nl,
nml_untouch_nodes (dtp); nml_untouch_nodes (dtp);
component_flag = 0; component_flag = 0;
non_zero_rank_count = 0;
/* Get the object name - should '!' and '\n' be permitted separators? */ /* Get the object name - should '!' and '\n' be permitted separators? */
...@@ -2456,16 +2493,23 @@ get_name: ...@@ -2456,16 +2493,23 @@ get_name:
if (c == '(' && nl->var_rank) if (c == '(' && nl->var_rank)
{ {
parsed_rank = 0;
if (nml_parse_qualifier (dtp, nl->dim, nl->ls, nl->var_rank, if (nml_parse_qualifier (dtp, nl->dim, nl->ls, nl->var_rank,
parse_err_msg) == FAILURE) parse_err_msg, &parsed_rank) == FAILURE)
{ {
sprintf (nml_err_msg, "%s for namelist variable %s", sprintf (nml_err_msg, "%s for namelist variable %s",
parse_err_msg, nl->var_name); parse_err_msg, nl->var_name);
goto nml_err_ret; goto nml_err_ret;
} }
if (parsed_rank > 0)
non_zero_rank_count++;
c = next_char (dtp); c = next_char (dtp);
unget_char (dtp, c); unget_char (dtp, c);
} }
else if (nl->var_rank > 0)
non_zero_rank_count++;
/* Now parse a derived type component. The root namelist_info address /* Now parse a derived type component. The root namelist_info address
is backed up, as is the previous component level. The component flag is backed up, as is the previous component level. The component flag
...@@ -2473,7 +2517,6 @@ get_name: ...@@ -2473,7 +2517,6 @@ get_name:
if (c == '%') if (c == '%')
{ {
if (nl->type != GFC_DTYPE_DERIVED) if (nl->type != GFC_DTYPE_DERIVED)
{ {
sprintf (nml_err_msg, "Attempt to get derived component for %s", sprintf (nml_err_msg, "Attempt to get derived component for %s",
...@@ -2488,7 +2531,6 @@ get_name: ...@@ -2488,7 +2531,6 @@ get_name:
component_flag = 1; component_flag = 1;
c = next_char (dtp); c = next_char (dtp);
goto get_name; goto get_name;
} }
/* Parse a character qualifier, if present. chigh = 0 is a default /* Parse a character qualifier, if present. chigh = 0 is a default
...@@ -2502,7 +2544,8 @@ get_name: ...@@ -2502,7 +2544,8 @@ get_name:
descriptor_dimension chd[1] = { {1, clow, nl->string_length} }; descriptor_dimension chd[1] = { {1, clow, nl->string_length} };
array_loop_spec ind[1] = { {1, clow, nl->string_length, 1} }; array_loop_spec ind[1] = { {1, clow, nl->string_length, 1} };
if (nml_parse_qualifier (dtp, chd, ind, 1, parse_err_msg) == FAILURE) if (nml_parse_qualifier (dtp, chd, ind, -1, parse_err_msg, &parsed_rank)
== FAILURE)
{ {
sprintf (nml_err_msg, "%s for namelist variable %s", sprintf (nml_err_msg, "%s for namelist variable %s",
parse_err_msg, nl->var_name); parse_err_msg, nl->var_name);
...@@ -2515,8 +2558,8 @@ get_name: ...@@ -2515,8 +2558,8 @@ get_name:
if (ind[0].step != 1) if (ind[0].step != 1)
{ {
sprintf (nml_err_msg, sprintf (nml_err_msg,
"Bad step in substring for namelist object %s", "Step not allowed in substring qualifier"
nl->var_name); " for namelist object %s", nl->var_name);
goto nml_err_ret; goto nml_err_ret;
} }
...@@ -2533,7 +2576,7 @@ get_name: ...@@ -2533,7 +2576,7 @@ get_name:
if (component_flag) if (component_flag)
nl = first_nl; nl = first_nl;
/*make sure no extraneous qualifiers are there.*/ /* Make sure no extraneous qualifiers are there. */
if (c == '(') if (c == '(')
{ {
...@@ -2542,6 +2585,15 @@ get_name: ...@@ -2542,6 +2585,15 @@ get_name:
goto nml_err_ret; goto nml_err_ret;
} }
/* Make sure there is no more than one non-zero rank object. */
if (non_zero_rank_count > 1)
{
sprintf (nml_err_msg, "Multiple sub-objects with non-zero rank in"
" namelist object %s", nl->var_name);
non_zero_rank_count = 0;
goto nml_err_ret;
}
/* According to the standard, an equal sign MUST follow an object name. The /* According to the standard, an equal sign MUST follow an object name. The
following is possibly lax - it allows comments, blank lines and so on to following is possibly lax - it allows comments, blank lines and so on to
intervene. eat_spaces (dtp); c = next_char (dtp); would be compliant*/ intervene. eat_spaces (dtp); c = next_char (dtp); would be compliant*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment