Move errno-protection into string_open_failed()
[exim.git] / src / src / string.c
index 9f1aeb81db5a9d435ac9235653700acf7aa56ca2..1b08e7fb8a58a856a72dd3ec276e2402c9e5a64d 100644 (file)
@@ -3,6 +3,7 @@
 *************************************************/
 
 /* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Miscellaneous string-handling functions. Some are not required for
@@ -12,7 +13,6 @@ utilities and tests, and are cut out by the COMPILE_UTILITY macro. */
 #include "exim.h"
 #include <assert.h>
 
-static void gstring_rebuffer(gstring * g);
 
 #ifndef COMPILE_UTILITY
 /*************************************************
@@ -575,18 +575,14 @@ uschar *ss = yield = store_get(Ustrlen(s) + 1, is_tainted(s));
 while (*s != 0)
   {
   if (*s != '\\')
-    {
     *ss++ = *s++;
-    }
   else if (isdigit(s[1]))
     {
     *ss++ = (s[1] - '0')*100 + (s[2] - '0')*10 + s[3] - '0';
     s += 4;
     }
   else if (*(++s) != 0)
-    {
     *ss++ = *s++;
-    }
   }
 
 *ss = 0;
@@ -864,7 +860,8 @@ Returns:     pointer to buffer, containing the next substring,
 */
 
 uschar *
-string_nextinlist(const uschar **listptr, int *separator, uschar *buffer, int buflen)
+string_nextinlist_trc(const uschar **listptr, int *separator, uschar *buffer, int buflen,
+ const uschar * func, int line)
 {
 int sep = *separator;
 const uschar *s = *listptr;
@@ -907,6 +904,8 @@ sep_is_special = iscntrl(sep);
 if (buffer)
   {
   int p = 0;
+  if (is_tainted(s) && !is_tainted(buffer))
+    die_tainted(US"string_nextinlist", func, line);
   for (; *s; s++)
     {
     if (*s == sep && (*(++s) != sep || sep_is_special)) break;
@@ -928,14 +927,11 @@ else
   start of a string. Avoid getting working memory for an empty item. */
 
   if (*s == sep)
-    {
-    s++;
-    if (*s != sep || sep_is_special)
+    if (*++s != sep || sep_is_special)
       {
       *listptr = s;
       return string_copy(US"");
       }
-    }
 
   /* Not an empty string; the first character is guaranteed to be a data
   character. */
@@ -1243,16 +1239,6 @@ return !!gp;
 
 
 
-/* Copy the content of a string to tainted memory */
-static void
-gstring_rebuffer(gstring * g)
-{
-uschar * s = store_get(g->size, TRUE);
-memcpy(s, g->s, g->ptr);
-g->s = s;
-}
-
-
 
 /* Build or append to a growing-string, sprintf-style.
 
@@ -1626,7 +1612,6 @@ string supplied as data, adds the strerror() text, and if the failure was
 "Permission denied", reads and includes the euid and egid.
 
 Arguments:
-  eno           the value of errno after the failure
   format        a text format string - deliberately not uschar *
   ...           arguments for the format string
 
@@ -1634,7 +1619,7 @@ Returns:        a message, in dynamic store
 */
 
 uschar *
-string_open_failed_trc(int eno, const uschar * func, unsigned line,
+string_open_failed_trc(const uschar * func, unsigned line,
   const char *format, ...)
 {
 va_list ap;
@@ -1649,23 +1634,27 @@ doesn't seem much we can do about that. */
 
 va_start(ap, format);
 (void) string_vformat_trc(g, func, line, STRING_SPRINTF_BUFFER_SIZE,
-       0, format, ap);
-string_from_gstring(g);
-gstring_release_unused(g);
+       SVFMT_REBUFFER, format, ap);
 va_end(ap);
 
-return eno == EACCES
-  ? string_sprintf("%s: %s (euid=%ld egid=%ld)", g->s, strerror(eno),
-    (long int)geteuid(), (long int)getegid())
-  : string_sprintf("%s: %s", g->s, strerror(eno));
+g = string_catn(g, US": ", 2);
+g = string_cat(g, US strerror(errno));
+
+if (errno == EACCES)
+  {
+  int save_errno = errno;
+  g = string_fmt_append(g, " (euid=%ld egid=%ld)",
+    (long int)geteuid(), (long int)getegid());
+  errno = save_errno;
+  }
+gstring_release_unused(g);
+return string_from_gstring(g);
 }
-#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. */