locale.c: Don't be too clever in strlcat
authorKarl Williamson <khw@cpan.org>
Sat, 22 Jul 2017 18:44:16 +0000 (12:44 -0600)
committerKarl Williamson <khw@cpan.org>
Sun, 10 Sep 2017 05:05:11 +0000 (23:05 -0600)
This code I wrote was attempting to avoid multiple calls to strlen in
constructing the catenation of various components of a string.  It did
this by keeping track of how far it got each iteration, and using that
as a starting point for the next.  I now realize that the return value
of strlcat is as if it succeeds, even if there isn't enough room.  That
means that if there were a problem, this could start out an iteration
such that it would be writing beyond the end of the buffer.  It is safer
to not do this, so this commit removes it.

The use of strlcat is a safety measure, as there should be a sufficient
amount of space calculated for things to fit, so there is no bug here.
But one should be safe.

locale.c

index 320de17..f8c0270 100644 (file)
--- a/locale.c
+++ b/locale.c
@@ -2228,7 +2228,6 @@ Perl__mem_collxfrm(pTHX_ const char *input_string,
         char * e = s + len;
         char * sans_nuls;
         STRLEN sans_nuls_len;
-        STRLEN sans_nuls_pos;
         int try_non_controls;
         char this_replacement_char[] = "?\0";   /* Room for a two-byte string,
                                                    making sure 2nd byte is NUL.
@@ -2347,19 +2346,14 @@ Perl__mem_collxfrm(pTHX_ const char *input_string,
         sans_nuls_len = (len * this_replacement_len) + 1;
         Newx(sans_nuls, sans_nuls_len, char);
         *sans_nuls = '\0';
-        sans_nuls_pos = 0;
 
         /* Replace each NUL with the lowest collating control.  Loop until have
          * exhausted all the NULs */
         while (s + s_strlen < e) {
-            sans_nuls_pos = my_strlcat(sans_nuls + sans_nuls_pos,
-                                       s,
-                                       sans_nuls_len);
+            my_strlcat(sans_nuls, s, sans_nuls_len);
 
             /* Do the actual replacement */
-            sans_nuls_pos = my_strlcat(sans_nuls + sans_nuls_pos,
-                                       this_replacement_char,
-                                       sans_nuls_len);
+            my_strlcat(sans_nuls, this_replacement_char, sans_nuls_len);
 
             /* Move past the input NUL */
             s += s_strlen + 1;
@@ -2367,7 +2361,7 @@ Perl__mem_collxfrm(pTHX_ const char *input_string,
         }
 
         /* And add anything that trails the final NUL */
-        my_strlcat(sans_nuls + sans_nuls_pos, s, sans_nuls_len);
+        my_strlcat(sans_nuls, s, sans_nuls_len);
 
         /* Switch so below we transform this modified string */
         s = sans_nuls;