From ce4f0e982b40763798b268d24947a61cac625d39 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 30 Oct 2004 06:54:19 +0000 Subject: Hiroshi Ito found some bugs. The 'c' command (cut and paste) was hardwired to not put a newline at the end (which was backwards, it should have been hardwired _to_ put a newline at the end, whether or not the input line ended with a newline). Test case for that: echo | sed -e '$ctest' And then this would segfault: echo | sed -e 'g' Because pattern_space got freed but the dead pointer was only overwritten in an if statement that didn't trigger if the hold space was empty. Oops. While debugging it, I found out that the hold space is persistent between multiple input files, so I promoted it to a global and added it to the memory cleanup. The relevant test case (to compare with That Other Sed) is: echo -n woo > woo sed -e h -e g woo echo "fish" | sed -e '/woo/h' -e "izap" -e 's/woo/thingy/' -e '/fish/g' woo - And somebody gratuitously stuck in a c99 int8_t type for something that's just a flag, so I grouped the darn ints. --- editors/sed.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'editors/sed.c') diff --git a/editors/sed.c b/editors/sed.c index 3d6871621..ae8d9832e 100644 --- a/editors/sed.c +++ b/editors/sed.c @@ -112,9 +112,9 @@ typedef struct sed_cmd_s { /* globals */ /* options */ -static int be_quiet = 0, in_place=0, regex_type=0; +static int be_quiet, in_place, regex_type; FILE *nonstdout; -char *outname; +char *outname,*hold_space; static const char bad_format_in_subst[] = @@ -122,7 +122,7 @@ static const char bad_format_in_subst[] = const char *const semicolon_whitespace = "; \n\r\t\v"; regmatch_t regmatch[10]; -static regex_t *previous_regex_ptr = NULL; +static regex_t *previous_regex_ptr; /* linked list of sed commands */ static sed_cmd_t sed_cmd_head; @@ -169,6 +169,8 @@ static void free_and_close_stuff(void) free(sed_cmd); sed_cmd = sed_cmd_next; } + + if(hold_space) free(hold_space); } #endif @@ -757,7 +759,7 @@ static int puts_maybe_newline(char *s, FILE *file, int missing_newline, int no_n static void process_file(FILE *file) { - char *pattern_space, *next_line, *hold_space=NULL; + char *pattern_space, *next_line; static int linenum = 0, missing_newline=0; int no_newline,next_no_newline=0; @@ -908,7 +910,7 @@ restart: /* Cut and paste text (replace) */ case 'c': /* Only triggers on last line of a matching range. */ - if (!sed_cmd->in_match) sed_puts(sed_cmd->string,1); + if (!sed_cmd->in_match) sed_puts(sed_cmd->string,0); goto discard_line; /* Read file, append contents to output */ @@ -1007,10 +1009,7 @@ restart: } case 'g': /* Replace pattern space with hold space */ free(pattern_space); - if (hold_space) { - pattern_space = strdup(hold_space); - no_newline=0; - } + pattern_space = strdup(hold_space ? hold_space : ""); break; case 'G': /* Append newline and hold space to pattern space */ { @@ -1096,9 +1095,7 @@ static void add_cmd_block(char *cmdstr) extern int sed_main(int argc, char **argv) { - int status = EXIT_SUCCESS; - int opt; - uint8_t getpat = 1; + int status = EXIT_SUCCESS, opt, getpat = 1; #ifdef CONFIG_FEATURE_CLEAN_UP /* destroy command strings on exit */ -- cgit v1.2.3