git://git.exim.org
/
exim.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Fix buffer overflow in string_vformat. Bug 2449
[exim.git]
/
src
/
src
/
string.c
diff --git
a/src/src/string.c
b/src/src/string.c
index d0b8db4ae52bfa834b834c03aed9536364c4438e..3445f8a42ebe678266ae26c2255bc611b47986e6 100644
(file)
--- a/
src/src/string.c
+++ b/
src/src/string.c
@@
-224,6
+224,8
@@
interpreted in strings.
Arguments:
pp points a pointer to the initiating "\" in the string;
the pointer gets updated to point to the final character
Arguments:
pp points a pointer to the initiating "\" in the string;
the pointer gets updated to point to the final character
+ If the backslash is the last character in the string, it
+ is not interpreted.
Returns: the value of the character escape
*/
Returns: the value of the character escape
*/
@@
-236,6
+238,7
@@
const uschar *hex_digits= CUS"0123456789abcdef";
int ch;
const uschar *p = *pp;
ch = *(++p);
int ch;
const uschar *p = *pp;
ch = *(++p);
+if (ch == '\0') return **pp;
if (isdigit(ch) && ch != '8' && ch != '9')
{
ch -= '0';
if (isdigit(ch) && ch != '8' && ch != '9')
{
ch -= '0';
@@
-651,18
+654,16
@@
uschar *t, *yield;
/* First find the end of the string */
if (*s != '\"')
/* First find the end of the string */
if (*s != '\"')
- {
while (*s != 0 && !isspace(*s)) s++;
while (*s != 0 && !isspace(*s)) s++;
- }
else
{
s++;
else
{
s++;
- while (*s
!= 0
&& *s != '\"')
+ while (*s && *s != '\"')
{
if (*s == '\\') (void)string_interpret_escape(&s);
s++;
}
{
if (*s == '\\') (void)string_interpret_escape(&s);
s++;
}
- if (*s
!= 0
) s++;
+ if (*s) s++;
}
/* Get enough store to copy into */
}
/* Get enough store to copy into */
@@
-907,7
+908,7
@@
int sep = *separator;
const uschar *s = *listptr;
BOOL sep_is_special;
const uschar *s = *listptr;
BOOL sep_is_special;
-if (
s == NULL
) return NULL;
+if (
!s
) return NULL;
/* This allows for a fixed specified separator to be an iscntrl() character,
but at the time of implementation, this is never the case. However, it's best
/* This allows for a fixed specified separator to be an iscntrl() character,
but at the time of implementation, this is never the case. However, it's best
@@
-923,19
+924,17
@@
if (sep <= 0)
if (*s == '<' && (ispunct(s[1]) || iscntrl(s[1])))
{
sep = s[1];
if (*s == '<' && (ispunct(s[1]) || iscntrl(s[1])))
{
sep = s[1];
-
s += 2
;
+
if (*++s) ++s
;
while (isspace(*s) && *s != sep) s++;
}
else
while (isspace(*s) && *s != sep) s++;
}
else
- {
- sep = (sep == 0)? ':' : -sep;
- }
+ sep = sep ? -sep : ':';
*separator = sep;
}
/* An empty string has no list elements */
*separator = sep;
}
/* An empty string has no list elements */
-if (
*s == 0
) return NULL;
+if (
!*s
) return NULL;
/* Note whether whether or not the separator is an iscntrl() character. */
/* Note whether whether or not the separator is an iscntrl() character. */
@@
-946,13
+945,13
@@
sep_is_special = iscntrl(sep);
if (buffer)
{
int p = 0;
if (buffer)
{
int p = 0;
- for (; *s
!= 0
; s++)
+ for (; *s; s++)
{
if (*s == sep && (*(++s) != sep || sep_is_special)) break;
if (p < buflen - 1) buffer[p++] = *s;
}
while (p > 0 && isspace(buffer[p-1])) p--;
{
if (*s == sep && (*(++s) != sep || sep_is_special)) break;
if (p < buflen - 1) buffer[p++] = *s;
}
while (p > 0 && isspace(buffer[p-1])) p--;
- buffer[p] =
0
;
+ buffer[p] =
'\0'
;
}
/* Handle the case when a buffer is not provided. */
}
/* Handle the case when a buffer is not provided. */
@@
-982,10
+981,10
@@
else
for (;;)
{
for (;;)
{
- for (ss = s + 1; *ss
!= 0
&& *ss != sep; ss++) ;
+ for (ss = s + 1; *ss && *ss != sep; ss++) ;
g = string_catn(g, s, ss-s);
s = ss;
g = string_catn(g, s, ss-s);
s = ss;
- if (
*s == 0 || *(++s)
!= sep || sep_is_special) break;
+ if (
!*s || *++s
!= sep || sep_is_special) break;
}
while (g->ptr > 0 && isspace(g->s[g->ptr-1])) g->ptr--;
buffer = string_from_gstring(g);
}
while (g->ptr > 0 && isspace(g->s[g->ptr-1])) g->ptr--;
buffer = string_from_gstring(g);
@@
-1133,7
+1132,7
@@
store_reset(g->s + (g->size = g->ptr + 1));
Arguments:
g the growable-string
p current end of data
Arguments:
g the growable-string
p current end of data
- count amount to grow by
+ count amount to grow by
, offset from p
*/
static void
*/
static void
@@
-1214,8
+1213,8
@@
memcpy(g->s + p, s, count);
g->ptr = p + count;
return g;
}
g->ptr = p + count;
return g;
}
-
-
+
+
gstring *
string_cat(gstring *string, const uschar *s)
{
gstring *
string_cat(gstring *string, const uschar *s)
{
@@
-1358,7
+1357,11
@@
while (*fp)
{
/* Avoid string_copyn() due to COMPILE_UTILITY */
if (g->ptr >= lim - 1)
{
/* Avoid string_copyn() due to COMPILE_UTILITY */
if (g->ptr >= lim - 1)
- if (extend) gstring_grow(g, g->ptr, 1); else return NULL;
+ {
+ if (!extend) return NULL;
+ gstring_grow(g, g->ptr, 1);
+ lim = g->size - 1;
+ }
g->s[g->ptr++] = (uschar) *fp++;
continue;
}
g->s[g->ptr++] = (uschar) *fp++;
continue;
}
@@
-1426,7
+1429,12
@@
while (*fp)
case 'X':
width = length > L_LONG ? 24 : 12;
if (g->ptr >= lim - width)
case 'X':
width = length > L_LONG ? 24 : 12;
if (g->ptr >= lim - width)
- if (extend) gstring_grow(g, g->ptr, width); else return NULL;
+ {
+ if (!extend) return NULL;
+ gstring_grow(g, g->ptr, width);
+ lim = g->size - 1;
+ gp = CS g->s + g->ptr;
+ }
strncpy(newformat, item_start, fp - item_start);
newformat[fp - item_start] = 0;
strncpy(newformat, item_start, fp - item_start);
newformat[fp - item_start] = 0;
@@
-1451,7
+1459,12
@@
while (*fp)
{
void * ptr;
if (g->ptr >= lim - 24)
{
void * ptr;
if (g->ptr >= lim - 24)
- if (extend) gstring_grow(g, g->ptr, 24); else return NULL;
+ {
+ if (!extend) return NULL;
+ gstring_grow(g, g->ptr, 24);
+ lim = g->size - 1;
+ gp = CS g->s + g->ptr;
+ }
/* sprintf() saying "(nil)" for a null pointer seems unreliable.
Handle it explicitly. */
if ((ptr = va_arg(ap, void *)))
/* sprintf() saying "(nil)" for a null pointer seems unreliable.
Handle it explicitly. */
if ((ptr = va_arg(ap, void *)))
@@
-1479,7
+1492,12
@@
while (*fp)
case 'G':
if (precision < 0) precision = 6;
if (g->ptr >= lim - precision - 8)
case 'G':
if (precision < 0) precision = 6;
if (g->ptr >= lim - precision - 8)
- if (extend) gstring_grow(g, g->ptr, precision+8); else return NULL;
+ {
+ if (!extend) return NULL;
+ gstring_grow(g, g->ptr, precision+8);
+ lim = g->size - 1;
+ gp = CS g->s + g->ptr;
+ }
strncpy(newformat, item_start, fp - item_start);
newformat[fp-item_start] = 0;
if (length == L_LONGDOUBLE)
strncpy(newformat, item_start, fp - item_start);
newformat[fp-item_start] = 0;
if (length == L_LONGDOUBLE)
@@
-1492,13
+1510,21
@@
while (*fp)
case '%':
if (g->ptr >= lim - 1)
case '%':
if (g->ptr >= lim - 1)
- if (extend) gstring_grow(g, g->ptr, 1); else return NULL;
+ {
+ if (!extend) return NULL;
+ gstring_grow(g, g->ptr, 1);
+ lim = g->size - 1;
+ }
g->s[g->ptr++] = (uschar) '%';
break;
case 'c':
if (g->ptr >= lim - 1)
g->s[g->ptr++] = (uschar) '%';
break;
case 'c':
if (g->ptr >= lim - 1)
- if (extend) gstring_grow(g, g->ptr, 1); else return NULL;
+ {
+ if (!extend) return NULL;
+ gstring_grow(g, g->ptr, 1);
+ lim = g->size - 1;
+ }
g->s[g->ptr++] = (uschar) va_arg(ap, int);
break;
g->s[g->ptr++] = (uschar) va_arg(ap, int);
break;
@@
-1563,7
+1589,11
@@
while (*fp)
}
}
else if (g->ptr >= lim - width)
}
}
else if (g->ptr >= lim - width)
+ {
gstring_grow(g, g->ptr, width);
gstring_grow(g, g->ptr, width);
+ lim = g->size - 1;
+ gp = CS g->s + g->ptr;
+ }
g->ptr += sprintf(gp, "%*.*s", width, precision, s);
if (fp[-1] == 'S')
g->ptr += sprintf(gp, "%*.*s", width, precision, s);
if (fp[-1] == 'S')