Fix for wordwrap() buffer overflow, CAN-2002-1396. --- php-4.2.2/ext/standard/string.c.wrap 2002-04-25 15:52:58.000000000 +0100 +++ php-4.2.2/ext/standard/string.c 2003-01-22 14:34:47.000000000 +0000 @@ -616,7 +616,7 @@ { const char *text, *breakchar = "\n"; char *newtext; - int textlen, breakcharlen = 1, newtextlen; + int textlen, breakcharlen = 1, newtextlen, alloced, chk; long current = 0, laststart = 0, lastspace = 0; long linelength = 75; zend_bool docut = 0; @@ -642,38 +642,40 @@ for (current = 0; current < textlen; current++) { if (text[current] == breakchar[0]) { laststart = lastspace = current; - } - else if (text[current] == ' ') { + } else if (text[current] == ' ') { if (current - laststart >= linelength) { newtext[current] = breakchar[0]; laststart = current; } lastspace = current; - } - else if (current - laststart >= linelength - && laststart != lastspace) { + } else if (current - laststart >= linelength && laststart != lastspace) { newtext[lastspace] = breakchar[0]; laststart = lastspace; } } RETURN_STRINGL(newtext, textlen, 0); - } - else { + } else { /* Multiple character line break or forced cut */ if (linelength > 0) { - newtextlen = textlen + (textlen/linelength + 1) * breakcharlen + 1; - } - else { - newtextlen = textlen * (breakcharlen + 1) + 1; + chk = (int)(textlen/linelength + 1); + alloced = textlen + chk * breakcharlen + 1; + } else { + chk = textlen; + alloced = textlen * (breakcharlen + 1) + 1; } - newtext = emalloc(newtextlen); + newtext = emalloc(alloced); /* now keep track of the actual new text length */ newtextlen = 0; laststart = lastspace = 0; for (current = 0; current < textlen; current++) { + if (chk <= 0) { + alloced += (int) (((textlen - current + 1)/linelength + 1) * breakcharlen) + 1; + newtext = erealloc(newtext, alloced); + chk = (int) ((textlen - current)/linelength) + 1; + } /* when we hit an existing break, copy to new buffer, and * fix up laststart and lastspace */ if (text[current] == breakchar[0] @@ -683,6 +685,7 @@ newtextlen += current-laststart+breakcharlen; current += breakcharlen - 1; laststart = lastspace = current + 1; + chk--; } /* if it is a space, check if it is at the line boundary, * copy and insert a break, or just keep track of it */ @@ -693,6 +696,7 @@ memcpy(newtext+newtextlen, breakchar, breakcharlen); newtextlen += breakcharlen; laststart = current + 1; + chk--; } lastspace = current; } @@ -706,6 +710,7 @@ memcpy(newtext+newtextlen, breakchar, breakcharlen); newtextlen += breakcharlen; laststart = lastspace = current; + chk--; } /* if the current word puts us over the linelength, copy * back up until the last space, insert a break, and move @@ -717,6 +722,7 @@ memcpy(newtext+newtextlen, breakchar, breakcharlen); newtextlen += breakcharlen; laststart = lastspace = lastspace + 1; + chk--; } } @@ -727,6 +733,8 @@ } newtext[newtextlen] = '\0'; + /* free unused memory */ + newtext = erealloc(newtext, newtextlen+1); RETURN_STRINGL(newtext, newtextlen, 0); }