Check return from asprintf()
[exim.git] / src / src / exim_dbutil.c
index eb3ae16b38d26213d3420f502aa821494eb66c12..a33c59c08bc229f82e81f3f59dcfa3dcc39d6246 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2016 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
 /* See the file NOTICE for conditions of use and distribution. */
 
 
@@ -253,14 +253,20 @@ dbfn_open(uschar *name, int flags, open_db *dbblock, BOOL lof)
 int rc;
 struct flock lock_data;
 BOOL read_only = flags == O_RDONLY;
 int rc;
 struct flock lock_data;
 BOOL read_only = flags == O_RDONLY;
-uschar dirname[256], filename[256];
+uschar * dirname, * filename;
 
 /* The first thing to do is to open a separate file on which to lock. This
 ensures that Exim has exclusive use of the database before it even tries to
 open it. If there is a database, there should be a lock file in existence. */
 
 
 /* The first thing to do is to open a separate file on which to lock. This
 ensures that Exim has exclusive use of the database before it even tries to
 open it. If there is a database, there should be a lock file in existence. */
 
-snprintf(CS dirname, sizeof(dirname), "%s/db", spool_directory);
-snprintf(CS filename, sizeof(filename), "%s/%.200s.lockfile", dirname, name);
+#ifdef COMPILE_UTILITY
+if (  asprintf(CSS &dirname, "%s/db", spool_directory) < 0
+   || asprintf(CSS &filename, "%s/%s.lockfile", dirname, name) < 0)
+  return NULL;
+#else
+dirname = string_sprintf("%s/db", spool_directory);
+filename = string_sprintf("%s/%s.lockfile", dirname, name);
+#endif
 
 dbblock->lockfd = Uopen(filename, flags, 0);
 if (dbblock->lockfd < 0)
 
 dbblock->lockfd = Uopen(filename, flags, 0);
 if (dbblock->lockfd < 0)
@@ -273,7 +279,7 @@ if (dbblock->lockfd < 0)
 /* Now we must get a lock on the opened lock file; do this with a blocking
 lock that times out. */
 
 /* Now we must get a lock on the opened lock file; do this with a blocking
 lock that times out. */
 
-lock_data.l_type = read_only? F_RDLCK : F_WRLCK;
+lock_data.l_type = read_only ? F_RDLCK : F_WRLCK;
 lock_data.l_whence = lock_data.l_start = lock_data.l_len = 0;
 
 sigalrm_seen = FALSE;
 lock_data.l_whence = lock_data.l_start = lock_data.l_len = 0;
 
 sigalrm_seen = FALSE;
@@ -296,10 +302,14 @@ if (rc < 0)
 /* At this point we have an opened and locked separate lock file, that is,
 exclusive access to the database, so we can go ahead and open it. */
 
 /* At this point we have an opened and locked separate lock file, that is,
 exclusive access to the database, so we can go ahead and open it. */
 
-sprintf(CS filename, "%s/%s", dirname, name);
+#ifdef COMPILE_UTILITY
+if (asprintf(CSS &filename, "%s/%s", dirname, name) < 0) return NULL;
+#else
+filename = string_sprintf("%s/%s", dirname, name);
+#endif
 EXIM_DBOPEN(filename, dirname, flags, 0, &(dbblock->dbptr));
 
 EXIM_DBOPEN(filename, dirname, flags, 0, &(dbblock->dbptr));
 
-if (dbblock->dbptr == NULL)
+if (!dbblock->dbptr)
   {
   printf("** Failed to open DBM file %s for %s:\n   %s%s\n", filename,
     read_only? "reading" : "writing", strerror(errno),
   {
   printf("** Failed to open DBM file %s for %s:\n   %s%s\n", filename,
     read_only? "reading" : "writing", strerror(errno),
@@ -517,15 +527,16 @@ uschar keybuffer[1024];
 
 dbdata_type = check_args(argc, argv, US"dumpdb", US"");
 spool_directory = argv[1];
 
 dbdata_type = check_args(argc, argv, US"dumpdb", US"");
 spool_directory = argv[1];
-dbm = dbfn_open(argv[2], O_RDONLY, &dbblock, FALSE);
-if (dbm == NULL) exit(1);
+if (!(dbm = dbfn_open(argv[2], O_RDONLY, &dbblock, FALSE)))
+  exit(1);
 
 /* Scan the file, formatting the information for each entry. Note
 that data is returned in a malloc'ed block, in order that it be
 correctly aligned. */
 
 
 /* Scan the file, formatting the information for each entry. Note
 that data is returned in a malloc'ed block, in order that it be
 correctly aligned. */
 
-key = dbfn_scan(dbm, TRUE, &cursor);
-while (key != NULL)
+for (key = dbfn_scan(dbm, TRUE, &cursor);
+     key;
+     key = dbfn_scan(dbm, FALSE, &cursor))
   {
   dbdata_retry *retry;
   dbdata_wait *wait;
   {
   dbdata_retry *retry;
   dbdata_wait *wait;
@@ -547,9 +558,8 @@ while (key != NULL)
     return 1;
     }
   Ustrcpy(keybuffer, key);
     return 1;
     }
   Ustrcpy(keybuffer, key);
-  value = dbfn_read_with_length(dbm, keybuffer, &length);
 
 
-  if (value == NULL)
+  if (!(value = dbfn_read_with_length(dbm, keybuffer, &length)))
     fprintf(stderr, "**** Entry \"%s\" was in the key scan, but the record "
                     "was not found in the file - something is wrong!\n",
       CS keybuffer);
     fprintf(stderr, "**** Entry \"%s\" was in the key scan, but the record "
                     "was not found in the file - something is wrong!\n",
       CS keybuffer);
@@ -669,7 +679,6 @@ while (key != NULL)
       }
     store_reset(value);
     }
       }
     store_reset(value);
     }
-  key = dbfn_scan(dbm, FALSE, &cursor);
   }
 
 dbfn_close(dbm);
   }
 
 dbfn_close(dbm);
@@ -776,8 +785,9 @@ for(;;)
     {
     int verify = 1;
     spool_directory = argv[1];
     {
     int verify = 1;
     spool_directory = argv[1];
-    dbm = dbfn_open(argv[2], O_RDWR, &dbblock, FALSE);
-    if (dbm == NULL) continue;
+
+    if (!(dbm = dbfn_open(argv[2], O_RDWR, &dbblock, FALSE)))
+      continue;
 
     if (Ustrcmp(field, "d") == 0)
       {
 
     if (Ustrcmp(field, "d") == 0)
       {
@@ -973,11 +983,10 @@ for(;;)
   /* Handle a read request, or verify after an update. */
 
   spool_directory = argv[1];
   /* Handle a read request, or verify after an update. */
 
   spool_directory = argv[1];
-  dbm = dbfn_open(argv[2], O_RDONLY, &dbblock, FALSE);
-  if (dbm == NULL) continue;
+  if (!(dbm = dbfn_open(argv[2], O_RDONLY, &dbblock, FALSE)))
+    continue;
 
 
-  record = dbfn_read_with_length(dbm, name, &oldlength);
-  if (record == NULL)
+  if (!(record = dbfn_read_with_length(dbm, name, &oldlength)))
     {
     printf("record %s not found\n", name);
     name[0] = 0;
     {
     printf("record %s not found\n", name);
     name[0] = 0;
@@ -1160,8 +1169,8 @@ oldest = time(NULL) - maxkeep;
 printf("Tidying Exim hints database %s/db/%s\n", argv[1], argv[2]);
 
 spool_directory = argv[1];
 printf("Tidying Exim hints database %s/db/%s\n", argv[1], argv[2]);
 
 spool_directory = argv[1];
-dbm = dbfn_open(argv[2], O_RDWR, &dbblock, FALSE);
-if (dbm == NULL) exit(1);
+if (!(dbm = dbfn_open(argv[2], O_RDWR, &dbblock, FALSE)))
+  exit(1);
 
 /* Prepare for building file names */
 
 
 /* Prepare for building file names */
 
@@ -1174,14 +1183,14 @@ to the file while scanning it. Pity the man page doesn't warn you about that.
 Therefore, we scan and build a list of all the keys. Then we use that to
 read the records and possibly update them. */
 
 Therefore, we scan and build a list of all the keys. Then we use that to
 read the records and possibly update them. */
 
-key = dbfn_scan(dbm, TRUE, &cursor);
-while (key != NULL)
+for (key = dbfn_scan(dbm, TRUE, &cursor);
+     key;
+     key = dbfn_scan(dbm, FALSE, &cursor))
   {
   key_item *k = store_get(sizeof(key_item) + Ustrlen(key));
   k->next = keychain;
   keychain = k;
   Ustrcpy(k->key, key);
   {
   key_item *k = store_get(sizeof(key_item) + Ustrlen(key));
   k->next = keychain;
   keychain = k;
   Ustrcpy(k->key, key);
-  key = dbfn_scan(dbm, FALSE, &cursor);
   }
 
 /* Now scan the collected keys and operate on the records, resetting
   }
 
 /* Now scan the collected keys and operate on the records, resetting
@@ -1189,7 +1198,7 @@ the store each time round. */
 
 reset_point = store_get(0);
 
 
 reset_point = store_get(0);
 
-while (keychain != NULL)
+while (keychain)
   {
   dbdata_generic *value;
 
   {
   dbdata_generic *value;