diff options
author | Alan Modra <amodra@gmail.com> | 2015-07-22 21:58:50 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2015-07-22 22:04:28 +0930 |
commit | 511b1657d2b251e529a7a0634325bb7d8f3af80d (patch) | |
tree | 85f87f4c5a71ab622a62b7e61bebc6d8d0b6c720 /gas | |
parent | 5b2af7dd40a4f3b570aef71daf11b9dfce9a5d13 (diff) | |
download | binutils-511b1657d2b251e529a7a0634325bb7d8f3af80d.zip binutils-511b1657d2b251e529a7a0634325bb7d8f3af80d.tar.gz binutils-511b1657d2b251e529a7a0634325bb7d8f3af80d.tar.bz2 |
gas line buffer handling
This fixes a segfault when macro definitions end on the last line of a
file, and that line isn't properly terminated with a newline. gas
used to throw away the last line in cases like this, whereas in other
cases gas added the missing newline. So I've also made gas
consistently provide a missing newline.
PR gas/18687
* input-scrub.c (input_scrub_next_buffer): Rearrange and simplify
loop. Don't drop lines at end of file lacking a newline, add a
newline instead. Ensure partial_size is zero whenever
partial_where is NULL. Adjust buffer size for extra char.
(input_scrub_push, input_scrub_begin): Adjust buffer size here too.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 9 | ||||
-rw-r--r-- | gas/input-scrub.c | 100 |
2 files changed, 54 insertions, 55 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 5ea9714..a3268cb 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,12 @@ +2015-07-22 Alan Modra <amodra@gmail.com> + + PR gas/18687 + * input-scrub.c (input_scrub_next_buffer): Rearrange and simplify + loop. Don't drop lines at end of file lacking a newline, add a + newline instead. Ensure partial_size is zero whenever + partial_where is NULL. Adjust buffer size for extra char. + (input_scrub_push, input_scrub_begin): Adjust buffer size here too. + 2015-07-20 Matthew Wahab <matthew.wahab@arm.com> * NEWS: Mention corrected spelling of armv6kz. diff --git a/gas/input-scrub.c b/gas/input-scrub.c index b94f4e4..c8e1e29 100644 --- a/gas/input-scrub.c +++ b/gas/input-scrub.c @@ -164,7 +164,7 @@ input_scrub_push (char *saved_position) sb_index = -1; buffer_start = (char *) xmalloc ((BEFORE_SIZE + buffer_length - + buffer_length + AFTER_SIZE)); + + buffer_length + AFTER_SIZE + 1)); memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE); return saved; @@ -209,7 +209,7 @@ input_scrub_begin (void) buffer_length = input_file_buffer_size (); buffer_start = (char *) xmalloc ((BEFORE_SIZE + buffer_length - + buffer_length + AFTER_SIZE)); + + buffer_length + AFTER_SIZE + 1)); memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE); /* Line number things. */ @@ -329,6 +329,7 @@ input_scrub_next_buffer (char **bufp) } --macro_nest; partial_where = NULL; + partial_size = 0; if (next_saved_file != NULL) *bufp = input_scrub_pop (next_saved_file); return partial_where; @@ -341,79 +342,68 @@ input_scrub_next_buffer (char **bufp) return partial_where; } - *bufp = buffer_start + BEFORE_SIZE; - if (partial_size) { memmove (buffer_start + BEFORE_SIZE, partial_where, (unsigned int) partial_size); memcpy (buffer_start + BEFORE_SIZE, save_source, AFTER_SIZE); } - limit = input_file_give_next_buffer (buffer_start - + BEFORE_SIZE - + partial_size); - if (limit) + + while (1) { - char *p; /* Find last newline. */ - /* Terminate the buffer to avoid confusing TC_EOL_IN_INSN. */ - *limit = '\0'; - for (p = limit - 1; *p != '\n' || TC_EOL_IN_INSN (p); --p) - ; - ++p; - - while (p <= buffer_start + BEFORE_SIZE) + char *p; + + *bufp = buffer_start + BEFORE_SIZE; + limit = input_file_give_next_buffer (buffer_start + + BEFORE_SIZE + + partial_size); + if (!limit) { - int limoff; - - limoff = limit - buffer_start; - buffer_length += input_file_buffer_size (); - buffer_start = (char *) xrealloc (buffer_start, - (BEFORE_SIZE - + 2 * buffer_length - + AFTER_SIZE)); - *bufp = buffer_start + BEFORE_SIZE; - limit = input_file_give_next_buffer (buffer_start + limoff); - - if (limit == NULL) - { - as_warn (_("partial line at end of file ignored")); - partial_where = NULL; - if (next_saved_file) - *bufp = input_scrub_pop (next_saved_file); - return NULL; - } + if (partial_size == 0) + break; + as_warn (_("end of file not at end of a line; newline inserted")); + p = buffer_start + BEFORE_SIZE + partial_size; + *p++ = '\n'; + limit = p; + } + else + { /* Terminate the buffer to avoid confusing TC_EOL_IN_INSN. */ *limit = '\0'; + + /* Find last newline. */ for (p = limit - 1; *p != '\n' || TC_EOL_IN_INSN (p); --p) ; ++p; } - partial_where = p; - partial_size = limit - p; - memcpy (save_source, partial_where, (int) AFTER_SIZE); - memcpy (partial_where, AFTER_STRING, (int) AFTER_SIZE); - } - else - { - partial_where = 0; - if (partial_size > 0) + if (p != buffer_start + BEFORE_SIZE) { - as_warn (_("partial line at end of file ignored")); + partial_where = p; + partial_size = limit - p; + memcpy (save_source, partial_where, (int) AFTER_SIZE); + memcpy (partial_where, AFTER_STRING, (int) AFTER_SIZE); + return partial_where; } - /* Tell the listing we've finished the file. */ - LISTING_EOF (); - - /* If we should pop to another file at EOF, do it. */ - if (next_saved_file) - { - *bufp = input_scrub_pop (next_saved_file); /* Pop state */ - /* partial_where is now correct to return, since we popped it. */ - } + partial_size = limit - (buffer_start + BEFORE_SIZE); + buffer_length += input_file_buffer_size (); + buffer_start = (char *) xrealloc (buffer_start, + (BEFORE_SIZE + + 2 * buffer_length + + AFTER_SIZE + 1)); } - return (partial_where); + + /* Tell the listing we've finished the file. */ + LISTING_EOF (); + + /* If we should pop to another file at EOF, do it. */ + partial_where = NULL; + if (next_saved_file) + *bufp = input_scrub_pop (next_saved_file); + + return partial_where; } /* The remaining part of this file deals with line numbers, error |