Remove attempts to quieten compiler static-checking
[exim.git] / src / src / store.c
index a8f5a07fcecfaaacced5c588d0eadc6ec7634fe6..47d6f9106cc1acc9a85cc5760234a69e2bc7ef6e 100644 (file)
@@ -3,7 +3,7 @@
 *************************************************/
 
 /* Copyright (c) University of Cambridge 1995 - 2018 */
 *************************************************/
 
 /* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim maintainers 2019 */
+/* Copyright (c) The Exim maintainers 2019 - 2020 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Exim gets and frees all its store through these functions. In the original
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Exim gets and frees all its store through these functions. In the original
@@ -50,17 +50,16 @@ The following different types of store are recognized:
   would be avoided.
 
   Intermediate layers (eg. the string functions) can test for taint, and use this
   would be avoided.
 
   Intermediate layers (eg. the string functions) can test for taint, and use this
-  for ensuringn that results have proper state.  For example the
+  for ensurinng that results have proper state.  For example the
   string_vformat_trc() routing supporting the string_sprintf() interface will
   recopy a string being built into a tainted allocation if it meets a %s for a
   string_vformat_trc() routing supporting the string_sprintf() interface will
   recopy a string being built into a tainted allocation if it meets a %s for a
-  tainted argument.
-
-  Internally we currently use malloc for nontainted pools, and mmap for tainted
-  pools.  The disparity is for speed of testing the taintedness of pointers;
-  because Linux appears to use distinct non-overlapping address allocations for
-  mmap vs. everything else, which means only two pointer-compares suffice for the
-  test.  Other OS' cannot use that optimisation, and a more lengthy test against
-  the limits of tainted-pool allcations has to be done.
+  tainted argument.  Any intermediate-layer function that (can) return a new
+  allocation should behave this way; returning a tainted result if any tainted
+  content is used.  Intermediate-layer functions (eg. Ustrncpy) that modify
+  existing allocations fail if tainted data is written into an untainted area.
+  Users of functions that modify existing allocations should check if a tainted
+  source and an untainted destination is used, and fail instead (sprintf() being
+  the classic case).
 */
 
 
 */
 
 
@@ -120,13 +119,6 @@ static storeblock *current_block[NPOOLS];
 static void *next_yield[NPOOLS];
 static int yield_length[NPOOLS] = { -1, -1, -1,  -1, -1, -1 };
 
 static void *next_yield[NPOOLS];
 static int yield_length[NPOOLS] = { -1, -1, -1,  -1, -1, -1 };
 
-/* The limits of the tainted pools.  Tracking these on new allocations enables
-a fast is_tainted implementation. We assume the kernel only allocates mmaps using
-one side or the other of data+heap, not both. */
-
-void * tainted_base = (void *)-1;
-void * tainted_top = (void *)0;
-
 /* pool_malloc holds the amount of memory used by the store pools; this goes up
 and down as store is reset or released. nonpool_malloc is the total got by
 malloc from other calls; this doesn't go down because it is just freed by
 /* pool_malloc holds the amount of memory used by the store pools; this goes up
 and down as store is reset or released. nonpool_malloc is the total got by
 malloc from other calls; this doesn't go down because it is just freed by
@@ -173,42 +165,40 @@ static const uschar * poolclass[NPOOLS] = {
 #endif
 
 
 #endif
 
 
-static void * store_mmap(int, const char *, int);
 static void * internal_store_malloc(int, const char *, int);
 static void * internal_store_malloc(int, const char *, int);
-static void   internal_untainted_free(void *, const char *, int linenumber);
-static void   internal_tainted_free(storeblock *, const char *, int linenumber);
+static void   internal_store_free(void *, const char *, int linenumber);
 
 /******************************************************************************/
 
 
 /******************************************************************************/
 
-#ifndef TAINT_CHECK_FAST
-/* Slower version check, for use when platform intermixes malloc and mmap area
-addresses. */
+/* Test if a pointer refers to tainted memory.
+
+Slower version check, for use when platform intermixes malloc and mmap area
+addresses. Test against the current-block of all tainted pools first, then all
+blocks of all tainted pools.
+
+Return: TRUE iff tainted
+*/
 
 BOOL
 is_tainted_fn(const void * p)
 {
 storeblock * b;
 
 BOOL
 is_tainted_fn(const void * p)
 {
 storeblock * b;
-int pool;
 
 
-for (pool = 0; pool < nelem(chainbase); pool++)
+for (int pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++)
   if ((b = current_block[pool]))
     {
   if ((b = current_block[pool]))
     {
-    char * bc = CS b + ALIGNED_SIZEOF_STOREBLOCK;
-    if (CS p >= bc && CS p <= bc + b->length) goto hit;
+    uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK;
+    if (US p >= bc && US p <= bc + b->length) return TRUE;
     }
 
     }
 
-for (pool = 0; pool < nelem(chainbase); pool++)
+for (int pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++)
   for (b = chainbase[pool]; b; b = b->next)
     {
   for (b = chainbase[pool]; b; b = b->next)
     {
-    char * bc = CS b + ALIGNED_SIZEOF_STOREBLOCK;
-    if (CS p >= bc && CS p <= bc + b->length) goto hit;
+    uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK;
+    if (US p >= bc && US p <= bc + b->length) return TRUE;
     }
 return FALSE;
     }
 return FALSE;
-
-hit:
-return pool >= POOL_TAINT_BASE;
 }
 }
-#endif
 
 
 void
 
 
 void
@@ -219,6 +209,7 @@ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Taint mismatch, %s: %s %d\n",
 }
 
 
 }
 
 
+
 /*************************************************
 *       Get a block from the current pool        *
 *************************************************/
 /*************************************************
 *       Get a block from the current pool        *
 *************************************************/
@@ -269,10 +260,7 @@ if (size > yield_length[pool])
     {
     /* Give up on this block, because it's too small */
     nblocks[pool]--;
     {
     /* Give up on this block, because it's too small */
     nblocks[pool]--;
-    if (pool < POOL_TAINT_BASE)
-      internal_untainted_free(newblock, func, linenumber);
-    else
-      internal_tainted_free(newblock, func, linenumber);
+    internal_store_free(newblock, func, linenumber);
     newblock = NULL;
     }
 
     newblock = NULL;
     }
 
@@ -288,9 +276,7 @@ if (size > yield_length[pool])
     if (++nblocks[pool] > maxblocks[pool])
       maxblocks[pool] = nblocks[pool];
 
     if (++nblocks[pool] > maxblocks[pool])
       maxblocks[pool] = nblocks[pool];
 
-    newblock = tainted
-      ? store_mmap(mlength, func, linenumber)
-      : internal_store_malloc(mlength, func, linenumber);
+    newblock = internal_store_malloc(mlength, func, linenumber);
     newblock->next = NULL;
     newblock->length = length;
 
     newblock->next = NULL;
     newblock->length = length;
 
@@ -315,10 +301,7 @@ store_last_get[pool] = next_yield[pool];
 /* Cut out the debugging stuff for utilities, but stop picky compilers from
 giving warnings. */
 
 /* Cut out the debugging stuff for utilities, but stop picky compilers from
 giving warnings. */
 
-#ifdef COMPILE_UTILITY
-func = func;
-linenumber = linenumber;
-#else
+#ifndef COMPILE_UTILITY
 DEBUG(D_memory)
   debug_printf("---%d Get %6p %5d %-14s %4d\n", pool,
     store_last_get[pool], size, func, linenumber);
 DEBUG(D_memory)
   debug_printf("---%d Get %6p %5d %-14s %4d\n", pool,
     store_last_get[pool], size, func, linenumber);
@@ -409,10 +392,7 @@ if (CS ptr + rounded_oldsize != CS (next_yield[pool]) ||
 /* Cut out the debugging stuff for utilities, but stop picky compilers from
 giving warnings. */
 
 /* Cut out the debugging stuff for utilities, but stop picky compilers from
 giving warnings. */
 
-#ifdef COMPILE_UTILITY
-func = func;
-linenumber = linenumber;
-#else
+#ifndef COMPILE_UTILITY
 DEBUG(D_memory)
   debug_printf("---%d Ext %6p %5d %-14s %4d\n", pool, ptr, newsize,
     func, linenumber);
 DEBUG(D_memory)
   debug_printf("---%d Ext %6p %5d %-14s %4d\n", pool, ptr, newsize,
     func, linenumber);
@@ -530,19 +510,13 @@ while ((b = bb))
   nbytes[pool] -= siz;
   pool_malloc -= siz;
   nblocks[pool]--;
   nbytes[pool] -= siz;
   pool_malloc -= siz;
   nblocks[pool]--;
-  if (pool < POOL_TAINT_BASE)
-    internal_untainted_free(b, func, linenumber);
-  else
-    internal_tainted_free(b, func, linenumber);
+  internal_store_free(b, func, linenumber);
   }
 
 /* Cut out the debugging stuff for utilities, but stop picky compilers from
 giving warnings. */
 
   }
 
 /* Cut out the debugging stuff for utilities, but stop picky compilers from
 giving warnings. */
 
-#ifdef COMPILE_UTILITY
-func = func;
-linenumber = linenumber;
-#else
+#ifndef COMPILE_UTILITY
 DEBUG(D_memory)
   debug_printf("---%d Rst %6p %5d %-14s %4d %d\n", pool, ptr,
     count + oldmalloc - pool_malloc,
 DEBUG(D_memory)
   debug_printf("---%d Rst %6p %5d %-14s %4d %d\n", pool, ptr,
     count + oldmalloc - pool_malloc,
@@ -626,10 +600,7 @@ for (int pool = 0; pool < nelem(current_block); pool++)
   /* Cut out the debugging stuff for utilities, but stop picky compilers from
   giving warnings. */
 
   /* Cut out the debugging stuff for utilities, but stop picky compilers from
   giving warnings. */
 
-#ifdef COMPILE_UTILITY
-  func = func;
-  linenumber = linenumber;
-#else
+#ifndef COMPILE_UTILITY
   DEBUG(D_memory)
     debug_printf("---%d Rel %6p %5d %-14s %4d %d\n", pool, ptr, count,
       func, linenumber, pool_malloc);
   DEBUG(D_memory)
     debug_printf("---%d Rel %6p %5d %-14s %4d %d\n", pool, ptr, count,
       func, linenumber, pool_malloc);
@@ -700,10 +671,7 @@ for (storeblock * b = chainbase[pool]; b; b = b->next)
     /* Cut out the debugging stuff for utilities, but stop picky compilers
     from giving warnings. */
 
     /* Cut out the debugging stuff for utilities, but stop picky compilers
     from giving warnings. */
 
-#ifdef COMPILE_UTILITY
-    func = func;
-    linenumber = linenumber;
-#else
+#ifndef COMPILE_UTILITY
     DEBUG(D_memory)
       debug_printf("-Release %6p %-20s %4d %d\n", (void *)bb, func,
        linenumber, pool_malloc);
     DEBUG(D_memory)
       debug_printf("-Release %6p %-20s %4d %d\n", (void *)bb, func,
        linenumber, pool_malloc);
@@ -751,7 +719,7 @@ int pool = tainted ? store_pool + POOL_TAINT_BASE : store_pool;
 BOOL release_ok = !tainted && store_last_get[pool] == block;
 uschar * newtext;
 
 BOOL release_ok = !tainted && store_last_get[pool] == block;
 uschar * newtext;
 
-#ifndef MACRO_PREDEF
+#if !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY)
 if (is_tainted(block) != tainted)
   die_tainted(US"store_newblock", CUS func, linenumber);
 #endif
 if (is_tainted(block) != tainted)
   die_tainted(US"store_newblock", CUS func, linenumber);
 #endif
@@ -765,55 +733,6 @@ return (void *)newtext;
 
 
 
 
 
 
-/******************************************************************************/
-static void *
-store_alloc_tail(void * yield, int size, const char * func, int line,
-  const uschar * type)
-{
-if ((nonpool_malloc += size) > max_nonpool_malloc)
-  max_nonpool_malloc = nonpool_malloc;
-
-/* Cut out the debugging stuff for utilities, but stop picky compilers from
-giving warnings. */
-
-#ifdef COMPILE_UTILITY
-func = func; line = line; type = type;
-#else
-
-/* If running in test harness, spend time making sure all the new store
-is not filled with zeros so as to catch problems. */
-
-if (f.running_in_test_harness)
-  memset(yield, 0xF0, (size_t)size);
-DEBUG(D_memory) debug_printf("--%6s %6p %5d bytes\t%-14s %4d\tpool %5d  nonpool %5d\n",
-  type, yield, size, func, line, pool_malloc, nonpool_malloc);
-#endif  /* COMPILE_UTILITY */
-
-return yield;
-}
-
-/*************************************************
-*                Mmap store                      *
-*************************************************/
-
-static void *
-store_mmap(int size, const char * func, int line)
-{
-void * yield, * top;
-
-if (size < 16) size = 16;
-
-if (!(yield = mmap(NULL, (size_t)size,
-                 PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)))
-  log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to mmap %d bytes of memory: "
-    "called from line %d of %s", size, line, func);
-
-if (yield < tainted_base) tainted_base = yield;
-if ((top = US yield + size) > tainted_top) tainted_top = top;
-
-return store_alloc_tail(yield, size, func, line, US"Mmap");
-}
-
 /*************************************************
 *                Malloc store                    *
 *************************************************/
 /*************************************************
 *                Malloc store                    *
 *************************************************/
@@ -825,13 +744,13 @@ function is called via the macro store_malloc().
 Arguments:
   size        amount of store wanted
   func        function from which called
 Arguments:
   size        amount of store wanted
   func        function from which called
-  linenumber  line number in source file
+  line       line number in source file
 
 Returns:      pointer to gotten store (panic on failure)
 */
 
 static void *
 
 Returns:      pointer to gotten store (panic on failure)
 */
 
 static void *
-internal_store_malloc(int size, const char *func, int linenumber)
+internal_store_malloc(int size, const char *func, int line)
 {
 void * yield;
 
 {
 void * yield;
 
@@ -839,9 +758,25 @@ if (size < 16) size = 16;
 
 if (!(yield = malloc((size_t)size)))
   log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to malloc %d bytes of memory: "
 
 if (!(yield = malloc((size_t)size)))
   log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to malloc %d bytes of memory: "
-    "called from line %d in %s", size, linenumber, func);
+    "called from line %d in %s", size, line, func);
+
+if ((nonpool_malloc += size) > max_nonpool_malloc)
+  max_nonpool_malloc = nonpool_malloc;
+
+/* Cut out the debugging stuff for utilities, but stop picky compilers from
+giving warnings. */
 
 
-return store_alloc_tail(yield, size, func, linenumber, US"Malloc");
+#ifndef COMPILE_UTILITY
+/* If running in test harness, spend time making sure all the new store
+is not filled with zeros so as to catch problems. */
+
+if (f.running_in_test_harness)
+  memset(yield, 0xF0, (size_t)size);
+DEBUG(D_memory) debug_printf("--Malloc %6p %5d bytes\t%-14s %4d\tpool %5d  nonpool %5d\n",
+  yield, size, func, line, pool_malloc, nonpool_malloc);
+#endif  /* COMPILE_UTILITY */
+
+return yield;
 }
 
 void *
 }
 
 void *
@@ -868,12 +803,9 @@ Returns:      nothing
 */
 
 static void
 */
 
 static void
-internal_untainted_free(void * block, const char * func, int linenumber)
+internal_store_free(void * block, const char * func, int linenumber)
 {
 {
-#ifdef COMPILE_UTILITY
-func = func;
-linenumber = linenumber;
-#else
+#ifndef COMPILE_UTILITY
 DEBUG(D_memory)
   debug_printf("----Free %6p %-20s %4d\n", block, func, linenumber);
 #endif  /* COMPILE_UTILITY */
 DEBUG(D_memory)
   debug_printf("----Free %6p %-20s %4d\n", block, func, linenumber);
 #endif  /* COMPILE_UTILITY */
@@ -884,21 +816,7 @@ void
 store_free_3(void * block, const char * func, int linenumber)
 {
 n_nonpool_blocks--;
 store_free_3(void * block, const char * func, int linenumber)
 {
 n_nonpool_blocks--;
-internal_untainted_free(block, func, linenumber);
-}
-
-/******************************************************************************/
-static void
-internal_tainted_free(storeblock * block, const char * func, int linenumber)
-{
-#ifdef COMPILE_UTILITY
-func = func;
-linenumber = linenumber;
-#else
-DEBUG(D_memory)
-  debug_printf("---Unmap %6p %-20s %4d\n", block, func, linenumber);
-#endif
-munmap((void *)block, block->length + ALIGNED_SIZEOF_STOREBLOCK);
+internal_store_free(block, func, linenumber);
 }
 
 /******************************************************************************/
 }
 
 /******************************************************************************/