aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2004-10-30 06:54:19 +0000
committerRob Landley <rob@landley.net>2004-10-30 06:54:19 +0000
commitce4f0e982b40763798b268d24947a61cac625d39 (patch)
treed7e680e89e0d6fb9843cb00552d8520de6fcf5e0
parent332c4728656a72ddd116f031b654994863275c9d (diff)
downloadbusybox-w32-ce4f0e982b40763798b268d24947a61cac625d39.tar.gz
busybox-w32-ce4f0e982b40763798b268d24947a61cac625d39.tar.bz2
busybox-w32-ce4f0e982b40763798b268d24947a61cac625d39.zip
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.
-rw-r--r--editors/sed.c21
1 files changed, 9 insertions, 12 deletions
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 {
112 112
113/* globals */ 113/* globals */
114/* options */ 114/* options */
115static int be_quiet = 0, in_place=0, regex_type=0; 115static int be_quiet, in_place, regex_type;
116FILE *nonstdout; 116FILE *nonstdout;
117char *outname; 117char *outname,*hold_space;
118 118
119 119
120static const char bad_format_in_subst[] = 120static const char bad_format_in_subst[] =
@@ -122,7 +122,7 @@ static const char bad_format_in_subst[] =
122const char *const semicolon_whitespace = "; \n\r\t\v"; 122const char *const semicolon_whitespace = "; \n\r\t\v";
123 123
124regmatch_t regmatch[10]; 124regmatch_t regmatch[10];
125static regex_t *previous_regex_ptr = NULL; 125static regex_t *previous_regex_ptr;
126 126
127/* linked list of sed commands */ 127/* linked list of sed commands */
128static sed_cmd_t sed_cmd_head; 128static sed_cmd_t sed_cmd_head;
@@ -169,6 +169,8 @@ static void free_and_close_stuff(void)
169 free(sed_cmd); 169 free(sed_cmd);
170 sed_cmd = sed_cmd_next; 170 sed_cmd = sed_cmd_next;
171 } 171 }
172
173 if(hold_space) free(hold_space);
172} 174}
173#endif 175#endif
174 176
@@ -757,7 +759,7 @@ static int puts_maybe_newline(char *s, FILE *file, int missing_newline, int no_n
757 759
758static void process_file(FILE *file) 760static void process_file(FILE *file)
759{ 761{
760 char *pattern_space, *next_line, *hold_space=NULL; 762 char *pattern_space, *next_line;
761 static int linenum = 0, missing_newline=0; 763 static int linenum = 0, missing_newline=0;
762 int no_newline,next_no_newline=0; 764 int no_newline,next_no_newline=0;
763 765
@@ -908,7 +910,7 @@ restart:
908 /* Cut and paste text (replace) */ 910 /* Cut and paste text (replace) */
909 case 'c': 911 case 'c':
910 /* Only triggers on last line of a matching range. */ 912 /* Only triggers on last line of a matching range. */
911 if (!sed_cmd->in_match) sed_puts(sed_cmd->string,1); 913 if (!sed_cmd->in_match) sed_puts(sed_cmd->string,0);
912 goto discard_line; 914 goto discard_line;
913 915
914 /* Read file, append contents to output */ 916 /* Read file, append contents to output */
@@ -1007,10 +1009,7 @@ restart:
1007 } 1009 }
1008 case 'g': /* Replace pattern space with hold space */ 1010 case 'g': /* Replace pattern space with hold space */
1009 free(pattern_space); 1011 free(pattern_space);
1010 if (hold_space) { 1012 pattern_space = strdup(hold_space ? hold_space : "");
1011 pattern_space = strdup(hold_space);
1012 no_newline=0;
1013 }
1014 break; 1013 break;
1015 case 'G': /* Append newline and hold space to pattern space */ 1014 case 'G': /* Append newline and hold space to pattern space */
1016 { 1015 {
@@ -1096,9 +1095,7 @@ static void add_cmd_block(char *cmdstr)
1096 1095
1097extern int sed_main(int argc, char **argv) 1096extern int sed_main(int argc, char **argv)
1098{ 1097{
1099 int status = EXIT_SUCCESS; 1098 int status = EXIT_SUCCESS, opt, getpat = 1;
1100 int opt;
1101 uint8_t getpat = 1;
1102 1099
1103#ifdef CONFIG_FEATURE_CLEAN_UP 1100#ifdef CONFIG_FEATURE_CLEAN_UP
1104 /* destroy command strings on exit */ 1101 /* destroy command strings on exit */