]> granicus.if.org Git - php/commitdiff
Fixed segfault in wordwrap() when wrapping to zero width and using
authorjim winstead <jimw@php.net>
Fri, 4 Jan 2002 19:48:08 +0000 (19:48 +0000)
committerjim winstead <jimw@php.net>
Fri, 4 Jan 2002 19:48:08 +0000 (19:48 +0000)
multi-character break or trying to force cut (bug #12768, now fails
and issues a warning because forcing a zero-width cut doesn't make
sense). Also converted to new paramater-passing API and avoid making
an extra copy of the return values.
# also added tests.
@- Fixed segfault in wordwrap() when wrapping to zero width and using
@  multi-character break or trying to force cut (bug #12768). (Jim)

ext/standard/string.c
ext/standard/tests/strings/wordwrap.phpt [new file with mode: 0644]

index 764b394cc417f2651b3c6f1bdef54591e03e581e..6b897346e03841ae6ad0f91fa8fd86c1c1cfa85f 100644 (file)
@@ -613,49 +613,27 @@ PHP_FUNCTION(ltrim)
    Wraps buffer to selected number of characters using string break char */
 PHP_FUNCTION(wordwrap)
 {
-       zval **ptext, **plinelength, **pbreakchar, **cut;
-       long i = 0, l = 0, pgr = 0, linelength = 0, last = 0, breakcharlen, docut = 0;
-       char *text, *breakchar, *newtext; 
-       int argc = ZEND_NUM_ARGS();
+       char *text, *breakchar = "\n", *newtext;
+       int textlen, breakcharlen = 1, newtextlen;
+       long linelength = 75, i = 0, l = 0, pgr = 0, last = 0;
+       zend_bool docut = 0;
 
-       if (argc < 1 || argc > 4 || 
-               zend_get_parameters_ex(ZEND_NUM_ARGS(), &ptext, &plinelength, &pbreakchar, &cut) == FAILURE) {
-               WRONG_PARAM_COUNT;
-       }
-       convert_to_string_ex(ptext);
-       
-       if (Z_STRVAL_PP(ptext) == 0)
-               RETURN_FALSE;
-
-       text = Z_STRVAL_PP(ptext);
-
-       if (argc > 1) {
-               convert_to_long_ex(plinelength);
-               linelength = Z_LVAL_PP(plinelength);
-       }
-       else {
-               linelength = 75;
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lsb", &text, &textlen, &linelength, &breakchar, &breakcharlen, &docut) == FAILURE) {
+               return;
        }
 
-       if (argc > 2) {
-               convert_to_string_ex(pbreakchar);
-               breakchar = Z_STRVAL_PP(pbreakchar);
-               breakcharlen = Z_STRLEN_PP(pbreakchar);
-       }
-       else {
-               breakchar = "\n";
-               breakcharlen = 1;
-       }
+       if (textlen == 0)
+               RETURN_FALSE;
 
-       if (argc > 3) {
-               convert_to_long_ex(cut);
-               docut = Z_LVAL_PP(cut);
+       if (linelength == 0 && docut) {
+               php_error(E_WARNING, "%s() can't force cut when width is zero",get_active_function_name(TSRMLS_C));
+               RETURN_FALSE;
        }
 
        /* Special case for a single-character break as it needs no
           additional storage space */
-       if (breakcharlen == 1 && docut == 0) {
-               newtext = estrndup(text, Z_STRLEN_PP(ptext));
+       if (breakcharlen == 1 && !docut) {
+               newtext = estrndup(text, textlen);
                while (newtext[i] != '\0') {
 
                        /* prescan line to see if it is greater than linelength */
@@ -697,12 +675,12 @@ PHP_FUNCTION(wordwrap)
                        i += l + 1;
                }
 
-               RETVAL_STRINGL(newtext, strlen(newtext), 1);
-               efree(newtext);
+               RETURN_STRINGL(newtext, textlen, 0);
        }
        else {
                /* Multiple character line break */
-               newtext = emalloc(Z_STRLEN_PP(ptext) * (breakcharlen + 1) + 1);
+               newtextlen = textlen * (breakcharlen + 1) + 1;
+               newtext = emalloc(newtextlen);
                newtext[0] = '\0';
 
                i = 0;
@@ -726,7 +704,7 @@ PHP_FUNCTION(wordwrap)
                                while (l >= 0) {
                                        if (text[i+l] == ' ') {
                                                strncat(newtext, text+last, i+l-last);
-                                               strcat(newtext, breakchar);
+                                               strncat(newtext, breakchar, breakcharlen);
                                                last = i + l + 1;
                                                break;
                                        }
@@ -737,19 +715,22 @@ PHP_FUNCTION(wordwrap)
                                        /* couldn't break it backwards, try looking forwards */
                                        l = linelength - 1;
                                        while (l <= pgr) {
-                                               if (docut == 0) {
+                                               if (!docut) {
                                                        if (text[i+l] == ' ') {
                                                                strncat(newtext, text+last, i+l-last);
-                                                               strcat(newtext, breakchar);
+                                                               strncat(newtext, breakchar, breakcharlen);
                                                                last = i + l + 1;
+                                                               ++l;
                                                                break;
                                                        }
                                                }
-                                               if (docut == 1) {
+                                               /* cut if longer than allowed */
+                                               else {
                                                        if (text[i+l] == ' ' || l > i-last) {
                                                                strncat(newtext, text+last, i+l-last+1);
-                                                               strcat(newtext, breakchar);
+                                                               strncat(newtext, breakchar, breakcharlen);
                                                                last = i + l + 1;
+                                                               ++l;
                                                                break;
                                                        }
                                                }
@@ -764,11 +745,10 @@ PHP_FUNCTION(wordwrap)
                }
 
                if (i + l > last) {
-                       strcat(newtext, text+last);
+                       strncat(newtext, text+last, i+l-last);
                }
 
-               RETVAL_STRINGL(newtext, strlen(newtext), 1);
-               efree(newtext);
+               RETURN_STRINGL(newtext, strlen(newtext), 0);
        }
 }
 /* }}} */
diff --git a/ext/standard/tests/strings/wordwrap.phpt b/ext/standard/tests/strings/wordwrap.phpt
new file mode 100644 (file)
index 0000000..4e30fb4
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+wordwrap() function
+--POST--
+--GET--
+--FILE--
+<?php
+
+$tests = <<<TESTS
+"12345 12345 12345 12345" === wordwrap("12345 12345 12345 12345")
+"12345 12345\\n1234567890\\n1234567890" === wordwrap("12345 12345 1234567890 1234567890",12)
+"12345\\n12345\\n12345\\n12345" === wordwrap("12345 12345 12345 12345",0)
+"12345ab12345ab12345ab12345" === wordwrap("12345 12345 12345 12345",0,"ab")
+"12345 12345ab1234567890ab1234567890" === wordwrap("12345 12345 1234567890 1234567890",12,"ab")
+TESTS;
+
+include('../../../../tests/quicktester.inc');
+
+--EXPECT--
+OK