You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Ba...@Sun.COM on 2008/06/29 06:08:50 UTC

Re: Solaris sed based apache filtering module (mod_sed)

mod_sed constant length buffer sizes fix :

Three buffers linebuf, genbuf and holdbuf are now reallocated dynamically.
Sed code has 3 buffers :
linebuf : Store a line.
holdbuf : store the intemediate hold data (sed h/H commands)
genbuf : Used in substitution intermediate results.

Original sed has the limitation on the fixed size buffers.
In this fix all these 3 buffers are adjusted dynamically. Initial buffer size
of these buffers is 1024 bytes. When these buffers needs reallocation, their
new buffer size is aligned to 4KB boundary.

List of affected files :
sed1.c libsed.h

Code has been updated and can be obtained by mercurial as :
$ hg clone ssh://anon@hg.opensolaris.org/hg/webstack/mod_sed

It should soon be visible at :
http://src.opensolaris.org/source/xref/webstack/mod_sed/

Diff is attached.

Regards,
Basant.


-------------------------------------------------------------
diff -r 32f5eb1dc14f libsed.h
--- a/libsed.h  Wed Apr 30 11:52:57 2008 -0700
+++ b/libsed.h  Sat Jun 28 20:35:06 2008 -0700
@@ -121,17 +121,14 @@
 
     unsigned       lsize;
     char           *linebuf;
-    char           *lbend;
     char           *lspend;
 
     unsigned       hsize;
     char           *holdbuf;
-    char           *hbend;
     char           *hspend;
 
     unsigned       gsize;
     char           *genbuf;
-    char           *gbend;
     char           *lcomend;
 
     apr_file_t    *fcode[NWFILES];
diff -r 32f5eb1dc14f sed1.c
--- a/sed1.c    Wed Apr 30 11:52:57 2008 -0700
+++ b/sed1.c    Sat Jun 28 20:35:06 2008 -0700
@@ -86,6 +86,151 @@
     }
 }
 
+#define INIT_BUF_SIZE 1024
+
+/*
+ * grow_buffer
+ */
+static void grow_buffer(apr_pool_t *pool, char **buffer,
+                        char **spend, unsigned int *cursize,
+                        unsigned int newsize)
+{
+    char* newbuffer = NULL;
+    int spendsize = 0;
+    if (*cursize >= newsize)
+        return;
+    /* Align it to 4 KB boundary */
+    newsize = (newsize  + ((1 << 12) - 1)) & ~((1 << 12) -1);
+    newbuffer = apr_pcalloc(pool, newsize);
+    if (*spend && *buffer && (*cursize > 0)) {
+        spendsize = *spend - *buffer;
+    }
+    if ((*cursize > 0) && *buffer) {
+        memcpy(newbuffer, *buffer, *cursize);
+    }
+    *buffer = newbuffer;
+    *cursize = newsize;
+    if (spend != buffer) {
+        *spend = *buffer + spendsize;
+    }
+}
+
+/*
+ * grow_line_buffer
+ */
+static void grow_line_buffer(sed_eval_t *eval, int newsize)
+{
+    grow_buffer(eval->pool, &eval->linebuf, &eval->lspend,
+                &eval->lsize, newsize);
+}
+
+/*
+ * grow_hold_buffer
+ */
+static void grow_hold_buffer(sed_eval_t *eval, int newsize)
+{
+    grow_buffer(eval->pool, &eval->holdbuf, &eval->hspend,
+                &eval->hsize, newsize);
+}
+
+/*
+ * grow_gen_buffer
+ */
+static void grow_gen_buffer(sed_eval_t *eval, int newsize,
+                            char **gspend)
+{
+    if (gspend == NULL) {
+        gspend = &eval->genbuf;
+    }
+    grow_buffer(eval->pool, &eval->genbuf, gspend,
+                &eval->gsize, newsize);
+    eval->lcomend = &eval->genbuf[71];
+}
+
+/*
+ * appendmem_to_linebuf
+ */
+static void appendmem_to_linebuf(sed_eval_t *eval, const char* sz, int len)
+{
+    int reqsize = (eval->lspend - eval->linebuf) + len;
+    if (eval->lsize < reqsize) {
+        grow_line_buffer(eval, reqsize);
+    }
+    memcpy(eval->lspend, sz, len);
+    eval->lspend += len;
+}
+
+/*
+ * append_to_linebuf
+ */
+static void append_to_linebuf(sed_eval_t *eval, const char* sz)
+{
+    int len = strlen(sz);
+    /* Copy string including null character */
+    appendmem_to_linebuf(eval, sz, len + 1);
+    --eval->lspend; /* lspend will now point to NULL character */
+}
+
+/*
+ * copy_to_linebuf
+ */
+static void copy_to_linebuf(sed_eval_t *eval, const char* sz)
+{
+    eval->lspend = eval->linebuf;
+    append_to_linebuf(eval, sz);
+}
+
+/*
+ * append_to_holdbuf
+ */
+static void append_to_holdbuf(sed_eval_t *eval, const char* sz)
+{
+    int len = strlen(sz);
+    int reqsize = (eval->hspend - eval->holdbuf) + len + 1;
+    if (eval->hsize <= reqsize) {
+        grow_hold_buffer(eval, reqsize);
+    }
+    strcpy(eval->hspend, sz);
+    /* hspend will now point to NULL character */
+    eval->hspend += len;
+}
+
+/*
+ * copy_to_holdbuf
+ */
+static void copy_to_holdbuf(sed_eval_t *eval, const char* sz)
+{
+    eval->hspend = eval->holdbuf;
+    append_to_holdbuf(eval, sz);
+}
+
+/*
+ * append_to_genbuf
+ */
+static void append_to_genbuf(sed_eval_t *eval, const char* sz, char **gspend)
+{
+    int len = strlen(sz);
+    int reqsize = (*gspend - eval->genbuf) + len + 1;
+    if (eval->gsize < reqsize) {
+        grow_gen_buffer(eval, reqsize, gspend);
+    }
+    strcpy(*gspend, sz);
+    /* *gspend will now point to NULL character */
+    *gspend += len;
+}
+
+/*
+ * copy_to_genbuf
+ */
+static void copy_to_genbuf(sed_eval_t *eval, const char* sz)
+{
+    int len = strlen(sz);
+    int reqsize = len + 1;
+    if (eval->gsize < reqsize) {
+        grow_gen_buffer(eval, reqsize, NULL);
+    }
+}
+
 /*
  * sed_init_eval
  */
@@ -113,16 +258,16 @@
     eval->fout = NULL;
 
     if (eval->linebuf == NULL) {
-        eval->linebuf = apr_palloc(eval->pool, LBSIZE + 1);
-        eval->lbend = eval->linebuf + LBSIZE;
+        eval->lsize = INIT_BUF_SIZE;
+        eval->linebuf = apr_pcalloc(eval->pool, eval->lsize);
     }
     if (eval->holdbuf == NULL) {
-        eval->holdbuf = apr_palloc(eval->pool, LBSIZE + 1);
-        eval->hbend = eval->holdbuf + LBSIZE;
+        eval->hsize = INIT_BUF_SIZE;
+        eval->holdbuf = apr_pcalloc(eval->pool, eval->hsize);
     }
     if (eval->genbuf == NULL) {
-        eval->genbuf = apr_palloc(eval->pool, LBSIZE + 1);
-        eval->gbend = eval->genbuf + LBSIZE;
+        eval->gsize = INIT_BUF_SIZE;
+        eval->genbuf = apr_pcalloc(eval->pool, eval->gsize);
     }
     eval->lspend = eval->linebuf;
     eval->hspend = eval->holdbuf;
@@ -243,18 +388,13 @@
             eval->lreadyflag = 1;
             break;
         }
-
-        while ((eval->linebuf + LBSIZE) <= eval->lspend + llen + 1) {
-            /* XXX : grow buffer */
-            return APR_EGENERAL;
-        }
-
-        memcpy(eval->lspend, buf, llen);
-        eval->lspend += llen;
+        
+        appendmem_to_linebuf(eval, buf, llen + 1);
+        --eval->lspend;
+        /* replace new line character with NULL */
+        *eval->lspend = '\0';
         buf += (llen + 1);
         bufsz -= (llen + 1);
-
-        *eval->lspend = '\0';
         rv = execute(eval);
         if (rv != 0)
             return APR_EGENERAL;
@@ -264,12 +404,7 @@
 
     /* Save the leftovers for later */
     if (bufsz) {
-        if ((eval->linebuf + LBSIZE) <= eval->lspend + bufsz) {
-            /* XXX : grow buffer */
-            return APR_EGENERAL;
-        }
-        memcpy(eval->lspend, buf, bufsz);
-        eval->lspend += bufsz;
+        appendmem_to_linebuf(eval, buf, bufsz);
     }
 
     return APR_SUCCESS;
@@ -296,10 +431,12 @@
             eval->lreadyflag = 0;
             eval->lspend--;
         } else {
-            if ((eval->linebuf + LBSIZE) <= eval->lspend) {
-                /* XXX : grow buffer */
-                return APR_EGENERAL;
-            }
+            /* Code can probably reach here when last character in output
+             * buffer is not null terminated 
+             */
+            /* Assure space for NULL */
+            append_to_linebuf(eval, "");
+            eval->lspend--;
         }
 
         *eval->lspend = '\0';
@@ -493,8 +630,7 @@
     lp = eval->linebuf;
     sp = eval->genbuf;
     rp = rhsbuf;
-    while (lp < step_vars->loc1)
-        *sp++ = *lp++;
+    sp = place(eval, sp, lp, step_vars->loc1);
     while(c = *rp++) {
         if (c == '&') {
             sp = place(eval, sp, step_vars->loc1, step_vars->loc2);
@@ -513,27 +649,15 @@
                 *sp++ = c;
           } else
             *sp++ = c;
-        if (sp == &eval->genbuf[LBSIZE+1]) {
-            eval_errf(eval, SEDERR_OLTL, eval->lnum);
-            *--sp = '\0';
-            rv = APR_EGENERAL;
-            goto out;
+        if (sp >= eval->genbuf + eval->gsize) {
+            /* expand genbuf and set the sp appropriately */
+            grow_gen_buffer(eval, eval->gsize + 1024, &sp);
         }
     }
     lp = step_vars->loc2;
     step_vars->loc2 = sp - eval->genbuf + eval->linebuf;
-    while(*sp++ = *lp++)
-        if (sp == &eval->genbuf[LBSIZE+1]) {
-            eval_errf(eval, SEDERR_OLTL, eval->lnum);
-            *--sp = '\0';
-            rv = APR_EGENERAL;
-            break;
-        }
-out:
-    lp = eval->linebuf;
-    sp = eval->genbuf;
-    while (*lp++ = *sp++);
-    eval->lspend = lp-1;
+    append_to_genbuf(eval, lp, &sp);
+    copy_to_linebuf(eval, eval->genbuf);
     return rv;
 }
 
@@ -542,17 +666,15 @@
  */
 static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2)
 {
-    char *sp, *l1, *l2;
+    char *sp = asp;
+    int n = al2 - al1;
+    int reqsize = (sp - eval->genbuf) + n + 1;
 
-    sp = asp;
-    l1 = al1;
-    l2 = al2;
-    while (l1 < l2) {
-        *sp++ = *l1++;
-        if (sp == &eval->genbuf[LBSIZE+1])
-            break;
+    if (eval->gsize < reqsize) {
+        grow_gen_buffer(eval, reqsize, &sp);
     }
-    return(sp);
+    memcpy(sp, al1, n);
+    return sp + n;
 }
 
 /*
@@ -600,9 +722,7 @@
             }
 
             p1++;
-            p2 = eval->linebuf;
-            while(*p2++ = *p1++);
-            eval->lspend = p2-1;
+            copy_to_linebuf(eval, p1);
             eval->jflag++;
             break;
 
@@ -612,45 +732,21 @@
             break;
 
         case GCOM:
-            p1 = eval->linebuf;
-            p2 = eval->holdbuf;
-            while(*p1++ = *p2++);
-            eval->lspend = p1-1;
+            copy_to_linebuf(eval, eval->holdbuf);
             break;
 
         case CGCOM:
-            *eval->lspend++ = '\n';
-            p1 = eval->lspend;
-            p2 = eval->holdbuf;
-            do {
-                if (p1 == &eval->linebuf[LBSIZE+1]) {
-                    eval_errf(eval, SEDERR_OLTL, eval->lnum);
-                    *--p1 = '\0';
-                    return APR_EGENERAL;
-                }
-            } while(*p1++ = *p2++);
-            eval->lspend = p1-1;
+            append_to_linebuf(eval, "\n");
+            append_to_linebuf(eval, eval->holdbuf);
             break;
 
         case HCOM:
-            p1 = eval->holdbuf;
-            p2 = eval->linebuf;
-            while(*p1++ = *p2++);
-            eval->hspend = p1-1;
+            copy_to_holdbuf(eval, eval->linebuf);
             break;
 
         case CHCOM:
-            *eval->hspend++ = '\n';
-            p1 = eval->hspend;
-            p2 = eval->linebuf;
-            do {
-                if (p1 == &eval->holdbuf[LBSIZE+1]) {
-                    eval_errf(eval, SEDERR_HSOVERFLOW);
-                    *--p1 = '\0';
-                    return APR_EGENERAL;
-                }
-            } while(*p1++ = *p2++);
-            eval->hspend = p1-1;
+            append_to_holdbuf(eval, "\n");
+            append_to_holdbuf(eval, eval->linebuf);
             break;
 
         case ICOM:
@@ -744,7 +840,7 @@
         case CNCOM:
             if(eval->aptr > eval->abuf)
                 arout(eval);
-            *eval->lspend++ = '\n';
+            append_to_linebuf(eval, "\n");
             eval->pending = ipc->next;
             break;
 
@@ -804,17 +900,9 @@
                                 eval->linebuf);
             break;
         case XCOM:
-            p1 = eval->linebuf;
-            p2 = eval->genbuf;
-            while(*p2++ = *p1++);
-            p1 = eval->holdbuf;
-            p2 = eval->linebuf;
-            while(*p2++ = *p1++);
-            eval->lspend = p2 - 1;
-            p1 = eval->genbuf;
-            p2 = eval->holdbuf;
-            while(*p2++ = *p1++);
-            eval->hspend = p2 - 1;
+            copy_to_genbuf(eval, eval->linebuf);
+            copy_to_linebuf(eval, eval->holdbuf);
+            copy_to_holdbuf(eval, eval->genbuf);
             break;
 
         case YCOM: 

Re: Solaris sed based apache filtering module (mod_sed)

Posted by Basant Kukreja <Ba...@Sun.COM>.
Minor changes : Fixed remaining warnings :
* warning: array subscript has type 'char'
* warning: suggest parentheses around assignment used as truth value
* warning C4018: '<' : signed/unsigned mismatch

Here is the diff :
----------------------------------------------------------------
diff -r 071789bf9134 regexp.c
--- a/regexp.c  Sun Jun 29 12:52:34 2008 -0700
+++ b/regexp.c  Fri Aug 08 17:49:35 2008 -0700
@@ -396,6 +396,7 @@ static int _advance(char *lp, char *ep, 
     char *bbeg;
     char neg;
     int ct;
+    int epint; /* int value of *ep */
 
     while (1) {
         neg = 0;
@@ -440,11 +441,15 @@ static int _advance(char *lp, char *ep, 
             return (0);
 
         case CBRA:
-            vars->braslist[*ep++] = lp;
+            epint = (int) *ep;
+            vars->braslist[epint] = lp;
+            ep++;
             continue;
 
         case CKET:
-            vars->braelist[*ep++] = lp;
+            epint = (int) *ep;
+            vars->braelist[epint] = lp;
+            ep++;
             continue;
 
         case CCHR | RNGE:
@@ -516,8 +521,10 @@ static int _advance(char *lp, char *ep, 
             goto star;
 
         case CBACK:
-            bbeg = vars->braslist[*ep];
-            ct = vars->braelist[*ep++] - bbeg;
+            epint = (int) *ep;
+            bbeg = vars->braslist[epint];
+            ct = vars->braelist[epint] - bbeg;
+            ep++;
 
             if (ecmp(bbeg, lp, ct)) {
                 lp += ct;
@@ -526,8 +533,10 @@ static int _advance(char *lp, char *ep, 
             return (0);
 
         case CBACK | STAR:
-            bbeg = vars->braslist[*ep];
-            ct = vars->braelist[*ep++] - bbeg;
+            epint = (int) *ep;
+            bbeg = vars->braslist[epint];
+            ct = vars->braelist[epint] - bbeg;
+            ep++;
             curlp = lp;
             while (ecmp(bbeg, lp, ct))
                 lp += ct;
diff -r 071789bf9134 sed0.c
--- a/sed0.c    Sun Jun 29 12:52:34 2008 -0700
+++ b/sed0.c    Fri Aug 08 17:49:35 2008 -0700
@@ -343,7 +343,7 @@ swit:
             }
             *--tp = '\0';
 
-            if (lpt = search(commands)) {
+            if ((lpt = search(commands)) != NULL) {
                 if (lpt->address) {
                     command_errf(commands, SEDERR_DLMES, commands->linebuf);
                     return -1;
@@ -437,8 +437,8 @@ jtcommon:
             commands->cp--;
 
             if (*commands->cp == '\0') {
-                if (pt = commands->labtab->chain) {
-                    while (pt1 = pt->lb1)
+                if ((pt = commands->labtab->chain) != NULL) {
+                    while ((pt1 = pt->lb1) != NULL)
                         pt = pt1;
                     pt->lb1 = commands->rep;
                 } else
@@ -454,12 +454,12 @@ jtcommon:
             commands->cp--;
             *--tp = '\0';
 
-            if (lpt = search(commands)) {
+            if ((lpt = search(commands)) != NULL) {
                 if (lpt->address) {
                     commands->rep->lb1 = lpt->address;
                 } else {
                     pt = lpt->chain;
-                    while (pt1 = pt->lb1)
+                    while ((pt1 = pt->lb1) != NULL)
                         pt = pt1;
                     pt->lb1 = commands->rep;
                 }
@@ -926,6 +926,7 @@ static char *ycomp(sed_commands_t *comma
 static char *ycomp(sed_commands_t *commands, char *expbuf)
 {
     char    c;
+    int cint; /* integer value of char c */
     char *ep, *tsp;
     int i;
     char    *sp;
@@ -953,11 +954,12 @@ static char *ycomp(sed_commands_t *comma
             sp++;
             c = '\n';
         }
-        if((ep[c] = *tsp++) == '\\' && *tsp == 'n') {
-            ep[c] = '\n';
+        cint = (int) c;
+        if((ep[cint] = *tsp++) == '\\' && *tsp == 'n') {
+            ep[cint] = '\n';
             tsp++;
         }
-        if(ep[c] == commands->sseof || ep[c] == '\0') {
+        if(ep[cint] == commands->sseof || ep[cint] == '\0') {
             command_errf(commands, SEDERR_TSNTSS, commands->linebuf);
         }
     }
diff -r 071789bf9134 sed1.c
--- a/sed1.c    Sun Jun 29 12:52:34 2008 -0700
+++ b/sed1.c    Fri Aug 08 17:49:35 2008 -0700
@@ -152,7 +152,7 @@ static void grow_gen_buffer(sed_eval_t *
  */
 static void appendmem_to_linebuf(sed_eval_t *eval, const char* sz, int len)
 {
-    int reqsize = (eval->lspend - eval->linebuf) + len;
+    unsigned int reqsize = (eval->lspend - eval->linebuf) + len;
     if (eval->lsize < reqsize) {
         grow_line_buffer(eval, reqsize);
     }
@@ -186,7 +186,7 @@ static void append_to_holdbuf(sed_eval_t
 static void append_to_holdbuf(sed_eval_t *eval, const char* sz)
 {
     int len = strlen(sz);
-    int reqsize = (eval->hspend - eval->holdbuf) + len + 1;
+    unsigned int reqsize = (eval->hspend - eval->holdbuf) + len + 1;
     if (eval->hsize <= reqsize) {
         grow_hold_buffer(eval, reqsize);
     }
@@ -210,7 +210,7 @@ static void append_to_genbuf(sed_eval_t 
 static void append_to_genbuf(sed_eval_t *eval, const char* sz, char **gspend)
 {
     int len = strlen(sz);
-    int reqsize = (*gspend - eval->genbuf) + len + 1;
+    unsigned int reqsize = (*gspend - eval->genbuf) + len + 1;
     if (eval->gsize < reqsize) {
         grow_gen_buffer(eval, reqsize, gspend);
     }
@@ -225,7 +225,7 @@ static void copy_to_genbuf(sed_eval_t *e
 static void copy_to_genbuf(sed_eval_t *eval, const char* sz)
 {
     int len = strlen(sz);
-    int reqsize = len + 1;
+    unsigned int reqsize = len + 1;
     if (eval->gsize < reqsize) {
         grow_gen_buffer(eval, reqsize, NULL);
     }
@@ -630,7 +630,7 @@ static apr_status_t dosub(sed_eval_t *ev
     sp = eval->genbuf;
     rp = rhsbuf;
     sp = place(eval, sp, lp, step_vars->loc1);
-    while(c = *rp++) {
+    while ((c = *rp++) != 0) {
         if (c == '&') {
             sp = place(eval, sp, step_vars->loc1, step_vars->loc2);
             if (sp == NULL)
@@ -667,7 +667,7 @@ static char *place(sed_eval_t *eval, cha
 {
     char *sp = asp;
     int n = al2 - al1;
-    int reqsize = (sp - eval->genbuf) + n + 1;
+    unsigned int reqsize = (sp - eval->genbuf) + n + 1;
 
     if (eval->gsize < reqsize) {
         grow_gen_buffer(eval, reqsize, &sp);
@@ -726,7 +726,7 @@ static apr_status_t command(sed_eval_t *
             break;
 
         case EQCOM:
-            length = apr_snprintf(sz, sizeof(sz), "%lld", eval->lnum);
+            length = apr_snprintf(sz, sizeof(sz), "%d", (int) eval->lnum);
             wline(eval, sz, length);
             break;
 
@@ -766,7 +766,7 @@ static apr_status_t command(sed_eval_t *
                 if((unsigned char)*p1 >= 040) {
                     if(*p1 == 0177) {
                         p3 = rub;
-                        while(*p2++ = *p3++)
+                        while ((*p2++ = *p3++) != 0)
                             if(p2 >= eval->lcomend) {
                                 *p2 = '\\';
                                 wline(eval, eval->genbuf,
@@ -812,7 +812,7 @@ static apr_status_t command(sed_eval_t *
                     }
                 } else {
                     p3 = trans[(unsigned char)*p1-1];
-                    while(*p2++ = *p3++)
+                    while ((*p2++ = *p3++) != 0)
                         if(p2 >= eval->lcomend) {
                             *p2 = '\\';
                             wline(eval, eval->genbuf, strlen(eval->genbuf));
@@ -907,7 +907,7 @@ static apr_status_t command(sed_eval_t *
         case YCOM: 
             p1 = eval->linebuf;
             p2 = ipc->re1;
-            while(*p1 = p2[(unsigned char)*p1])    p1++;
+            while((*p1 = p2[(unsigned char)*p1]) != 0)    p1++;
             break;
     }
     return APR_SUCCESS;
----------------------------------------------------------------

Re: Solaris sed based apache filtering module (mod_sed)

Posted by Ba...@Sun.COM.
Solaris ucb sed code works fine when each line has new line character. If new
line character is missing from the end of the file then behaviour was not
friendly. The reason is that sed is a true "line" editor.

$ cat nocrlf.inp
<HTML>
abcd
</HTML>   ---> "no new line here"
$ /usr/ucb/sed -e 's/a/g/g' nocrlf.inp
<HTML>
gbcd

gnu sed behaves properly in above situation.

This is the fix for the regression caused by my previous checkin. If last byte
of the file is not a new line, then last byte was not printing in to the
output.
Steffen <in...@apachelounge.com> reported this issue to me.

diff is attached.

Regards,
Basant.

diff -r 2866cd8c83a2 sed1.c
--- a/sed1.c    Sat Jun 28 21:00:41 2008 -0700
+++ b/sed1.c    Sun Jun 29 12:51:49 2008 -0700
@@ -432,11 +432,10 @@ apr_status_t sed_finalize_eval(sed_eval_
             eval->lspend--;
         } else {
             /* Code can probably reach here when last character in output
-             * buffer is not null terminated
+             * buffer is not a newline.
              */
             /* Assure space for NULL */
             append_to_linebuf(eval, "");
-            eval->lspend--;
         }

         *eval->lspend = '\0';


On Sat, Jun 28, 2008 at 09:08:50PM -0700, Basant.Kukreja@Sun.COM wrote:
> mod_sed constant length buffer sizes fix :
> 
> Three buffers linebuf, genbuf and holdbuf are now reallocated dynamically.
> Sed code has 3 buffers :
> linebuf : Store a line.
> holdbuf : store the intemediate hold data (sed h/H commands)
> genbuf : Used in substitution intermediate results.
> 
> Original sed has the limitation on the fixed size buffers.
> In this fix all these 3 buffers are adjusted dynamically. Initial buffer size
> of these buffers is 1024 bytes. When these buffers needs reallocation, their
> new buffer size is aligned to 4KB boundary.
> 
> List of affected files :
> sed1.c libsed.h
> 
> Code has been updated and can be obtained by mercurial as :
> $ hg clone ssh://anon@hg.opensolaris.org/hg/webstack/mod_sed
> 
> It should soon be visible at :
> http://src.opensolaris.org/source/xref/webstack/mod_sed/
> 
> Diff is attached.
> 
> Regards,
> Basant.
> 
> 
> -------------------------------------------------------------
> diff -r 32f5eb1dc14f libsed.h
> --- a/libsed.h  Wed Apr 30 11:52:57 2008 -0700
> +++ b/libsed.h  Sat Jun 28 20:35:06 2008 -0700
> @@ -121,17 +121,14 @@
>  
>      unsigned       lsize;
>      char           *linebuf;
> -    char           *lbend;
>      char           *lspend;
>  
>      unsigned       hsize;
>      char           *holdbuf;
> -    char           *hbend;
>      char           *hspend;
>  
>      unsigned       gsize;
>      char           *genbuf;
> -    char           *gbend;
>      char           *lcomend;
>  
>      apr_file_t    *fcode[NWFILES];
> diff -r 32f5eb1dc14f sed1.c
> --- a/sed1.c    Wed Apr 30 11:52:57 2008 -0700
> +++ b/sed1.c    Sat Jun 28 20:35:06 2008 -0700
> @@ -86,6 +86,151 @@
>      }
>  }
>  
> +#define INIT_BUF_SIZE 1024
> +
> +/*
> + * grow_buffer
> + */
> +static void grow_buffer(apr_pool_t *pool, char **buffer,
> +                        char **spend, unsigned int *cursize,
> +                        unsigned int newsize)
> +{
> +    char* newbuffer = NULL;
> +    int spendsize = 0;
> +    if (*cursize >= newsize)
> +        return;
> +    /* Align it to 4 KB boundary */
> +    newsize = (newsize  + ((1 << 12) - 1)) & ~((1 << 12) -1);
> +    newbuffer = apr_pcalloc(pool, newsize);
> +    if (*spend && *buffer && (*cursize > 0)) {
> +        spendsize = *spend - *buffer;
> +    }
> +    if ((*cursize > 0) && *buffer) {
> +        memcpy(newbuffer, *buffer, *cursize);
> +    }
> +    *buffer = newbuffer;
> +    *cursize = newsize;
> +    if (spend != buffer) {
> +        *spend = *buffer + spendsize;
> +    }
> +}
> +
> +/*
> + * grow_line_buffer
> + */
> +static void grow_line_buffer(sed_eval_t *eval, int newsize)
> +{
> +    grow_buffer(eval->pool, &eval->linebuf, &eval->lspend,
> +                &eval->lsize, newsize);
> +}
> +
> +/*
> + * grow_hold_buffer
> + */
> +static void grow_hold_buffer(sed_eval_t *eval, int newsize)
> +{
> +    grow_buffer(eval->pool, &eval->holdbuf, &eval->hspend,
> +                &eval->hsize, newsize);
> +}
> +
> +/*
> + * grow_gen_buffer
> + */
> +static void grow_gen_buffer(sed_eval_t *eval, int newsize,
> +                            char **gspend)
> +{
> +    if (gspend == NULL) {
> +        gspend = &eval->genbuf;
> +    }
> +    grow_buffer(eval->pool, &eval->genbuf, gspend,
> +                &eval->gsize, newsize);
> +    eval->lcomend = &eval->genbuf[71];
> +}
> +
> +/*
> + * appendmem_to_linebuf
> + */
> +static void appendmem_to_linebuf(sed_eval_t *eval, const char* sz, int len)
> +{
> +    int reqsize = (eval->lspend - eval->linebuf) + len;
> +    if (eval->lsize < reqsize) {
> +        grow_line_buffer(eval, reqsize);
> +    }
> +    memcpy(eval->lspend, sz, len);
> +    eval->lspend += len;
> +}
> +
> +/*
> + * append_to_linebuf
> + */
> +static void append_to_linebuf(sed_eval_t *eval, const char* sz)
> +{
> +    int len = strlen(sz);
> +    /* Copy string including null character */
> +    appendmem_to_linebuf(eval, sz, len + 1);
> +    --eval->lspend; /* lspend will now point to NULL character */
> +}
> +
> +/*
> + * copy_to_linebuf
> + */
> +static void copy_to_linebuf(sed_eval_t *eval, const char* sz)
> +{
> +    eval->lspend = eval->linebuf;
> +    append_to_linebuf(eval, sz);
> +}
> +
> +/*
> + * append_to_holdbuf
> + */
> +static void append_to_holdbuf(sed_eval_t *eval, const char* sz)
> +{
> +    int len = strlen(sz);
> +    int reqsize = (eval->hspend - eval->holdbuf) + len + 1;
> +    if (eval->hsize <= reqsize) {
> +        grow_hold_buffer(eval, reqsize);
> +    }
> +    strcpy(eval->hspend, sz);
> +    /* hspend will now point to NULL character */
> +    eval->hspend += len;
> +}
> +
> +/*
> + * copy_to_holdbuf
> + */
> +static void copy_to_holdbuf(sed_eval_t *eval, const char* sz)
> +{
> +    eval->hspend = eval->holdbuf;
> +    append_to_holdbuf(eval, sz);
> +}
> +
> +/*
> + * append_to_genbuf
> + */
> +static void append_to_genbuf(sed_eval_t *eval, const char* sz, char **gspend)
> +{
> +    int len = strlen(sz);
> +    int reqsize = (*gspend - eval->genbuf) + len + 1;
> +    if (eval->gsize < reqsize) {
> +        grow_gen_buffer(eval, reqsize, gspend);
> +    }
> +    strcpy(*gspend, sz);
> +    /* *gspend will now point to NULL character */
> +    *gspend += len;
> +}
> +
> +/*
> + * copy_to_genbuf
> + */
> +static void copy_to_genbuf(sed_eval_t *eval, const char* sz)
> +{
> +    int len = strlen(sz);
> +    int reqsize = len + 1;
> +    if (eval->gsize < reqsize) {
> +        grow_gen_buffer(eval, reqsize, NULL);
> +    }
> +}
> +
>  /*
>   * sed_init_eval
>   */
> @@ -113,16 +258,16 @@
>      eval->fout = NULL;
>  
>      if (eval->linebuf == NULL) {
> -        eval->linebuf = apr_palloc(eval->pool, LBSIZE + 1);
> -        eval->lbend = eval->linebuf + LBSIZE;
> +        eval->lsize = INIT_BUF_SIZE;
> +        eval->linebuf = apr_pcalloc(eval->pool, eval->lsize);
>      }
>      if (eval->holdbuf == NULL) {
> -        eval->holdbuf = apr_palloc(eval->pool, LBSIZE + 1);
> -        eval->hbend = eval->holdbuf + LBSIZE;
> +        eval->hsize = INIT_BUF_SIZE;
> +        eval->holdbuf = apr_pcalloc(eval->pool, eval->hsize);
>      }
>      if (eval->genbuf == NULL) {
> -        eval->genbuf = apr_palloc(eval->pool, LBSIZE + 1);
> -        eval->gbend = eval->genbuf + LBSIZE;
> +        eval->gsize = INIT_BUF_SIZE;
> +        eval->genbuf = apr_pcalloc(eval->pool, eval->gsize);
>      }
>      eval->lspend = eval->linebuf;
>      eval->hspend = eval->holdbuf;
> @@ -243,18 +388,13 @@
>              eval->lreadyflag = 1;
>              break;
>          }
> -
> -        while ((eval->linebuf + LBSIZE) <= eval->lspend + llen + 1) {
> -            /* XXX : grow buffer */
> -            return APR_EGENERAL;
> -        }
> -
> -        memcpy(eval->lspend, buf, llen);
> -        eval->lspend += llen;
> +        
> +        appendmem_to_linebuf(eval, buf, llen + 1);
> +        --eval->lspend;
> +        /* replace new line character with NULL */
> +        *eval->lspend = '\0';
>          buf += (llen + 1);
>          bufsz -= (llen + 1);
> -
> -        *eval->lspend = '\0';
>          rv = execute(eval);
>          if (rv != 0)
>              return APR_EGENERAL;
> @@ -264,12 +404,7 @@
>  
>      /* Save the leftovers for later */
>      if (bufsz) {
> -        if ((eval->linebuf + LBSIZE) <= eval->lspend + bufsz) {
> -            /* XXX : grow buffer */
> -            return APR_EGENERAL;
> -        }
> -        memcpy(eval->lspend, buf, bufsz);
> -        eval->lspend += bufsz;
> +        appendmem_to_linebuf(eval, buf, bufsz);
>      }
>  
>      return APR_SUCCESS;
> @@ -296,10 +431,12 @@
>              eval->lreadyflag = 0;
>              eval->lspend--;
>          } else {
> -            if ((eval->linebuf + LBSIZE) <= eval->lspend) {
> -                /* XXX : grow buffer */
> -                return APR_EGENERAL;
> -            }
> +            /* Code can probably reach here when last character in output
> +             * buffer is not null terminated 
> +             */
> +            /* Assure space for NULL */
> +            append_to_linebuf(eval, "");
> +            eval->lspend--;
>          }
>  
>          *eval->lspend = '\0';
> @@ -493,8 +630,7 @@
>      lp = eval->linebuf;
>      sp = eval->genbuf;
>      rp = rhsbuf;
> -    while (lp < step_vars->loc1)
> -        *sp++ = *lp++;
> +    sp = place(eval, sp, lp, step_vars->loc1);
>      while(c = *rp++) {
>          if (c == '&') {
>              sp = place(eval, sp, step_vars->loc1, step_vars->loc2);
> @@ -513,27 +649,15 @@
>                  *sp++ = c;
>            } else
>              *sp++ = c;
> -        if (sp == &eval->genbuf[LBSIZE+1]) {
> -            eval_errf(eval, SEDERR_OLTL, eval->lnum);
> -            *--sp = '\0';
> -            rv = APR_EGENERAL;
> -            goto out;
> +        if (sp >= eval->genbuf + eval->gsize) {
> +            /* expand genbuf and set the sp appropriately */
> +            grow_gen_buffer(eval, eval->gsize + 1024, &sp);
>          }
>      }
>      lp = step_vars->loc2;
>      step_vars->loc2 = sp - eval->genbuf + eval->linebuf;
> -    while(*sp++ = *lp++)
> -        if (sp == &eval->genbuf[LBSIZE+1]) {
> -            eval_errf(eval, SEDERR_OLTL, eval->lnum);
> -            *--sp = '\0';
> -            rv = APR_EGENERAL;
> -            break;
> -        }
> -out:
> -    lp = eval->linebuf;
> -    sp = eval->genbuf;
> -    while (*lp++ = *sp++);
> -    eval->lspend = lp-1;
> +    append_to_genbuf(eval, lp, &sp);
> +    copy_to_linebuf(eval, eval->genbuf);
>      return rv;
>  }
>  
> @@ -542,17 +666,15 @@
>   */
>  static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2)
>  {
> -    char *sp, *l1, *l2;
> +    char *sp = asp;
> +    int n = al2 - al1;
> +    int reqsize = (sp - eval->genbuf) + n + 1;
>  
> -    sp = asp;
> -    l1 = al1;
> -    l2 = al2;
> -    while (l1 < l2) {
> -        *sp++ = *l1++;
> -        if (sp == &eval->genbuf[LBSIZE+1])
> -            break;
> +    if (eval->gsize < reqsize) {
> +        grow_gen_buffer(eval, reqsize, &sp);
>      }
> -    return(sp);
> +    memcpy(sp, al1, n);
> +    return sp + n;
>  }
>  
>  /*
> @@ -600,9 +722,7 @@
>              }
>  
>              p1++;
> -            p2 = eval->linebuf;
> -            while(*p2++ = *p1++);
> -            eval->lspend = p2-1;
> +            copy_to_linebuf(eval, p1);
>              eval->jflag++;
>              break;
>  
> @@ -612,45 +732,21 @@
>              break;
>  
>          case GCOM:
> -            p1 = eval->linebuf;
> -            p2 = eval->holdbuf;
> -            while(*p1++ = *p2++);
> -            eval->lspend = p1-1;
> +            copy_to_linebuf(eval, eval->holdbuf);
>              break;
>  
>          case CGCOM:
> -            *eval->lspend++ = '\n';
> -            p1 = eval->lspend;
> -            p2 = eval->holdbuf;
> -            do {
> -                if (p1 == &eval->linebuf[LBSIZE+1]) {
> -                    eval_errf(eval, SEDERR_OLTL, eval->lnum);
> -                    *--p1 = '\0';
> -                    return APR_EGENERAL;
> -                }
> -            } while(*p1++ = *p2++);
> -            eval->lspend = p1-1;
> +            append_to_linebuf(eval, "\n");
> +            append_to_linebuf(eval, eval->holdbuf);
>              break;
>  
>          case HCOM:
> -            p1 = eval->holdbuf;
> -            p2 = eval->linebuf;
> -            while(*p1++ = *p2++);
> -            eval->hspend = p1-1;
> +            copy_to_holdbuf(eval, eval->linebuf);
>              break;
>  
>          case CHCOM:
> -            *eval->hspend++ = '\n';
> -            p1 = eval->hspend;
> -            p2 = eval->linebuf;
> -            do {
> -                if (p1 == &eval->holdbuf[LBSIZE+1]) {
> -                    eval_errf(eval, SEDERR_HSOVERFLOW);
> -                    *--p1 = '\0';
> -                    return APR_EGENERAL;
> -                }
> -            } while(*p1++ = *p2++);
> -            eval->hspend = p1-1;
> +            append_to_holdbuf(eval, "\n");
> +            append_to_holdbuf(eval, eval->linebuf);
>              break;
>  
>          case ICOM:
> @@ -744,7 +840,7 @@
>          case CNCOM:
>              if(eval->aptr > eval->abuf)
>                  arout(eval);
> -            *eval->lspend++ = '\n';
> +            append_to_linebuf(eval, "\n");
>              eval->pending = ipc->next;
>              break;
>  
> @@ -804,17 +900,9 @@
>                                  eval->linebuf);
>              break;
>          case XCOM:
> -            p1 = eval->linebuf;
> -            p2 = eval->genbuf;
> -            while(*p2++ = *p1++);
> -            p1 = eval->holdbuf;
> -            p2 = eval->linebuf;
> -            while(*p2++ = *p1++);
> -            eval->lspend = p2 - 1;
> -            p1 = eval->genbuf;
> -            p2 = eval->holdbuf;
> -            while(*p2++ = *p1++);
> -            eval->hspend = p2 - 1;
> +            copy_to_genbuf(eval, eval->linebuf);
> +            copy_to_linebuf(eval, eval->holdbuf);
> +            copy_to_holdbuf(eval, eval->genbuf);
>              break;
>  
>          case YCOM: