1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00
samba-mirror/lib/util/substitute.c
Martin Schwenke 9d90ac352d util: Fix off-by-one error in message about overflow
len includes space for the NUL character, so the calculation needs to
take the NUL character into account.

While touching this, drop unnecessary casts by updating format string
and update to modern debug macro.

Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>

Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Fri Jul  5 02:24:52 UTC 2019 on sn-devel-184
2019-07-05 02:24:52 +00:00

212 lines
4.8 KiB
C

/*
Unix SMB/CIFS implementation.
Samba utility functions
Copyright (C) Andrew Tridgell 1992-2001
Copyright (C) Simo Sorce 2001-2002
Copyright (C) Martin Pool 2003
Copyright (C) James Peach 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "replace.h"
#include "debug.h"
#ifndef SAMBA_UTIL_CORE_ONLY
#include "charset/charset.h"
#else
#include "charset_compat.h"
#endif
#include "substitute.h"
/**
* @file
* @brief Substitute utilities.
**/
/**
Substitute a string for a pattern in another string. Make sure there is
enough room!
This routine looks for pattern in s and replaces it with
insert. It may do multiple replacements or just one.
Any of " ; ' $ or ` in the insert string are replaced with _
if len==0 then the string cannot be extended. This is different from the old
use of len==0 which was for no length checks to be done.
**/
static void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
bool remove_unsafe_characters, bool replace_once,
bool allow_trailing_dollar)
{
char *p;
size_t ls, lp, li, i;
if (!insert || !pattern || !*pattern || !s)
return;
ls = strlen(s);
lp = strlen(pattern);
li = strlen(insert);
if (len == 0)
len = ls + 1; /* len is number of *bytes* */
while (lp <= ls && (p = strstr_m(s,pattern))) {
if (ls + li - lp >= len) {
DBG_ERR("ERROR: string overflow by "
"%zu in string_sub(%.50s, %zu)\n",
ls + li - lp + 1 - len,
pattern,
len);
break;
}
if (li != lp) {
memmove(p+li,p+lp,strlen(p+lp)+1);
}
for (i=0;i<li;i++) {
switch (insert[i]) {
case '$':
/* allow a trailing $
* (as in machine accounts) */
if (allow_trailing_dollar && (i == li - 1 )) {
p[i] = insert[i];
break;
}
FALL_THROUGH;
case '`':
case '"':
case '\'':
case ';':
case '%':
case '\r':
case '\n':
if ( remove_unsafe_characters ) {
p[i] = '_';
/* yes this break should be here
* since we want to fall throw if
* not replacing unsafe chars */
break;
}
FALL_THROUGH;
default:
p[i] = insert[i];
}
}
s = p + li;
ls = ls + li - lp;
if (replace_once)
break;
}
}
void string_sub_once(char *s, const char *pattern,
const char *insert, size_t len)
{
string_sub2( s, pattern, insert, len, true, true, false );
}
void string_sub(char *s,const char *pattern, const char *insert, size_t len)
{
string_sub2( s, pattern, insert, len, true, false, false );
}
/**
* Talloc'ed version of string_sub
*/
_PUBLIC_ char *string_sub_talloc(TALLOC_CTX *mem_ctx, const char *s,
const char *pattern, const char *insert)
{
const char *p;
char *ret;
size_t len, alloc_len;
if (insert == NULL || pattern == NULL || !*pattern || s == NULL)
return NULL;
/* determine length needed */
len = strlen(s);
for (p = strstr(s, pattern); p != NULL;
p = strstr(p+strlen(pattern), pattern)) {
len += strlen(insert) - strlen(pattern);
}
alloc_len = MAX(len, strlen(s))+1;
ret = talloc_array(mem_ctx, char, alloc_len);
if (ret == NULL)
return NULL;
strncpy(ret, s, alloc_len);
string_sub(ret, pattern, insert, alloc_len);
ret = talloc_realloc(mem_ctx, ret, char, len+1);
if (ret == NULL)
return NULL;
if (ret[len] != '\0') {
DEBUG(0,("Internal error at %s(%d): string not terminated\n",
__FILE__, __LINE__));
abort();
}
talloc_set_name_const(ret, ret);
return ret;
}
/**
Similar to string_sub() but allows for any character to be substituted.
Use with caution!
if len==0 then the string cannot be extended. This is different from the old
use of len==0 which was for no length checks to be done.
**/
_PUBLIC_ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
{
char *p;
size_t ls,lp,li;
if (!insert || !pattern || !s)
return;
ls = strlen(s);
lp = strlen(pattern);
li = strlen(insert);
if (!*pattern)
return;
if (len == 0)
len = ls + 1; /* len is number of *bytes* */
while (lp <= ls && (p = strstr_m(s,pattern))) {
if (ls + li - lp >= len) {
DBG_ERR("ERROR: string overflow by "
"%zu in all_string_sub(%.50s, %zu)\n",
ls + li - lp + 1 - len,
pattern,
len);
break;
}
if (li != lp) {
memmove(p+li,p+lp,strlen(p+lp)+1);
}
memcpy(p, insert, li);
s = p + li;
ls = ls + li - lp;
}
}