diff options
author | Paolo Bonzini <bonzini@gnu.org> | 2006-07-20 16:05:46 +0000 |
---|---|---|
committer | Paolo Bonzini <bonzini@gnu.org> | 2008-01-09 16:12:09 +0100 |
commit | 4ca34ac568881f50c9d5ecd2750938396686cf25 (patch) | |
tree | 5fcff6244b4e1eee45b8d46b5a5b2da87ac00f39 /sed | |
parent | ec9561cfa498794621c415005c196abd736f7587 (diff) | |
download | sed-4ca34ac568881f50c9d5ecd2750938396686cf25.tar.gz |
don't rely on malloc(0) != NULL
git-archimport-id: bonzini@gnu.org--2004b/sed--stable--4.1--patch-69
Diffstat (limited to 'sed')
-rw-r--r-- | sed/execute.c | 139 |
1 files changed, 101 insertions, 38 deletions
diff --git a/sed/execute.c b/sed/execute.c index 5e8a38a..ab2cc5c 100644 --- a/sed/execute.c +++ b/sed/execute.c @@ -84,6 +84,12 @@ struct line { #endif }; +#ifdef HAVE_MBRTOWC +#define SIZEOF_LINE (sizeof (struct line) - sizeof (mbstate_t)) +#else +#define SIZEOF_LINE (sizeof (struct line)) +#endif + /* A queue of text to write out at the end of a cycle (filled by the "a", "r" and "R" commands.) */ struct append_queue { @@ -366,11 +372,13 @@ str_append_modified(to, string, length, type) #endif } -/* initialize a "struct line" buffer */ -static void line_init P_((struct line *, size_t initial_size)); +/* Initialize a "struct line" buffer. Copy multibyte state from `state' + if not null. */ +static void line_init P_((struct line *, struct line *, size_t initial_size)); static void -line_init(buf, initial_size) +line_init(buf, state, initial_size) struct line *buf; + struct line *state; size_t initial_size; { buf->text = MALLOC(initial_size, char); @@ -380,18 +388,43 @@ line_init(buf, initial_size) buf->chomped = true; #ifdef HAVE_MBRTOWC - memset (&buf->mbstate, 0, sizeof (buf->mbstate)); + if (state) + memcpy (&buf->mbstate, &state->mbstate, sizeof (buf->mbstate)); + else + memset (&buf->mbstate, 0, sizeof (buf->mbstate)); #endif +} +/* Reset a "struct line" buffer to length zero. Copy multibyte state from + `state' if not null. */ +static void line_reset P_((struct line *, struct line *)); +static void +line_reset(buf, state) + struct line *buf, *state; +{ + if (buf->alloc == 0) + line_init(buf, state, INITIAL_BUFFER_SIZE); + else + { + buf->length = 0; +#ifdef HAVE_MBRTOWC + if (state) + memcpy (&buf->mbstate, &state->mbstate, sizeof (buf->mbstate)); + else + memset (&buf->mbstate, 0, sizeof (buf->mbstate)); +#endif + } } /* Copy the contents of the line `from' into the line `to'. - This destroys the old contents of `to'. */ -static void line_copy P_((struct line *from, struct line *to)); + This destroys the old contents of `to'. + Copy the multibyte state if `state' is true. */ +static void line_copy P_((struct line *from, struct line *to, bool state)); static void -line_copy(from, to) +line_copy(from, to, state) struct line *from; struct line *to; + bool state; { /* Remove the inactive portion in the destination buffer. */ to->alloc += to->active - to->text; @@ -415,38 +448,53 @@ line_copy(from, to) MEMCPY(to->active, from->active, from->length); #ifdef HAVE_MBRTOWC - MEMCPY(&to->mbstate, &from->mbstate, sizeof (from->mbstate)); + if (state) + MEMCPY(&to->mbstate, &from->mbstate, sizeof (from->mbstate)); #endif } -/* Append the contents of the line `from' to the line `to'. */ -static void line_append P_((struct line *from, struct line *to)); +/* Append the contents of the line `from' to the line `to'. + Copy the multibyte state if `state' is true. */ +static void line_append P_((struct line *from, struct line *to, bool state)); static void -line_append(from, to) +line_append(from, to, state) struct line *from; struct line *to; + bool state; { str_append(to, "\n", 1); str_append(to, from->active, from->length); to->chomped = from->chomped; #ifdef HAVE_MBRTOWC - MEMCPY (&to->mbstate, &from->mbstate, sizeof (from->mbstate)); + if (state) + MEMCPY (&to->mbstate, &from->mbstate, sizeof (from->mbstate)); #endif } -/* Exchange the contents of two "struct line" buffers. */ -static void line_exchange P_((struct line *, struct line *)); +/* Exchange two "struct line" buffers. + Copy the multibyte state if `state' is true. */ +static void line_exchange P_((struct line *a, struct line *b, bool state)); static void -line_exchange(a, b) +line_exchange(a, b, state) struct line *a; struct line *b; + bool state; { struct line t; - MEMCPY(&t, a, sizeof(struct line)); - MEMCPY( a, b, sizeof(struct line)); - MEMCPY( b, &t, sizeof(struct line)); + if (state) + { + MEMCPY(&t, a, sizeof (struct line)); + MEMCPY( a, b, sizeof (struct line)); + MEMCPY( b, &t, sizeof (struct line)); + } + else + { + MEMCPY(&t, a, SIZEOF_LINE); + MEMCPY( a, b, SIZEOF_LINE); + MEMCPY( b, &t, SIZEOF_LINE); + } } @@ -1072,9 +1120,7 @@ do_subst(sub) static struct re_registers regs; - if (s_accum.alloc == 0) - line_init(&s_accum, INITIAL_BUFFER_SIZE); - s_accum.length = 0; + line_reset(&s_accum, &line); /* The first part of the loop optimizes s/xxx// when xxx is at the start, and s/xxx$// */ @@ -1166,8 +1212,8 @@ do_subst(sub) /* Exchange line and s_accum. This can be much cheaper than copying s_accum.active into line.text (for huge lines). */ - line_exchange(&line, &s_accum); - + line_exchange(&line, &s_accum, false); + /* Finish up. */ if (count < sub->numb) return; @@ -1180,7 +1226,7 @@ do_subst(sub) { #ifdef HAVE_POPEN FILE *pipe; - s_accum.length = 0; + line_reset(&s_accum, NULL); str_append (&line, "", 1); pipe = popen(line.active, "r"); @@ -1197,7 +1243,10 @@ do_subst(sub) pclose (pipe); - line_exchange(&line, &s_accum); + /* Exchange line and s_accum. This can be much cheaper than copying + s_accum.active into line.text (for huge lines). See comment above + for 'g' as to while the third argument is incorrect anyway. */ + line_exchange(&line, &s_accum, true); if (line.length && line.active[line.length - 1] == '\n') line.length--; @@ -1337,9 +1386,7 @@ execute_program(vec, input) #ifdef HAVE_POPEN FILE *pipe; int cmd_length = cur_cmd->x.cmd_txt.text_length; - if (s_accum.alloc == 0) - line_init(&s_accum, INITIAL_BUFFER_SIZE); - s_accum.length = 0; + line_reset(&s_accum, NULL); if (!cmd_length) { @@ -1376,8 +1423,9 @@ execute_program(vec, input) /* Exchange line and s_accum. This can be much cheaper than copying s_accum.active into line.text - (for huge lines). */ - line_exchange(&line, &s_accum); + (for huge lines). See comment above for 'g' as + to while the third argument is incorrect anyway. */ + line_exchange(&line, &s_accum, true); } else flush_output(output_file.fp); @@ -1392,19 +1440,33 @@ execute_program(vec, input) } case 'g': - line_copy(&hold, &line); + /* We do not have a really good choice for the third parameter. + The problem is that hold space and the input file might as + well have different states; copying it from hold space means + that subsequent input might be read incorrectly, while + keeping it as in pattern space means that commands operating + on the moved buffer might consider a wrong character set. + We keep it true because it's what sed <= 4.1.5 did. */ + line_copy(&hold, &line, true); break; case 'G': - line_append(&hold, &line); + /* We do not have a really good choice for the third parameter. + The problem is that hold space and pattern space might as + well have different states. So, true is as wrong as false. + We keep it true because it's what sed <= 4.1.5 did, but + we could consider having line_ap. */ + line_append(&hold, &line, true); break; case 'h': - line_copy(&line, &hold); + /* Here, it is ok to have true. */ + line_copy(&line, &hold, true); break; case 'H': - line_append(&line, &hold); + /* See comment above for 'G' regarding the third parameter. */ + line_append(&line, &hold, true); break; case 'i': @@ -1535,7 +1597,8 @@ execute_program(vec, input) break; case 'x': - line_exchange(&line, &hold); + /* See comment above for 'g' regarding the third parameter. */ + line_exchange(&line, &hold, false); break; case 'y': @@ -1700,9 +1763,9 @@ process_files(the_program, argv) struct input input; int status; - line_init(&line, INITIAL_BUFFER_SIZE); - line_init(&hold, 0); - line_init(&buffer, 0); + line_init(&line, NULL, INITIAL_BUFFER_SIZE); + line_init(&hold, NULL, 0); + line_init(&buffer, NULL, 0); #ifdef EXPERIMENTAL_DASH_N_OPTIMIZATION branches = count_branches(the_program); |