mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-20 01:33:03 +00:00
* src/location.h (boundary): Note that a line or column equal
to INT_MAX indicates an overflow.
* src/scan-gram.l: Include verify.h. Don't include get-errno.h.
(rule_length_overflow, increment_rule_length, add_column_width):
New functions.
(<INITIAL>{id}, <SC_ESCAPED_STRING>"\"", <SC_ESCAPED_CHARACTER>"'"):
(<SC_BRACED_CODE>"}"):
Use increment_rule_length rather than incrementing it by hand.
(adjust_location, handle_syncline): Diagnose overflow.
(handle_action_dollar, handle_action_at):
Fix bug with monstrosities like $-2147483648.
Remove now-unnecessary checks.
(scan_integer): Verify assumptions and remove now-unnecessary checks.
(convert_ucn_to_byte): Verify assumptions.
(handle_syncline): New arg LOC. All callers changed.
Don't store through a value derived from char const * pointer.
This commit is contained in:
22
ChangeLog
22
ChangeLog
@@ -1,3 +1,25 @@
|
|||||||
|
2005-12-28 Paul Eggert <eggert@cs.ucla.edu>
|
||||||
|
|
||||||
|
* src/location.h (boundary): Note that a line or column equal
|
||||||
|
to INT_MAX indicates an overflow.
|
||||||
|
* src/scan-gram.l: Include verify.h. Don't include get-errno.h.
|
||||||
|
(rule_length_overflow, increment_rule_length, add_column_width):
|
||||||
|
New functions.
|
||||||
|
(<INITIAL>{id}, <SC_ESCAPED_STRING>"\"", <SC_ESCAPED_CHARACTER>"'"):
|
||||||
|
(<SC_BRACED_CODE>"}"):
|
||||||
|
Use increment_rule_length rather than incrementing it by hand.
|
||||||
|
(adjust_location, handle_syncline): Diagnose overflow.
|
||||||
|
(handle_action_dollar, handle_action_at):
|
||||||
|
Fix bug with monstrosities like $-2147483648.
|
||||||
|
Remove now-unnecessary checks.
|
||||||
|
(scan_integer): Verify assumptions and remove now-unnecessary checks.
|
||||||
|
(convert_ucn_to_byte): Verify assumptions.
|
||||||
|
(handle_syncline): New arg LOC. All callers changed.
|
||||||
|
Don't store through a value derived from char const * pointer.
|
||||||
|
|
||||||
|
* src/reader.c (grammar_rule_check): Rewrite slightly to avoid
|
||||||
|
GCC warnings.
|
||||||
|
|
||||||
2005-12-27 Paul Eggert <eggert@cs.ucla.edu>
|
2005-12-27 Paul Eggert <eggert@cs.ucla.edu>
|
||||||
|
|
||||||
* src/reader.c (grammar_midrule_action, grammar_symbol_append):
|
* src/reader.c (grammar_midrule_action, grammar_symbol_append):
|
||||||
|
|||||||
@@ -29,11 +29,13 @@ typedef struct
|
|||||||
/* The name of the file that contains the boundary. */
|
/* The name of the file that contains the boundary. */
|
||||||
uniqstr file;
|
uniqstr file;
|
||||||
|
|
||||||
/* The (origin-1) line that contains the boundary. */
|
/* The (origin-1) line that contains the boundary.
|
||||||
|
If this is INT_MAX, the line number has overflowed. */
|
||||||
int line;
|
int line;
|
||||||
|
|
||||||
/* The (origin-1) column just after the boundary. This is neither a
|
/* The (origin-1) column just after the boundary. This is neither a
|
||||||
byte count, nor a character count; it is a column count. */
|
byte count, nor a character count; it is a column count.
|
||||||
|
If this is INT_MAX, the column number has overflowed. */
|
||||||
int column;
|
int column;
|
||||||
|
|
||||||
} boundary;
|
} boundary;
|
||||||
|
|||||||
129
src/scan-gram.l
129
src/scan-gram.l
@@ -32,7 +32,6 @@
|
|||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
#include <mbswidth.h>
|
#include <mbswidth.h>
|
||||||
#include <get-errno.h>
|
|
||||||
#include <quote.h>
|
#include <quote.h>
|
||||||
|
|
||||||
#include "complain.h"
|
#include "complain.h"
|
||||||
@@ -41,6 +40,7 @@
|
|||||||
#include "gram.h"
|
#include "gram.h"
|
||||||
#include "quotearg.h"
|
#include "quotearg.h"
|
||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
|
#include "verify.h"
|
||||||
#include "uniqstr.h"
|
#include "uniqstr.h"
|
||||||
|
|
||||||
#define YY_USER_INIT \
|
#define YY_USER_INIT \
|
||||||
@@ -117,9 +117,23 @@ scanner_last_string_free (void)
|
|||||||
Outside of well-formed rules, RULE_LENGTH has an undefined value. */
|
Outside of well-formed rules, RULE_LENGTH has an undefined value. */
|
||||||
static int rule_length;
|
static int rule_length;
|
||||||
|
|
||||||
|
static void rule_length_overflow (location) __attribute__ ((__noreturn__));
|
||||||
|
|
||||||
|
/* Increment the rule length by one, checking for overflow. */
|
||||||
|
static inline void
|
||||||
|
increment_rule_length (location loc)
|
||||||
|
{
|
||||||
|
rule_length++;
|
||||||
|
|
||||||
|
/* Don't allow rule_length == INT_MAX, since that might cause
|
||||||
|
confusion with strtol if INT_MAX == LONG_MAX. */
|
||||||
|
if (rule_length == INT_MAX)
|
||||||
|
rule_length_overflow (loc);
|
||||||
|
}
|
||||||
|
|
||||||
static void handle_dollar (int token_type, char *cp, location loc);
|
static void handle_dollar (int token_type, char *cp, location loc);
|
||||||
static void handle_at (int token_type, char *cp, location loc);
|
static void handle_at (int token_type, char *cp, location loc);
|
||||||
static void handle_syncline (char *args);
|
static void handle_syncline (char *, location);
|
||||||
static unsigned long int scan_integer (char const *p, int base, location loc);
|
static unsigned long int scan_integer (char const *p, int base, location loc);
|
||||||
static int convert_ucn_to_byte (char const *hex_text);
|
static int convert_ucn_to_byte (char const *hex_text);
|
||||||
static void unexpected_eof (boundary, char const *);
|
static void unexpected_eof (boundary, char const *);
|
||||||
@@ -190,7 +204,7 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
/* #line directives are not documented, and may be withdrawn or
|
/* #line directives are not documented, and may be withdrawn or
|
||||||
modified in future versions of Bison. */
|
modified in future versions of Bison. */
|
||||||
^"#line "{int}" \"".*"\"\n" {
|
^"#line "{int}" \"".*"\"\n" {
|
||||||
handle_syncline (yytext + sizeof "#line " - 1);
|
handle_syncline (yytext + sizeof "#line " - 1, *loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +266,7 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
{id} {
|
{id} {
|
||||||
val->symbol = symbol_get (yytext, *loc);
|
val->symbol = symbol_get (yytext, *loc);
|
||||||
id_loc = *loc;
|
id_loc = *loc;
|
||||||
rule_length++;
|
increment_rule_length (*loc);
|
||||||
BEGIN SC_AFTER_IDENTIFIER;
|
BEGIN SC_AFTER_IDENTIFIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +397,7 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
STRING_FINISH;
|
STRING_FINISH;
|
||||||
loc->start = token_start;
|
loc->start = token_start;
|
||||||
val->chars = last_string;
|
val->chars = last_string;
|
||||||
rule_length++;
|
increment_rule_length (*loc);
|
||||||
BEGIN INITIAL;
|
BEGIN INITIAL;
|
||||||
return STRING;
|
return STRING;
|
||||||
}
|
}
|
||||||
@@ -410,7 +424,7 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
last_string_1 = last_string[1];
|
last_string_1 = last_string[1];
|
||||||
symbol_user_token_number_set (val->symbol, last_string_1, *loc);
|
symbol_user_token_number_set (val->symbol, last_string_1, *loc);
|
||||||
STRING_FREE;
|
STRING_FREE;
|
||||||
rule_length++;
|
increment_rule_length (*loc);
|
||||||
BEGIN INITIAL;
|
BEGIN INITIAL;
|
||||||
return ID;
|
return ID;
|
||||||
}
|
}
|
||||||
@@ -431,7 +445,7 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
<SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>
|
<SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>
|
||||||
{
|
{
|
||||||
\\[0-7]{1,3} {
|
\\[0-7]{1,3} {
|
||||||
unsigned long int c = strtoul (yytext + 1, 0, 8);
|
unsigned long int c = strtoul (yytext + 1, NULL, 8);
|
||||||
if (UCHAR_MAX < c)
|
if (UCHAR_MAX < c)
|
||||||
complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
|
complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
|
||||||
else if (! c)
|
else if (! c)
|
||||||
@@ -441,10 +455,9 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
}
|
}
|
||||||
|
|
||||||
\\x[0-9abcdefABCDEF]+ {
|
\\x[0-9abcdefABCDEF]+ {
|
||||||
unsigned long int c;
|
verify (UCHAR_MAX < ULONG_MAX);
|
||||||
set_errno (0);
|
unsigned long int c = strtoul (yytext + 2, NULL, 16);
|
||||||
c = strtoul (yytext + 2, 0, 16);
|
if (UCHAR_MAX < c)
|
||||||
if (UCHAR_MAX < c || get_errno ())
|
|
||||||
complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
|
complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
|
||||||
else if (! c)
|
else if (! c)
|
||||||
complain_at (*loc, _("invalid null character: %s"), quote (yytext));
|
complain_at (*loc, _("invalid null character: %s"), quote (yytext));
|
||||||
@@ -603,9 +616,9 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
if (outer_brace)
|
if (outer_brace)
|
||||||
{
|
{
|
||||||
STRING_FINISH;
|
STRING_FINISH;
|
||||||
rule_length++;
|
|
||||||
loc->start = code_start;
|
loc->start = code_start;
|
||||||
val->chars = last_string;
|
val->chars = last_string;
|
||||||
|
increment_rule_length (*loc);
|
||||||
BEGIN INITIAL;
|
BEGIN INITIAL;
|
||||||
return token_type;
|
return token_type;
|
||||||
}
|
}
|
||||||
@@ -693,6 +706,29 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
semantic actions of this grammar. */
|
semantic actions of this grammar. */
|
||||||
int max_left_semantic_context = 0;
|
int max_left_semantic_context = 0;
|
||||||
|
|
||||||
|
/* If BUF is null, add BUFSIZE (which in this case must be less than
|
||||||
|
INT_MAX) to COLUMN; otherwise, add mbsnwidth (BUF, BUFSIZE, 0) to
|
||||||
|
COLUMN. If an overflow occurs, or might occur but is undetectable,
|
||||||
|
return INT_MAX. Assume COLUMN is nonnegative. */
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
add_column_width (int column, char const *buf, size_t bufsize)
|
||||||
|
{
|
||||||
|
size_t width;
|
||||||
|
unsigned int remaining_columns = INT_MAX - column;
|
||||||
|
|
||||||
|
if (buf)
|
||||||
|
{
|
||||||
|
if (INT_MAX / 2 <= bufsize)
|
||||||
|
return INT_MAX;
|
||||||
|
width = mbsnwidth (buf, bufsize, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
width = bufsize;
|
||||||
|
|
||||||
|
return width <= remaining_columns ? column + width : INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set *LOC and adjust scanner cursor to account for token TOKEN of
|
/* Set *LOC and adjust scanner cursor to account for token TOKEN of
|
||||||
size SIZE. */
|
size SIZE. */
|
||||||
|
|
||||||
@@ -711,22 +747,29 @@ adjust_location (location *loc, char const *token, size_t size)
|
|||||||
switch (*p)
|
switch (*p)
|
||||||
{
|
{
|
||||||
case '\n':
|
case '\n':
|
||||||
line++;
|
line += line < INT_MAX;
|
||||||
column = 1;
|
column = 1;
|
||||||
p0 = p + 1;
|
p0 = p + 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\t':
|
case '\t':
|
||||||
column += mbsnwidth (p0, p - p0, 0);
|
{
|
||||||
column += 8 - ((column - 1) & 7);
|
column = add_column_width (column, p0, p - p0);
|
||||||
p0 = p + 1;
|
column = add_column_width (column, NULL, 8 - ((column - 1) & 7));
|
||||||
break;
|
p0 = p + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scanner_cursor.line = line;
|
scanner_cursor.line = line;
|
||||||
scanner_cursor.column = column + mbsnwidth (p0, p - p0, 0);
|
scanner_cursor.column = column = add_column_width (column, p0, p - p0);
|
||||||
|
|
||||||
loc->end = scanner_cursor;
|
loc->end = scanner_cursor;
|
||||||
|
|
||||||
|
if (line == INT_MAX && loc->start.line != INT_MAX)
|
||||||
|
warn_at (*loc, _("line number overflow"));
|
||||||
|
if (column == INT_MAX && loc->start.column != INT_MAX)
|
||||||
|
warn_at (*loc, _("column number overflow"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -819,11 +862,9 @@ handle_action_dollar (char *text, location loc)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
long int num;
|
long int num = strtol (cp, NULL, 10);
|
||||||
set_errno (0);
|
|
||||||
num = strtol (cp, 0, 10);
|
|
||||||
|
|
||||||
if (INT_MIN <= num && num <= rule_length && ! get_errno ())
|
if (1 - INT_MAX + rule_length <= num && num <= rule_length)
|
||||||
{
|
{
|
||||||
int n = num;
|
int n = num;
|
||||||
if (max_left_semantic_context < 1 - n)
|
if (max_left_semantic_context < 1 - n)
|
||||||
@@ -899,11 +940,9 @@ handle_action_at (char *text, location loc)
|
|||||||
obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
|
obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
long int num;
|
long int num = strtol (cp, NULL, 10);
|
||||||
set_errno (0);
|
|
||||||
num = strtol (cp, 0, 10);
|
|
||||||
|
|
||||||
if (INT_MIN <= num && num <= rule_length && ! get_errno ())
|
if (1 - INT_MAX + rule_length <= num && num <= rule_length)
|
||||||
{
|
{
|
||||||
int n = num;
|
int n = num;
|
||||||
obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
|
obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
|
||||||
@@ -956,14 +995,15 @@ handle_at (int token_type, char *text, location loc)
|
|||||||
static unsigned long int
|
static unsigned long int
|
||||||
scan_integer (char const *number, int base, location loc)
|
scan_integer (char const *number, int base, location loc)
|
||||||
{
|
{
|
||||||
unsigned long int num;
|
verify (INT_MAX < ULONG_MAX);
|
||||||
set_errno (0);
|
unsigned long int num = strtoul (number, NULL, base);
|
||||||
num = strtoul (number, 0, base);
|
|
||||||
if (INT_MAX < num || get_errno ())
|
if (INT_MAX < num)
|
||||||
{
|
{
|
||||||
complain_at (loc, _("integer out of range: %s"), quote (number));
|
complain_at (loc, _("integer out of range: %s"), quote (number));
|
||||||
num = INT_MAX;
|
num = INT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -977,7 +1017,8 @@ scan_integer (char const *number, int base, location loc)
|
|||||||
static int
|
static int
|
||||||
convert_ucn_to_byte (char const *ucn)
|
convert_ucn_to_byte (char const *ucn)
|
||||||
{
|
{
|
||||||
unsigned long int code = strtoul (ucn + 2, 0, 16);
|
verify (UCHAR_MAX <= INT_MAX);
|
||||||
|
unsigned long int code = strtoul (ucn + 2, NULL, 16);
|
||||||
|
|
||||||
/* FIXME: Currently we assume Unicode-compatible unibyte characters
|
/* FIXME: Currently we assume Unicode-compatible unibyte characters
|
||||||
on ASCII hosts (i.e., Latin-1 on hosts with 8-bit bytes). On
|
on ASCII hosts (i.e., Latin-1 on hosts with 8-bit bytes). On
|
||||||
@@ -1029,18 +1070,34 @@ convert_ucn_to_byte (char const *ucn)
|
|||||||
`----------------------------------------------------------------*/
|
`----------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_syncline (char *args)
|
handle_syncline (char *args, location loc)
|
||||||
{
|
{
|
||||||
int lineno = strtol (args, &args, 10);
|
char *after_num;
|
||||||
const char *file = NULL;
|
unsigned long int lineno = strtoul (args, &after_num, 10);
|
||||||
file = strchr (args, '"') + 1;
|
char *file = strchr (after_num, '"') + 1;
|
||||||
*strchr (file, '"') = 0;
|
*strchr (file, '"') = '\0';
|
||||||
|
if (INT_MAX <= lineno)
|
||||||
|
{
|
||||||
|
warn_at (loc, _("line number overflow"));
|
||||||
|
lineno = INT_MAX;
|
||||||
|
}
|
||||||
scanner_cursor.file = current_file = uniqstr_new (file);
|
scanner_cursor.file = current_file = uniqstr_new (file);
|
||||||
scanner_cursor.line = lineno;
|
scanner_cursor.line = lineno;
|
||||||
scanner_cursor.column = 1;
|
scanner_cursor.column = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------.
|
||||||
|
| Report a rule that is too long. |
|
||||||
|
`---------------------------------*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
rule_length_overflow (location loc)
|
||||||
|
{
|
||||||
|
fatal_at (loc, _("rule is too long"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------.
|
/*----------------------------------------------------------------.
|
||||||
| For a token or comment starting at START, report message MSGID, |
|
| For a token or comment starting at START, report message MSGID, |
|
||||||
| which should say that an end marker was found before |
|
| which should say that an end marker was found before |
|
||||||
|
|||||||
Reference in New Issue
Block a user