X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Fstring.c;h=963948f77657bcb1cc88550662e4f648458cc09b;hb=b4b3528b6ffe0a1bd405893052f9ce0788e8d46b;hp=76e47f4184a061d71a2e8f1ad3b390348735319f;hpb=55414b25bee9f0195ccd1e47f3d3b5cba766e099;p=exim.git diff --git a/src/src/string.c b/src/src/string.c index 76e47f418..963948f77 100644 --- a/src/src/string.c +++ b/src/src/string.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2014 */ +/* Copyright (c) University of Cambridge 1995 - 2016 */ /* See the file NOTICE for conditions of use and distribution. */ /* Miscellaneous string-handling functions. Some are not required for @@ -717,8 +717,9 @@ uschar buffer[STRING_SPRINTF_BUFFER_SIZE]; va_start(ap, format); if (!string_vformat(buffer, sizeof(buffer), format, ap)) log_write(0, LOG_MAIN|LOG_PANIC_DIE, - "string_sprintf expansion was longer than " SIZE_T_FMT " (%s)", - sizeof(buffer), format); + "string_sprintf expansion was longer than " SIZE_T_FMT + "; format string was (%s)\nexpansion started '%.32s'", + sizeof(buffer), format, buffer); va_end(ap); return string_copy(buffer); } @@ -912,7 +913,7 @@ sep_is_special = iscntrl(sep); if (buffer != NULL) { - register int p = 0; + int p = 0; for (; *s != 0; s++) { if (*s == sep && (*(++s) != sep || sep_is_special)) break; @@ -951,7 +952,7 @@ else for (;;) { for (ss = s + 1; *ss != 0 && *ss != sep; ss++); - buffer = string_cat(buffer, &size, &ptr, s, ss-s); + buffer = string_catn(buffer, &size, &ptr, s, ss-s); s = ss; if (*s == 0 || *(++s) != sep || sep_is_special) break; } @@ -969,7 +970,7 @@ return buffer; #ifndef COMPILE_UTILITY /************************************************ -* Add element to seperated list * +* Add element to separated list * ************************************************/ /* This function is used to build a list, returning an allocated null-terminated growable string. The @@ -994,17 +995,17 @@ uschar * sp; if (list) { - new = string_cat(new, &sz, &off, list, Ustrlen(list)); - new = string_cat(new, &sz, &off, &sep, 1); + new = string_cat (new, &sz, &off, list); + new = string_catn(new, &sz, &off, &sep, 1); } while((sp = Ustrchr(ele, sep))) { - new = string_cat(new, &sz, &off, ele, sp-ele+1); - new = string_cat(new, &sz, &off, &sep, 1); + new = string_catn(new, &sz, &off, ele, sp-ele+1); + new = string_catn(new, &sz, &off, &sep, 1); ele = sp+1; } -new = string_cat(new, &sz, &off, ele, Ustrlen(ele)); +new = string_cat(new, &sz, &off, ele); new[off] = '\0'; return new; } @@ -1013,12 +1014,17 @@ return new; static const uschar * Ustrnchr(const uschar * s, int c, unsigned * len) { -while (*len) +unsigned siz = *len; +while (siz) { if (!*s) return NULL; - if (*s == c) return s; + if (*s == c) + { + *len = siz; + return s; + } s++; - *len--; + siz--; } return NULL; } @@ -1033,18 +1039,18 @@ const uschar * sp; if (list) { - new = string_cat(new, &sz, &off, list, Ustrlen(list)); - new = string_cat(new, &sz, &off, &sep, 1); + new = string_cat (new, &sz, &off, list); + new = string_catn(new, &sz, &off, &sep, 1); } while((sp = Ustrnchr(ele, sep, &len))) { - new = string_cat(new, &sz, &off, ele, sp-ele+1); - new = string_cat(new, &sz, &off, &sep, 1); + new = string_catn(new, &sz, &off, ele, sp-ele+1); + new = string_catn(new, &sz, &off, &sep, 1); ele = sp+1; len--; } -new = string_cat(new, &sz, &off, ele, len); +new = string_catn(new, &sz, &off, ele, len); new[off] = '\0'; return new; } @@ -1072,7 +1078,7 @@ Arguments: characters, updated to the new offset s points to characters to add count count of characters to add; must not exceed the length of s, if s - is a C string + is a C string. If -1 given, strlen(s) is used. If string is given as NULL, *size and *ptr should both be zero. @@ -1080,10 +1086,12 @@ Returns: pointer to the start of the string, changed if copied for expansion. Note that a NUL is not added, though space is left for one. This is because string_cat() is often called multiple times to build up a string - there's no point adding the NUL till the end. + */ +/* coverity[+alloc] */ uschar * -string_cat(uschar *string, int *size, int *ptr, const uschar *s, int count) +string_catn(uschar *string, int *size, int *ptr, const uschar *s, int count) { int p = *ptr; @@ -1126,12 +1134,25 @@ if (p + count >= *size) /* Because we always specify the exact number of characters to copy, we can use memcpy(), which is likely to be more efficient than strncopy() because the -latter has to check for zero bytes. */ +latter has to check for zero bytes. + +The Coverity annotation deals with the lack of correlated variable tracking; +common use is a null string and zero size and pointer, on first use for a +string being built. The "if" above then allocates, but Coverity assume that +the "if" might not happen and whines for a null-deref done by the memcpy(). */ +/* coverity[deref_parm_field_in_call] */ memcpy(string + p, s, count); *ptr = p + count; return string; } + + +uschar * +string_cat(uschar *string, int *size, int *ptr, const uschar *s) +{ +return string_catn(string, size, ptr, s, Ustrlen(s)); +} #endif /* COMPILE_UTILITY */ @@ -1169,7 +1190,7 @@ va_start(ap, count); for (i = 0; i < count; i++) { uschar *t = va_arg(ap, uschar *); - string = string_cat(string, size, ptr, t, Ustrlen(t)); + string = string_cat(string, size, ptr, t); } va_end(ap); @@ -1512,6 +1533,7 @@ specified messages. If it does, the message just gets truncated, and there doesn't seem much we can do about that. */ (void)string_vformat(buffer+15, sizeof(buffer) - 15, format, ap); +va_end(ap); return (eno == EACCES)? string_sprintf("%s: %s (euid=%ld egid=%ld)", buffer, strerror(eno), @@ -1542,14 +1564,35 @@ static uschar * string_get_localpart(address_item *addr, uschar *yield, int *sizeptr, int *ptrptr) { -if (testflag(addr, af_include_affixes) && addr->prefix != NULL) - yield = string_cat(yield, sizeptr, ptrptr, addr->prefix, - Ustrlen(addr->prefix)); -yield = string_cat(yield, sizeptr, ptrptr, addr->local_part, - Ustrlen(addr->local_part)); -if (testflag(addr, af_include_affixes) && addr->suffix != NULL) - yield = string_cat(yield, sizeptr, ptrptr, addr->suffix, - Ustrlen(addr->suffix)); +uschar * s; + +s = addr->prefix; +if (testflag(addr, af_include_affixes) && s) + { +#ifdef SUPPORT_I18N + if (testflag(addr, af_utf8_downcvt)) + s = string_localpart_utf8_to_alabel(s, NULL); +#endif + yield = string_cat(yield, sizeptr, ptrptr, s); + } + +s = addr->local_part; +#ifdef SUPPORT_I18N +if (testflag(addr, af_utf8_downcvt)) + s = string_localpart_utf8_to_alabel(s, NULL); +#endif +yield = string_cat(yield, sizeptr, ptrptr, s); + +s = addr->suffix; +if (testflag(addr, af_include_affixes) && s) + { +#ifdef SUPPORT_I18N + if (testflag(addr, af_utf8_downcvt)) + s = string_localpart_utf8_to_alabel(s, NULL); +#endif + yield = string_cat(yield, sizeptr, ptrptr, s); + } + return yield; } @@ -1598,7 +1641,7 @@ if (testflag(addr, af_pfr) || addr->transport != NULL && addr->transport->info->local)) { if (testflag(addr, af_file) && addr->local_part[0] != '/') - yield = string_cat(yield, &size, &ptr, CUS"save ", 5); + yield = string_catn(yield, &size, &ptr, CUS"save ", 5); yield = string_get_localpart(addr, yield, &size, &ptr); } @@ -1610,15 +1653,18 @@ else { if (addr->local_part != NULL) { + const uschar * s; yield = string_get_localpart(addr, yield, &size, &ptr); - yield = string_cat(yield, &size, &ptr, US"@", 1); - yield = string_cat(yield, &size, &ptr, addr->domain, - Ustrlen(addr->domain) ); + yield = string_catn(yield, &size, &ptr, US"@", 1); + s = addr->domain; +#ifdef SUPPORT_I18N + if (testflag(addr, af_utf8_downcvt)) + s = string_localpart_utf8_to_alabel(s, NULL); +#endif + yield = string_cat(yield, &size, &ptr, s); } else - { - yield = string_cat(yield, &size, &ptr, addr->address, Ustrlen(addr->address)); - } + yield = string_cat(yield, &size, &ptr, addr->address); yield[ptr] = 0; /* If the address we are going to print is the same as the top address, @@ -1645,28 +1691,24 @@ if ((all_parents || testflag(addr, af_pfr)) && address_item *addr2; for (addr2 = addr->parent; addr2 != topaddr; addr2 = addr2->parent) { - yield = string_cat(yield, &size, &ptr, s, 2); - yield = string_cat(yield, &size, &ptr, addr2->address, Ustrlen(addr2->address)); + yield = string_catn(yield, &size, &ptr, s, 2); + yield = string_cat (yield, &size, &ptr, addr2->address); if (!all_parents) break; s = US", "; } - yield = string_cat(yield, &size, &ptr, US")", 1); + yield = string_catn(yield, &size, &ptr, US")", 1); } /* Add the top address if it is required */ if (add_topaddr) { - yield = string_cat(yield, &size, &ptr, US" <", 2); + yield = string_catn(yield, &size, &ptr, US" <", 2); - if (addr->onetime_parent == NULL) - yield = string_cat(yield, &size, &ptr, topaddr->address, - Ustrlen(topaddr->address)); - else - yield = string_cat(yield, &size, &ptr, addr->onetime_parent, - Ustrlen(addr->onetime_parent)); + yield = string_cat(yield, &size, &ptr, + addr->onetime_parent ? addr->onetime_parent : topaddr->address); - yield = string_cat(yield, &size, &ptr, US">", 1); + yield = string_catn(yield, &size, &ptr, US">", 1); } yield[ptr] = 0; /* string_cat() leaves space */ @@ -1675,6 +1717,17 @@ return yield; #endif /* COMPILE_UTILITY */ +#ifndef COMPILE_UTILITY +/* qsort(3), currently used to sort the environment variables +for -bP environment output, needs a function to compare two pointers to string +pointers. Here it is. */ + +int +string_compare_by_pointer(const void *a, const void *b) +{ +return Ustrcmp(* CUSS a, * CUSS b); +} +#endif /* COMPILE_UTILITY */