summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2021-07-15 15:12:50 +0300
committerSergey Poznyakoff <gray@gnu.org>2021-07-15 15:29:43 +0300
commit231194ebb67b2c2865b8d4e82bd5379761742ec1 (patch)
tree4e040b2e31fe544faa33c8d02958a189abe5c0ad
parent62a81295d771a9ca90e617b13992279932211b78 (diff)
downloadmailutils-231194ebb67b2c2865b8d4e82bd5379761742ec1.tar.gz
mailutils-231194ebb67b2c2865b8d4e82bd5379761742ec1.tar.bz2
Fix stream reference bug in mu_filter_stream_create
If the mu_filter_xcode_t function failed in mu_filter_init request, mu_filter_stream_create would leave the transport reference counter incremented by one. * libmailutils/stream/fltstream.c (mu_filter_stream_create): On failure, decrement reference counter of transport stream. * libmailutils/tests/fltcnt.c: Test for the above bug as well.
-rw-r--r--libmailutils/stream/fltstream.c1
-rw-r--r--libmailutils/tests/fltcnt.c136
2 files changed, 121 insertions, 16 deletions
diff --git a/libmailutils/stream/fltstream.c b/libmailutils/stream/fltstream.c
index cb938d025..08ed59c63 100644
--- a/libmailutils/stream/fltstream.c
+++ b/libmailutils/stream/fltstream.c
@@ -719,6 +719,7 @@ mu_filter_stream_create (mu_stream_t *pflt,
rc = filter_stream_init (fs);
if (rc)
{
+ mu_stream_unref (str);
free (fs);
return rc;
}
diff --git a/libmailutils/tests/fltcnt.c b/libmailutils/tests/fltcnt.c
index f5ad04f3a..c5bdacc0c 100644
--- a/libmailutils/tests/fltcnt.c
+++ b/libmailutils/tests/fltcnt.c
@@ -1,19 +1,42 @@
/*
NAME
- fltcnt - check how mu_filter_chain_create() changes the reference counter
- of its input stream.
+ fltcnt - checks transport reference counter changes during filter creation.
-DESCRIPTION
- On success, mu_filter_chain_create shall increment the reference counter
- if its "transport" argument by 1. On error, the reference counter shall
- remain unchanged. Versions of mailutils prior to 2021-07-15 failed to
- meet the latter requirement.
+SYNOPSIS
+ fltcnt [NAME...]
- The program checks how the input reference counter changes across two
- calls to mu_filter_chain_create: one that succeeds and other that fails.
- If the changes are as described above, it returns 0. Otherwise it prints
- a diagnostics message on standard error and returns 1.
+DESCRIPTION
+ Any filter creation call should behave as follows:
+
+ On success, it shall increment the reference counter in its "transport"
+ argument by 1.
+ On error, the reference counter shall remain unchanged.
+
+ The following functions failed to meet these requirements in mailutils
+ versions prior to 2021-07-15:
+
+ mu_filter_chain_create
+ On error, this function decremented the transport reference counter.
+ This happened, in particular, if an invalid filter has been requested.
+ However, if improper arguments were given to a valid filter, the
+ mu_filter_stream_create bug described below would compensate for this.
+
+ To check for this bug, the program does two mu_filter_chain_create
+ calls: one with a valid filter name, and another one with an inexisting
+ filter name. Reference counter values are verified after each call.
+
+ mu_filter_stream_create
+ If the mu_filter_xcode_t function failed in mu_filter_init request,
+ mu_filter_stream_create would leave the transport reference counter
+ incremented by one.
+ By default, the program runs both tests in this order. If any of them
+ fails, it prints two diagnostic messages: the first one describes where
+ exactly the program failed to meet its expectations and the second one
+ gives the name of the test that failed.
+
+ To run a single test, give its name as a command line argument.
+
LICENSE
GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2021 Free Software Foundation, Inc.
@@ -40,16 +63,13 @@ LICENSE
#include <mailutils/sys/stream.h>
int
-main (int argc, char **argv)
+test_mu_filter_chain_create (mu_stream_t in)
{
- mu_stream_t in, flt;
+ mu_stream_t flt;
int rc;
char *fargv[] = { "7bit", "+", "7bit", NULL };
int init_ref_count;
- /* Create input stream and increase its reference counter. */
- MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0));
- mu_stream_ref (in);
/* Save the initial reference counter. */
init_ref_count = in->ref_count;
@@ -119,5 +139,89 @@ main (int argc, char **argv)
return 0;
}
+
+static enum mu_filter_result
+xfail_transcoder (void *xdata,
+ enum mu_filter_command cmd,
+ struct mu_filter_io *iobuf)
+{
+ if (cmd == mu_filter_init)
+ {
+ iobuf->errcode = MU_ERR_USER0;
+ return mu_filter_failure;
+ }
+ return mu_filter_ok;
+}
+
+int
+test_mu_filter_stream_create (mu_stream_t in)
+{
+ int rc;
+ int init_ref_count;
+ mu_stream_t flt;
+ void *data = malloc(1);
+
+ /* Save the initial reference counter. */
+ init_ref_count = in->ref_count;
+
+ rc = mu_filter_stream_create (&flt, in,
+ MU_FILTER_ENCODE,
+ xfail_transcoder,
+ data, MU_STREAM_READ);
+
+ if (rc != MU_ERR_USER0)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_filter_stream_create", NULL, rc);
+ return 1;
+ }
+
+ if (in->ref_count != init_ref_count)
+ {
+ mu_error ("after failed mu_filter_stream_create: unexpected ref_count: %lu",
+ (unsigned long) in->ref_count);
+ return 1;
+ }
+ return 0;
+}
+int
+main (int argc, char **argv)
+{
+ mu_stream_t in;
+ static struct testtab
+ {
+ char *name;
+ int (*test) (mu_stream_t);
+ } testtab[] = {
+ { "mu_filter_chain_create", test_mu_filter_chain_create },
+ { "mu_filter_stream_create", test_mu_filter_stream_create },
+ { NULL }
+ };
+ int i;
+ /* Create input stream and increase its reference counter. */
+ MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0));
+ mu_stream_ref (in);
+
+ for (i = 0; testtab[i].name; i++)
+ {
+ int rc;
+
+ if (argc > 1)
+ {
+ int j;
+ for (j = 1; j < argc; j++)
+ if (strcmp (argv[j], testtab[i].name) == 0)
+ break;
+ if (j == argc)
+ continue;
+ }
+ rc = testtab[i].test (in);
+ if (rc)
+ {
+ mu_error ("%s: FAIL", testtab[i].name);
+ return rc;
+ }
+ }
+ return 0;
+}

Return to:

Send suggestions and report system problems to the System administrator.