LCOV - code coverage report
Current view: top level - lib/util - substitute.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 84 109 77.1 %
Date: 2024-04-13 12:30:31 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Samba utility functions
       4             :    
       5             :    Copyright (C) Andrew Tridgell 1992-2001
       6             :    Copyright (C) Simo Sorce      2001-2002
       7             :    Copyright (C) Martin Pool     2003
       8             :    Copyright (C) James Peach     2005
       9             :    
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             :    
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             :    
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "replace.h"
      25             : #include "debug.h"
      26             : #ifndef SAMBA_UTIL_CORE_ONLY
      27             : #include "charset/charset.h"
      28             : #else
      29             : #include "charset_compat.h"
      30             : #endif
      31             : #include "substitute.h"
      32             : 
      33             : /**
      34             :  * @file
      35             :  * @brief Substitute utilities.
      36             :  **/
      37             : 
      38             : /**
      39             :  Substitute a string for a pattern in another string. Make sure there is
      40             :  enough room!
      41             : 
      42             :  This routine looks for pattern in s and replaces it with
      43             :  insert. It may do multiple replacements or just one.
      44             : 
      45             :  Any of " ; ' $ or ` in the insert string are replaced with _
      46             :  if len==0 then the string cannot be extended. This is different from the old
      47             :  use of len==0 which was for no length checks to be done.
      48             : **/
      49             : 
      50           5 : static void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
      51             :                         bool remove_unsafe_characters, bool replace_once,
      52             :                         bool allow_trailing_dollar)
      53             : {
      54           5 :         char *p;
      55           5 :         size_t ls, lp, li, i;
      56             : 
      57           5 :         if (!insert || !pattern || !*pattern || !s)
      58           0 :                 return;
      59             : 
      60           5 :         ls = strlen(s);
      61           5 :         lp = strlen(pattern);
      62           5 :         li = strlen(insert);
      63             : 
      64           5 :         if (len == 0)
      65           0 :                 len = ls + 1; /* len is number of *bytes* */
      66             : 
      67          11 :         while (lp <= ls && (p = strstr_m(s,pattern))) {
      68           6 :                 if (ls + li - lp >= len) {
      69           0 :                         DBG_ERR("ERROR: string overflow by "
      70             :                                 "%zu in string_sub(%.50s, %zu)\n",
      71             :                                 ls + li - lp + 1 - len,
      72             :                                 pattern,
      73             :                                 len);
      74           0 :                         break;
      75             :                 }
      76           6 :                 if (li != lp) {
      77           3 :                         memmove(p+li,p+lp,strlen(p+lp)+1);
      78             :                 }
      79          25 :                 for (i=0;i<li;i++) {
      80          19 :                         switch (insert[i]) {
      81           0 :                         case '$':
      82             :                                 /* allow a trailing $
      83             :                                  * (as in machine accounts) */
      84           0 :                                 if (allow_trailing_dollar && (i == li - 1 )) {
      85           0 :                                         p[i] = insert[i];
      86           0 :                                         break;
      87             :                                 }
      88           2 :                                 FALL_THROUGH;
      89             :                         case '`':
      90             :                         case '"':
      91             :                         case '\'':
      92             :                         case ';':
      93             :                         case '%':
      94             :                         case '\r':
      95             :                         case '\n':
      96           2 :                                 if ( remove_unsafe_characters ) {
      97           2 :                                         p[i] = '_';
      98             :                                         /* yes this break should be here
      99             :                                          * since we want to fall throw if
     100             :                                          * not replacing unsafe chars */
     101           2 :                                         break;
     102             :                                 }
     103          17 :                                 FALL_THROUGH;
     104             :                         default:
     105          17 :                                 p[i] = insert[i];
     106             :                         }
     107             :                 }
     108           6 :                 s = p + li;
     109           6 :                 ls = ls + li - lp;
     110             : 
     111           6 :                 if (replace_once)
     112           0 :                         break;
     113             :         }
     114             : }
     115             : 
     116           5 : void string_sub(char *s,const char *pattern, const char *insert, size_t len)
     117             : {
     118           5 :         string_sub2( s, pattern, insert, len, true, false, false );
     119           5 : }
     120             : 
     121             : /**
     122             :  Similar to string_sub() but allows for any character to be substituted. 
     123             :  Use with caution!
     124             :  if len==0 then the string cannot be extended. This is different from the old
     125             :  use of len==0 which was for no length checks to be done.
     126             : **/
     127             : 
     128      102425 : _PUBLIC_ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
     129             : {
     130        1639 :         char *p;
     131        1639 :         size_t ls,lp,li;
     132             : 
     133      102425 :         if (!insert || !pattern || !s)
     134           0 :                 return;
     135             : 
     136      102425 :         ls = strlen(s);
     137      102425 :         lp = strlen(pattern);
     138      102425 :         li = strlen(insert);
     139             : 
     140      102425 :         if (!*pattern)
     141           0 :                 return;
     142             : 
     143      102425 :         if (len == 0)
     144      102425 :                 len = ls + 1; /* len is number of *bytes* */
     145             : 
     146      104515 :         while (lp <= ls && (p = strstr_m(s,pattern))) {
     147        2090 :                 if (ls + li - lp >= len) {
     148           0 :                         DBG_ERR("ERROR: string overflow by "
     149             :                                 "%zu in all_string_sub(%.50s, %zu)\n",
     150             :                                 ls + li - lp + 1 - len,
     151             :                                 pattern,
     152             :                                 len);
     153           0 :                         break;
     154             :                 }
     155        2090 :                 if (li != lp) {
     156          98 :                         memmove(p+li,p+lp,strlen(p+lp)+1);
     157             :                 }
     158        2090 :                 memcpy(p, insert, li);
     159        2090 :                 s = p + li;
     160        2090 :                 ls = ls + li - lp;
     161             :         }
     162             : }
     163             : 
     164             : /*
     165             :  * Internal guts of talloc_string_sub and talloc_all_string_sub.
     166             :  * talloc version of string_sub2.
     167             :  */
     168             : 
     169      285905 : char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
     170             :                         const char *pattern,
     171             :                         const char *insert,
     172             :                         bool remove_unsafe_characters,
     173             :                         bool replace_once,
     174             :                         bool allow_trailing_dollar)
     175             : {
     176         129 :         char *p, *in;
     177         129 :         char *s;
     178         129 :         char *string;
     179         129 :         ssize_t ls,lp,li,ld, i;
     180             : 
     181      285905 :         if (!insert || !pattern || !*pattern || !src) {
     182           0 :                 return NULL;
     183             :         }
     184             : 
     185      285905 :         string = talloc_strdup(mem_ctx, src);
     186      285905 :         if (string == NULL) {
     187           0 :                 DEBUG(0, ("talloc_string_sub2: "
     188             :                         "talloc_strdup failed\n"));
     189           0 :                 return NULL;
     190             :         }
     191             : 
     192      285905 :         s = string;
     193             : 
     194      285905 :         in = talloc_strdup(mem_ctx, insert);
     195      285905 :         if (!in) {
     196           0 :                 DEBUG(0, ("talloc_string_sub2: ENOMEM\n"));
     197           0 :                 talloc_free(string);
     198           0 :                 return NULL;
     199             :         }
     200      285905 :         ls = (ssize_t)strlen(s);
     201      285905 :         lp = (ssize_t)strlen(pattern);
     202      285905 :         li = (ssize_t)strlen(insert);
     203      285905 :         ld = li - lp;
     204             : 
     205     2268318 :         for (i=0;i<li;i++) {
     206     1982413 :                 switch (in[i]) {
     207         182 :                         case '$':
     208             :                                 /* allow a trailing $
     209             :                                  * (as in machine accounts) */
     210         182 :                                 if (allow_trailing_dollar && (i == li - 1 )) {
     211           0 :                                         break;
     212             :                                 }
     213             : 
     214           0 :                                 FALL_THROUGH;
     215             :                         case '`':
     216             :                         case '"':
     217             :                         case '\'':
     218             :                         case ';':
     219             :                         case '%':
     220             :                         case '\r':
     221             :                         case '\n':
     222         182 :                                 if (remove_unsafe_characters) {
     223         100 :                                         in[i] = '_';
     224         100 :                                         break;
     225             :                                 }
     226             : 
     227             :                                 FALL_THROUGH;
     228             :                         default:
     229             :                                 /* ok */
     230     1981344 :                                 break;
     231             :                 }
     232             :         }
     233             : 
     234      497177 :         while ((p = strstr_m(s,pattern))) {
     235      211272 :                 if (ld > 0) {
     236      208480 :                         int offset = PTR_DIFF(s,string);
     237      208480 :                         string = (char *)talloc_realloc_size(mem_ctx, string,
     238             :                                                         ls + ld + 1);
     239      208480 :                         if (!string) {
     240           0 :                                 DEBUG(0, ("talloc_string_sub: out of "
     241             :                                           "memory!\n"));
     242           0 :                                 TALLOC_FREE(in);
     243           0 :                                 return NULL;
     244             :                         }
     245      208480 :                         p = string + offset + (p - s);
     246             :                 }
     247      211272 :                 if (li != lp) {
     248      210354 :                         memmove(p+li,p+lp,strlen(p+lp)+1);
     249             :                 }
     250      211272 :                 memcpy(p, in, li);
     251      211272 :                 s = p + li;
     252      211272 :                 ls += ld;
     253             : 
     254      211272 :                 if (replace_once) {
     255           0 :                         break;
     256             :                 }
     257             :         }
     258      285905 :         TALLOC_FREE(in);
     259      285905 :         return string;
     260             : }
     261             : 
     262             : /* Same as string_sub, but returns a talloc'ed string */
     263             : 
     264      219709 : char *talloc_string_sub(TALLOC_CTX *mem_ctx,
     265             :                         const char *src,
     266             :                         const char *pattern,
     267             :                         const char *insert)
     268             : {
     269      219709 :         return talloc_string_sub2(mem_ctx, src, pattern, insert,
     270             :                         true, false, false);
     271             : }
     272             : 
     273       62124 : char *talloc_all_string_sub(TALLOC_CTX *ctx,
     274             :                                 const char *src,
     275             :                                 const char *pattern,
     276             :                                 const char *insert)
     277             : {
     278       62124 :         return talloc_string_sub2(ctx, src, pattern, insert,
     279             :                         false, false, false);
     280             : }

Generated by: LCOV version 1.14