Use long names for the _DRIVER_*, and _OPT_* macros
[exim.git] / src / src / spool_in.c
index 6341387a206f45f6a91181548e26e1da3d0b2cb2..e1d6e3422968032df7ae6c9f9a4dbf173df9fb46 100644 (file)
@@ -25,6 +25,8 @@ fact it won't be written to. Just in case there's a major disaster (e.g.
 overwriting some other file descriptor with the value of this one), open it
 with append.
 
 overwriting some other file descriptor with the value of this one), open it
 with append.
 
+As called by deliver_message() (at least) we are operating as root.
+
 Argument: the id of the message
 Returns:  fd if file successfully opened and locked, else -1
 
 Argument: the id of the message
 Returns:  fd if file successfully opened and locked, else -1
 
@@ -37,7 +39,6 @@ spool_open_datafile(uschar *id)
 int i;
 struct stat statbuf;
 flock_t lock_data;
 int i;
 struct stat statbuf;
 flock_t lock_data;
-uschar spoolname[256];
 int fd;
 
 /* If split_spool_directory is set, first look for the file in the appropriate
 int fd;
 
 /* If split_spool_directory is set, first look for the file in the appropriate
@@ -49,23 +50,31 @@ splitting state. */
 
 for (i = 0; i < 2; i++)
   {
 
 for (i = 0; i < 2; i++)
   {
+  uschar * fname;
   int save_errno;
   int save_errno;
-  message_subdir[0] = split_spool_directory == (i == 0) ? id[5] : 0;
-  snprintf(CS spoolname, sizeof(spoolname), "%s/input/%s/%s/%s-D",
-           spool_directory, queue_name, message_subdir, id);
-  DEBUG(D_deliver) debug_printf("Trying spool file %s\n", spoolname);
 
 
-  if ((fd = Uopen(spoolname, O_RDWR | O_APPEND, 0)) >= 0)
+  message_subdir[0] = split_spool_directory == i ? '\0' : id[5];
+  fname = spool_fname(US"input", message_subdir, id, US"-D");
+  DEBUG(D_deliver) debug_printf("Trying spool file %s\n", fname);
+
+  if ((fd = Uopen(fname,
+#ifdef O_CLOEXEC
+                     O_CLOEXEC |
+#endif
+                     O_RDWR | O_APPEND, 0)) >= 0)
     break;
   save_errno = errno;
   if (errno == ENOENT)
     {
     if (i == 0) continue;
     if (!queue_running)
     break;
   save_errno = errno;
   if (errno == ENOENT)
     {
     if (i == 0) continue;
     if (!queue_running)
-      log_write(0, LOG_MAIN, "Spool file %s-D not found", id);
+      log_write(0, LOG_MAIN, "Spool%s%s file %s-D not found",
+       *queue_name ? US" Q=" : US"",
+       *queue_name ? queue_name : US"",
+       id);
     }
     }
-  else log_write(0, LOG_MAIN, "Spool error for %s: %s", spoolname,
-    strerror(errno));
+  else
+    log_write(0, LOG_MAIN, "Spool error for %s: %s", fname, strerror(errno));
   errno = save_errno;
   return -1;
   }
   errno = save_errno;
   return -1;
   }
@@ -78,8 +87,9 @@ an open file descriptor (at least, I think that's the Cygwin story). On real
 Unix systems it doesn't make any difference as long as Exim is consistent in
 what it locks. */
 
 Unix systems it doesn't make any difference as long as Exim is consistent in
 what it locks. */
 
-(void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) |
-  FD_CLOEXEC);
+#ifndef O_CLOEXEC
+(void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif
 
 lock_data.l_type = F_WRLCK;
 lock_data.l_whence = SEEK_SET;
 
 lock_data.l_type = F_WRLCK;
 lock_data.l_whence = SEEK_SET;
@@ -212,6 +222,8 @@ have been the cause of that incident, but in any case, this code must be robust
 against such an event, and if such a file is encountered, it must be treated as
 malformed.
 
 against such an event, and if such a file is encountered, it must be treated as
 malformed.
 
+As called from deliver_message() (at least) we are running as root.
+
 Arguments:
   name          name of the header file, including the -H
   read_headers  TRUE if in-store header structures are to be built
 Arguments:
   name          name of the header file, including the -H
   read_headers  TRUE if in-store header structures are to be built
@@ -322,10 +334,11 @@ for (n = 0; n < 2; n++)
   {
   if (!subdir_set)
     message_subdir[0] = split_spool_directory == (n == 0) ? name[5] : 0;
   {
   if (!subdir_set)
     message_subdir[0] = split_spool_directory == (n == 0) ? name[5] : 0;
-  sprintf(CS big_buffer, "%s/input/%s/%s/%s",
-         spool_directory, queue_name, message_subdir, name);
-  if ((f = Ufopen(big_buffer, "rb"))) break;
-  if (n != 0 || subdir_set || errno != ENOENT) return spool_read_notopen;
+
+  if ((f = Ufopen(spool_fname(US"input", message_subdir, name, US""), "rb")))
+    break;
+  if (n != 0 || subdir_set || errno != ENOENT)
+    return spool_read_notopen;
   }
 
 errno = 0;
   }
 
 errno = 0;
@@ -472,21 +485,24 @@ for (;;)
 
     else if (Ustrncmp(p, "cl ", 3) == 0)
       {
 
     else if (Ustrncmp(p, "cl ", 3) == 0)
       {
-      int index, count;
-      uschar name[20];   /* Need plenty of space for %d format */
-      tree_node *node;
-      if (  sscanf(CS big_buffer + 5, "%d %d", &index, &count) != 2
+      unsigned index, count;
+      uschar name[20];   /* Need plenty of space for %u format */
+      tree_node * node;
+      if (  sscanf(CS big_buffer + 5, "%u %u", &index, &count) != 2
         || index >= 20
         || index >= 20
+        || count > 16384       /* arbitrary limit on variable size */
          )
         goto SPOOL_FORMAT_ERROR;
       if (index < 10)
          )
         goto SPOOL_FORMAT_ERROR;
       if (index < 10)
-        (void) string_format(name, sizeof(name), "%c%d", 'c', index);
+        (void) string_format(name, sizeof(name), "%c%u", 'c', index);
       else
       else
-        (void) string_format(name, sizeof(name), "%c%d", 'm', index - 10);
+        (void) string_format(name, sizeof(name), "%c%u", 'm', index - 10);
       node = acl_var_create(name);
       node->data.ptr = store_get(count + 1);
       node = acl_var_create(name);
       node->data.ptr = store_get(count + 1);
+      /* We sanity-checked the count, so disable the Coverity error */
+      /* coverity[tainted_data] */
       if (fread(node->data.ptr, 1, count+1, f) < count) goto SPOOL_READ_ERROR;
       if (fread(node->data.ptr, 1, count+1, f) < count) goto SPOOL_READ_ERROR;
-      ((uschar*)node->data.ptr)[count] = 0;
+      (US node->data.ptr)[count] = '\0';
       }
     break;
 
       }
     break;
 
@@ -656,10 +672,12 @@ DEBUG(D_deliver)
 #endif  /* COMPILE_UTILITY */
 
 /* After reading the tree, the next line has not yet been read into the
 #endif  /* COMPILE_UTILITY */
 
 /* After reading the tree, the next line has not yet been read into the
-buffer. It contains the count of recipients which follow on separate lines. */
+buffer. It contains the count of recipients which follow on separate lines.
+Apply an arbitrary sanity check.*/
 
 if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
 
 if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
-if (sscanf(CS big_buffer, "%d", &rcount) != 1) goto SPOOL_FORMAT_ERROR;
+if (sscanf(CS big_buffer, "%d", &rcount) != 1 || rcount > 16384)
+  goto SPOOL_FORMAT_ERROR;
 
 #ifndef COMPILE_UTILITY
 DEBUG(D_deliver) debug_printf("recipients_count=%d\n", rcount);
 
 #ifndef COMPILE_UTILITY
 DEBUG(D_deliver) debug_printf("recipients_count=%d\n", rcount);
@@ -668,6 +686,10 @@ DEBUG(D_deliver) debug_printf("recipients_count=%d\n", rcount);
 recipients_list_max = rcount;
 recipients_list = store_get(rcount * sizeof(recipient_item));
 
 recipients_list_max = rcount;
 recipients_list = store_get(rcount * sizeof(recipient_item));
 
+/* We sanitised the count and know we have enough memory, so disable
+the Coverity error on recipients_count */
+/* coverity[tainted_data] */
+
 for (recipients_count = 0; recipients_count < rcount; recipients_count++)
   {
   int nn;
 for (recipients_count = 0; recipients_count < rcount; recipients_count++)
   {
   int nn;