]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.7-20210615
authorWietse Venema <wietse@porcupine.org>
Tue, 15 Jun 2021 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Wed, 19 Jan 2022 06:36:07 +0000 (01:36 -0500)
postfix/HISTORY
postfix/html/postmap.1.html
postfix/man/man1/postmap.1
postfix/src/global/mail_version.h
postfix/src/postmap/Makefile.in
postfix/src/postmap/postmap.c
postfix/src/util/Makefile.in
postfix/src/util/dict_thash.c
postfix/src/util/slmdb.c

index 29457aefc0bed28a761af121e6616ec8a8edbd68..862671a8820ed6b588ff706e57e22ed64dd195af 100644 (file)
@@ -25624,3 +25624,16 @@ Apologies for any names omitted.
 
        Cleanup: simplify the LMDB error recovery code. File:
        util/slmdb.c.
+
+20210615
+
+       Bugfix (introduced: Postfix 3.4): the texthash: map
+       implementation did not support "postmap -F" behavior.
+       Reported by Christopher Gurnee, who also found the missing
+       code in the postmap source. File: util/dict_thash.c.
+
+       Cleanup: documentation for the postmap -F option. File:
+       postmap/postmap.c.
+
+       Cleanup: simplify the LMDB error recovery code. File:
+       util/slmdb.c.
index 27380f2f3d9d31193188ba676ec683380bcd713e..3ce1ff838584323c52b988b3f938d84e2668120b 100644 (file)
@@ -101,7 +101,9 @@ POSTMAP(1)                                                          POSTMAP(1)
               When creating a map from source file, process each  value  as  a
               list  of  filenames, concatenate the content of those files, and
               store the base64-encoded result instead of the value (see  INPUT
-              FORMAT for details).
+              FILE FORMAT for details).
+
+              This feature is available in Postfix version 3.4 and later.
 
        <b>-h</b>     Enable  message header query mode. When reading lookup keys from
               standard input with "<b>-q -</b>", process the input as  if  it  is  an
index e4dd20e7b472a1ee4a2f29adc1eb4061a2b384c7..d086d6ca282f2ba66de8a2bbff431c6312e074c6 100644 (file)
@@ -115,7 +115,9 @@ When querying a map, or listing a map, base64\-decode each
 value. When creating a map from source file, process each
 value as a list of filenames, concatenate the content of
 those files, and store the base64\-encoded result instead
-of the value (see INPUT FORMAT for details).
+of the value (see INPUT FILE FORMAT for details).
+.sp
+This feature is available in Postfix version 3.4 and later.
 .IP \fB\-h\fR
 Enable message header query mode. When reading lookup keys
 from standard input with "\fB\-q \-\fR", process the input
index f57b8a1ef7862d21d59989a876d2490d9717f132..989ba2a781e736cbc96cd9b78f881527ead16f85 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20210612"
+#define MAIL_RELEASE_DATE      "20210615"
 #define MAIL_VERSION_NUMBER    "3.7"
 
 #ifdef SNAPSHOT
index c28af2aea7c64531563b003309740c8aefd53bb4..dc5369d9b066bb7412c5130dddfcda9a7fc83f30 100644 (file)
@@ -85,7 +85,7 @@ lmdb_bulk_test: $(PROG)
        rm -f lmdb_retry.lmdb main.cf
        tr A-Z a-z < /usr/share/dict/words| \
            sed -e 's/.*/&      &/' -e 10000q| LANG=C sort -u >lmdb_retry
-       echo lmdb_map_size=10000 >main.cf
+       echo lmdb_map_size=10240 >main.cf
        ($(SHLIB_ENV) $(VALGRIND) ./postmap -c . lmdb:lmdb_retry; \
        $(SHLIB_ENV) $(VALGRIND) ./postmap -s lmdb:lmdb_retry | \
            LANG=C sort > lmdb_retry.tmp)
@@ -95,8 +95,8 @@ lmdb_bulk_test: $(PROG)
 lmdb_incr_test: $(PROG)
        rm -f lmdb_retry.lmdb main.cf
        tr A-Z a-z < /usr/share/dict/words| \
-           sed -e 's/.*/&      &/' -e 10000q| LANG=C sort -u >lmdb_retry
-       echo lmdb_map_size=10000 >main.cf
+           sed -e 's/.*/&      &/' -e 1000q| LANG=C sort -u >lmdb_retry
+       echo lmdb_map_size=10240 >main.cf
        ($(SHLIB_ENV) $(VALGRIND) ./postmap -ic . lmdb:lmdb_retry <lmdb_retry; \
        $(SHLIB_ENV) $(VALGRIND) ./postmap -s lmdb:lmdb_retry | \
            LANG=C sort > lmdb_retry.tmp)
index 6d4f2413ea37f89cd776dcff962975f3b99910bd..d97425c6c19c328daebecda1cdc82e49b3a0ed31 100644 (file)
 /*     value. When creating a map from source file, process each
 /*     value as a list of filenames, concatenate the content of
 /*     those files, and store the base64-encoded result instead
-/*     of the value (see INPUT FORMAT for details).
+/*     of the value (see INPUT FILE FORMAT for details).
+/* .sp
+/*     This feature is available in Postfix version 3.4 and later.
 /* .IP \fB-h\fR
 /*     Enable message header query mode. When reading lookup keys
 /*     from standard input with "\fB-q -\fR", process the input
index 3b2e55c048b43e04f18f3332039790af7af58066..a0bb00a917f85d2fc05e8bebba89048a739967ae 100644 (file)
@@ -1720,6 +1720,7 @@ dict_thash.o: htable.h
 dict_thash.o: iostuff.h
 dict_thash.o: msg.h
 dict_thash.o: myflock.h
+dict_thash.o: mymalloc.h
 dict_thash.o: readlline.h
 dict_thash.o: stringops.h
 dict_thash.o: sys_defs.h
index a121ead35518390e3abf12edbd087e649e9e6133..5012fb9e2739a1dbb35f89b89db976508d042265 100644 (file)
@@ -46,6 +46,7 @@
 /* Utility library. */
 
 #include <msg.h>
+#include <mymalloc.h>
 #include <iostuff.h>
 #include <vstring.h>
 #include <stringops.h>
@@ -179,6 +180,24 @@ DICT   *dict_thash_open(const char *path, int open_flags, int dict_flags)
                msg_warn("%s, line %d: record is in \"key: value\" format;"
                         " is this an alias file?", path, lineno);
 
+           /*
+            * Optionally treat the value as a filename, and replace the value
+            * with the BASE64-encoded content of the named file.
+            */
+           if (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) {
+               VSTRING *base64_buf;
+               char   *err;
+
+               if ((base64_buf = dict_file_to_b64(dict, value)) == 0) {
+                   err = dict_file_get_error(dict);
+                   msg_warn("%s, line %d: %s: skipping this entry",
+                            VSTREAM_PATH(fp), lineno, err);
+                   myfree(err);
+                   continue;
+               }
+               value = vstring_str(base64_buf);
+           }
+
            /*
             * Store the value under the key. Handle duplicates
             * appropriately. XXX Move this into dict_ht, but 1) that map
index ac1594ff300fae69ea5d65bafad1360c909f3c92..9f03b477dd1b3b265f9bf6d0c0e03220739273fe 100644 (file)
   * triggers a long jump back into the caller to some pre-arranged point (the
   * closest thing that C has to exception handling). The application is then
   * expected to repeat the bulk transaction from scratch.
+  * 
+  * When any code aborts a bulk transaction, it must reset slmdb->txn to null
+  * to avoid a use-after-free problem in slmdb_close().
   */
 
  /*
@@ -379,7 +382,9 @@ static int slmdb_prepare(SLMDB *slmdb)
      * This is called before accessing the database, or after recovery from
      * an LMDB error. Note: this code cannot recover from errors itself.
      * slmdb->txn is either the database open() transaction or a
-     * freshly-created bulk-mode transaction.
+     * freshly-created bulk-mode transaction. When slmdb_prepare() commits or
+     * aborts commits a transaction, it must set slmdb->txn to null to avoid
+     * a use-after-free error in slmdb_close().
      * 
      * - With O_TRUNC we make a "drop" request before updating the database.
      * 
@@ -410,6 +415,7 @@ static int slmdb_prepare(SLMDB *slmdb)
 static int slmdb_recover(SLMDB *slmdb, int status)
 {
     MDB_envinfo info;
+    int     original_status = status;
 
     /*
      * This may be needed in non-MDB_NOLOCK mode. Recovery is rare enough
@@ -425,19 +431,14 @@ static int slmdb_recover(SLMDB *slmdb, int status)
        return (status);
 
     /*
-     * Recover bulk transactions only if they can be restarted, but limit the
-     * number of recovery attempts.
+     * Limit the number of bulk transaction recovery attempts.
      */
     if ((slmdb->slmdb_flags & SLMDB_FLAG_BULK) != 0
-       && (slmdb->longjmp_fn == 0
-           || (slmdb->bulk_retry_count += 1) > slmdb->bulk_retry_limit))
+       && (slmdb->bulk_retry_count += 1) > slmdb->bulk_retry_limit)
        return (status);
 
     /*
-     * If we can recover from the error, we clear the error condition and the
-     * caller should retry the failed operation immediately. Otherwise, the
-     * caller should terminate with a fatal run-time error and the program
-     * should be re-run later.
+     * Try to clear the error condition.
      */
     switch (status) {
 
@@ -504,18 +505,33 @@ static int slmdb_recover(SLMDB *slmdb, int status)
     }
 
     /*
-     * If a bulk-transaction error is recoverable, build a new bulk
-     * transaction from scratch, by making a long jump back into the caller
-     * at some pre-arranged point. In MDB_NOLOCK mode, there is no need to
-     * upgrade the lock to "exclusive", because the failed write transaction
-     * has no side effects.
+     * If we cleared the error condition for a non-bulk transaction, return a
+     * success status. The caller should retry the failed operation
+     * immediately.
      */
-    if (status == 0 && (slmdb->slmdb_flags & SLMDB_FLAG_BULK) != 0
-       && (status = mdb_txn_begin(slmdb->env, (MDB_txn *) 0,
-                                  slmdb->lmdb_flags & MDB_RDONLY,
-                                  &slmdb->txn)) == 0
-       && (status = slmdb_prepare(slmdb)) == 0)
-       slmdb->longjmp_fn(slmdb->cb_context, 1);
+    if (status == 0 && (slmdb->slmdb_flags & SLMDB_FLAG_BULK) != 0) {
+
+       /*
+        * We cleared the error condition for a bulk transaction. If the
+        * transaction is not restartable, return the original error. The
+        * caller should terminate with a fatal run-time error, and the
+        * program should be re-run later.
+        */
+       if (slmdb->longjmp_fn == 0)
+           return (original_status);
+
+       /*
+        * Rebuild a bulk transaction from scratch, by making a long jump
+        * back into the caller at some pre-arranged point. In MDB_NOLOCK
+        * mode, there is no need to upgrade a lock to "exclusive", because a
+        * failed write transaction has no side effects.
+        */
+       if ((status = mdb_txn_begin(slmdb->env, (MDB_txn *) 0,
+                                   slmdb->lmdb_flags & MDB_RDONLY,
+                                   &slmdb->txn)) == 0
+           && (status = slmdb_prepare(slmdb)) == 0)
+           slmdb->longjmp_fn(slmdb->cb_context, 1);
+    }
     return (status);
 }
 
@@ -667,8 +683,12 @@ int     slmdb_cursor_get(SLMDB *slmdb, MDB_val *mdb_key,
     /*
      * TODO: figure how we would recover a failing bulk transaction.
      */
-    if ((slmdb->slmdb_flags & SLMDB_FLAG_BULK) != 0)
+    if ((slmdb->slmdb_flags & SLMDB_FLAG_BULK) != 0) {
+       if (slmdb->assert_fn)
+           slmdb->assert_fn(slmdb->cb_context,
+                    "slmdb_cursor_get: bulk transaction is not supported");
        return (MDB_PANIC);
+    }
 
     /*
      * Open a read transaction and cursor if needed.
@@ -790,7 +810,8 @@ int     slmdb_close(SLMDB *slmdb)
 
     /*
      * Finish an open bulk transaction. If slmdb_recover() returns after a
-     * bulk-transaction error, then it was unable to recover.
+     * bulk-transaction error, then it was unable to clear the error
+     * condition, or unable to restart the bulk transaction.
      */
     if ((slmdb->slmdb_flags & SLMDB_FLAG_BULK) != 0 && slmdb->txn != 0
        && (status = mdb_txn_commit(slmdb->txn)) != 0)