Well, my ADD has caused me to refocus my attention back to the issues
of strlcat() and strlcpy().  I started some conversion several months
ago, but other things have interrupted me.  Late last week, I took
a look at what I had started, and wasn't exceptionally impressed with
what I saw.  Although my initial patch did provide the benefits of 
strlcat() and strlcpy() to the core and module writers on systems with
those functions in libc, elsewhere, people were still out in the 
cold.

The attached patch helps to fix that.  It adds two new functions to 
util.c:  Perl_my_strlcat() and Perl_my_strlcpy().  These functions
provide all the functionality that strlcat() and strlcpy() provide
in systems where these functions are not included in libc.  The 
code for these functions were originally released as part of C<inn>,
but the code for strlcat() and strlcpy() within C<inn> was released
into the public domain.  The code required few modifications to 
be worked into Perl, but are mostly as Russ Allbery original had 
written them.  Thanks Russ!

The patch included was tested on Linux, with and without ithreads and
DEBUGGING, and passed all of its tests.

Steve Peters
[EMAIL PROTECTED]
--- doio.c.old  2005-06-23 05:49:45.000000000 -0500
+++ doio.c      2005-06-27 09:37:50.807826128 -0500
@@ -274,17 +274,10 @@
            }
            mode[0] = 'w';
            writing = 1;
-#ifdef HAS_STRLCAT
             if (out_raw)
                 strlcat(mode, "b", PERL_MODE_MAX);
             else if (out_crlf)
                 strlcat(mode, "t", PERL_MODE_MAX); 
-#else
-           if (out_raw)
-               strcat(mode, "b");
-           else if (out_crlf)
-               strcat(mode, "t");
-#endif
            if (num_svs > 1) {
                fp = PerlProc_popen_list(mode, num_svs, svp);
            }
@@ -312,17 +305,10 @@
            }
            writing = 1;
 
-#ifdef HAS_STRLCAT
             if (out_raw)
                 strlcat(mode, "b", PERL_MODE_MAX);
             else if (out_crlf)
                 strlcat(mode, "t", PERL_MODE_MAX);
-#else
-           if (out_raw)
-               strcat(mode, "b");
-           else if (out_crlf)
-               strcat(mode, "t");
-#endif
            if (*type == '&') {
              duplicity:
                dodup = PERLIO_DUP_FD;
@@ -440,17 +426,10 @@
        else if (*type == IoTYPE_RDONLY) {
            for (type++; isSPACE(*type); type++) ;
            mode[0] = 'r';
-#ifdef HAS_STRLCAT
             if (in_raw)
                 strlcat(mode, "b", PERL_MODE_MAX);
             else if (in_crlf)
                 strlcat(mode, "t", PERL_MODE_MAX);
-#else
-           if (in_raw)
-               strcat(mode, "b");
-           else if (in_crlf)
-               strcat(mode, "t");
-#endif
            if (*type == '&') {
                goto duplicity;
            }
@@ -501,17 +480,10 @@
            TAINT_PROPER("piped open");
            mode[0] = 'r';
 
-#ifdef HAS_STRLCAT
             if (in_raw)
                 strlcat(mode, "b", PERL_MODE_MAX);
             else if (in_crlf)
                 strlcat(mode, "t", PERL_MODE_MAX);
-#else
-           if (in_raw)
-               strcat(mode, "b");
-           else if (in_crlf)
-               strcat(mode, "t");
-#endif
 
            if (num_svs > 1) {
                fp = PerlProc_popen_list(mode,num_svs,svp);
@@ -538,17 +510,10 @@
                ;
            mode[0] = 'r';
 
-#ifdef HAS_STRLCAT
             if (in_raw)
                 strlcat(mode, "b", PERL_MODE_MAX);
             else if (in_crlf)
                 strlcat(mode, "t", PERL_MODE_MAX);
-#else
-           if (in_raw)
-               strcat(mode, "b");
-           else if (in_crlf)
-               strcat(mode, "t");
-#endif
 
            if (*name == '-' && name[1] == '\0') {
                fp = PerlIO_stdin();
@@ -1532,19 +1497,11 @@
         char flags[PERL_FLAGS_MAX];
        if (strnEQ(cmd,PL_cshname,PL_cshlen) &&
            strnEQ(cmd+PL_cshlen," -c",3)) {
-#ifdef HAS_STRLCPY
-          strlcpy(flags, "-c", PERL_FLAGS_MAX);
-#else
-         strcpy(flags,"-c");
-#endif
+         strlcpy(flags, "-c", PERL_FLAGS_MAX);
          s = cmd+PL_cshlen+3;
          if (*s == 'f') {
              s++;
-#ifdef HAS_STRLCPY
               strlcat(flags, "f", PERL_FLAGS_MAX);
-#else
-             strcat(flags,"f");
-#endif
          }
          if (*s == ' ')
              s++;
--- embed.fnc.old       2005-06-24 09:30:49.000000000 -0500
+++ embed.fnc   2005-06-25 08:35:49.000000000 -0500
@@ -488,6 +488,12 @@
 Ap     |void   |my_setenv      |const char* nam|const char* val
 Ap     |I32    |my_stat
 Ap     |char * |my_strftime    |const char *fmt|int sec|int min|int hour|int 
mday|int mon|int year|int wday|int yday|int isdst
+#if !defined(HAS_STRLCAT)
+Ap      |size_t |my_strlcat     |char *dst|const char* src|size_t size
+#endif
+#if !defined(HAS_STRLCPY)
+Ap      |size_t |my_strlcpy     |char *dst|const char* src|size_t size
+#endif
 #if defined(MYSWAP)
 ApPa   |short  |my_swap        |short s
 ApPa   |long   |my_htonl       |long l
--- op.c.old    2005-06-20 04:35:16.000000000 -0500
+++ op.c        2005-06-27 10:24:29.097421448 -0500
@@ -223,7 +223,8 @@
            /* The next block assumes the buffer is at least 205 chars
               long.  At present, it's always at least 256 chars. */
            if (p-name > 200) {
-               strcpy(name+200, "...");
+               char *dot_dot = name + 200;
+               strlcpy(dot_dot, "...", sizeof("..."));
                p = name+199;
            }
            else {
--- perl.h.old  2005-06-24 09:25:41.000000000 -0500
+++ perl.h      2005-06-27 10:42:16.820102928 -0500
@@ -978,6 +978,14 @@
 #   endif
 #endif /* !HAS_BCMP */
 
+#ifndef HAS_STRLCAT
+#    define strlcat(d,s,sz) my_strlcat(aTHX_ d,s,sz) 
+#endif
+
+#ifndef HAS_STRLCPY
+#    define strlcpy(d,s,sz) my_strlcpy(aTHX_ d,s,sz)
+#endif
+
 #ifdef I_NETINET_IN
 #   include <netinet/in.h>
 #endif
--- pp_ctl.c.old        2005-06-23 14:23:56.000000000 -0500
+++ pp_ctl.c    2005-06-27 10:25:13.779628720 -0500
@@ -3485,7 +3485,7 @@
     ret = doeval(gimme, NULL, runcv, seq);
     if (PERLDB_INTER && was != (I32)PL_sub_generation /* Some subs defined 
here. */
        && ret != PL_op->op_next) {     /* Successive compilation. */
-       strcpy(safestr, "_<(eval )");   /* Anything fake and short. */
+       strlcpy(safestr, "_<(eval )", strlen(safestr) + 1);     /* Anything 
fake and short. */
     }
     return DOCATCH(ret);
 }
--- pp_sys.c.old        2005-06-24 03:09:51.000000000 -0500
+++ pp_sys.c    2005-06-27 09:35:29.548300840 -0500
@@ -3721,14 +3721,15 @@
     PerlIO *myfp;
     int anum = 1;
 
-    New(666, cmdline, strlen(cmd) + (strlen(filename) * 2) + 10, char);
-    strcpy(cmdline, cmd);
-    strcat(cmdline, " ");
+    const int size = strlen(cmd) + (strlen(filename) * 2) + 10;
+    New(666, cmdline, size, char);
+    strlcpy(cmdline, cmd, size);
+    strlcat(cmdline, " ", size);
     for (s = cmdline + strlen(cmdline); *filename; ) {
        *s++ = '\\';
        *s++ = *filename++;
     }
-    strcpy(s, " 2>&1");
+    strlcpy(s, " 2>&1", size);
     myfp = PerlProc_popen(cmdline, "r");
     Safefree(cmdline);
 
--- sv.c.old    2005-06-24 09:30:49.000000000 -0500
+++ sv.c        2005-06-27 09:30:01.173221440 -0500
@@ -3308,7 +3308,8 @@
        s = SvGROW_mutable(sv, len + 1);
        SvCUR_set(sv, len);
        SvPOKp_on(sv);
-       return strcpy(s, t);
+       (void)strlcpy(s,t,len + 1);
+       return s;
     }
 }
 
768c768,769
<       return strcpy(newaddr,pv);
---
>       (void)strlcpy(newaddr,pv,pvlen);
>       return newaddr;
814a816
>     int sz;
817,818c819,820
< 
<     newaddr = (char*)PerlMemShared_malloc(strlen(pv)+1);
---
>     sz = strlen(pv)+1;
>     newaddr = (char*)PerlMemShared_malloc(sz);
824c826,827
<     return strcpy(newaddr,pv);
---
>     (void)strlcpy(newaddr,pv,sz);
>     return newaddr;
2811c2814
<           strcat(tmpbuf, scriptname);
---
>           strlcat(tmpbuf, scriptname, MAXPATHLEN);
2843c2846,2847
<               cur = strcpy(tmpbuf, scriptname);
---
>               (void)strlcpy(tmpbuf, scriptname, MAXPATHLEN);
>               cur = tmpbuf;
4907a4912,4989
> #ifndef HAS_STRLCPY
> 
> /*
>  * =for apidoc strlcpy
>  *
>  * This function copies from C<src> to C<dst> up to a maximum 
>  * size of C<size>, and guarantees that C<dst> is NUL-terminated
>  * with a size no larger than C<size>.
>  *
>  * This function is included in Perl only when the system's libc
>  * does not already include a library function called
>  * C<strlcpy>.  Thanks to macros to redefine the function name, 
>  * C<my_strlcpy> should not be called directly.  C<strlcpy>
>  * should be called instead.
>  *
>  *  =cut
>  *  */
> 
> /*
>  * This code originally written by Russ Allberry for C<inn> and
>  * released in the public domain.  It was modified slightly for
>  * use within Perl.
>  */
> 
> size_t
> Perl_my_strlcpy(pTHX_ char *dst, const char *src, size_t size)
> {
>     size_t length, copy;
> 
>     length = strlen(src);
>     if (size > 0) {
>         copy = (length >= size) ? size - 1 : length;
>         memcpy(dst, src, copy);
>         dst[copy] = '\0';
>     }
>     return length;
> }
> #endif
> 
> #ifndef HAS_STRLCAT
> /*
>  * =for apidoc strlcpy
>  *
>  * This function concatenates C<src> to C<dst> up to a maximum
>  * size of C<size>, and guarantees that C<dst> is NUL-terminated
>  * with a size no larger than C<size>.
>  *
>  * This function is included in Perl only when the system's libc
>  * does not already include a library function called
>  * C<strlcat>.  Thanks to macros to redefine the function name,
>  * C<my_strlcat> should not be called directly.  C<strlcat>
>  * should be called instead.
>  *
>  *  =cut
>  *  */
> 
> /*
>  * This code originally written by Russ Allberry for C<inn> and
>  * released in the public domain.  It was modified slightly for
>  * use within Perl.
>  */
> 
> size_t
> Perl_my_strlcat(pTHX_ char *dst, const char *src, size_t size)
> {
>     size_t used, length, copy;
> 
>     used = strlen(dst);
>     length = strlen(src);
>     if (size > 0 && used < size - 1) {
>         copy = (length >= size - used) ? size - used - 1 : length;
>         memcpy(dst + used, src, copy);
>         dst[used + copy] = '\0';
>     }
>     return used + length;
> }
> #endif
> 

Reply via email to