]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: istream-sized - set stream_errno=EPIPE if stream is too small
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 23 Dec 2016 17:51:41 +0000 (12:51 -0500)
committerGitLab <gitlab@git.dovecot.net>
Fri, 23 Dec 2016 19:08:57 +0000 (21:08 +0200)
src/lib/istream-sized.c
src/lib/istream-sized.h
src/lib/test-istream-sized.c [new file with mode: 0644]

index 6f54c5317b54f8fc01b83de6a5538afaebb35045..e5b4cf136b67e79079d51aa77f4f58a64bb265aa 100644 (file)
@@ -98,9 +98,10 @@ static ssize_t i_stream_sized_read(struct istream_private *stream)
        } else if (stream->istream.stream_errno == ENOENT) {
                /* lost the file */
        } else {
+               /* EOF before we reached the wanted size */
                error = sstream->error_callback(&data, sstream->error_context);
                io_stream_set_error(&stream->iostream, "%s", error);
-               stream->istream.stream_errno = EINVAL;
+               stream->istream.stream_errno = EPIPE;
        }
 
        ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) :
index 61a78eb5d10eec50d45bc4efd201c81a02df10ab..3c71877db894b4e03d65b40534d371dedefa51ed 100644 (file)
@@ -16,8 +16,9 @@ typedef const char *
 istream_sized_callback_t(const struct istream_sized_error_data *data,
                         void *context);
 
-/* Assume that input is exactly the given size. If it's smaller, log an error
-   and fail with EINVAL error. If it's larger, log an error but don't fail. */
+/* Assume that input stream is exactly the given size. If the stream is too
+   small, fail with stream_errno=EPIPE. If stream is too large, fail with
+   stream_errno=EINVAL. */
 struct istream *i_stream_create_sized(struct istream *input, uoff_t size);
 /* Same as i_stream_create_sized(), but set the error message via the
    callback. */
diff --git a/src/lib/test-istream-sized.c b/src/lib/test-istream-sized.c
new file mode 100644 (file)
index 0000000..cf8b30b
--- /dev/null
@@ -0,0 +1,66 @@
+/* Copyright (c) 2016 Dovecot authors, see the included COPYING file */
+
+#include "test-lib.h"
+#include "str.h"
+#include "istream-private.h"
+#include "istream-sized.h"
+
+static const struct {
+       const char *input;
+       uoff_t size;
+       int stream_errno;
+} tests[] = {
+       { "", 0, 0 },
+       { "", 1, EPIPE },
+       { "a", 1, 0 },
+       { "ab", 1, EINVAL },
+       { "ab", 0, EINVAL },
+       { "ab", (uoff_t)-1, EPIPE },
+};
+
+static void
+run_test(const char *sized_input, uoff_t sized_size, int stream_errno)
+{
+       unsigned int sized_input_len = strlen(sized_input);
+       struct istream *input_data, *input;
+       const unsigned char *data;
+       size_t i, size;
+       int ret = 0;
+
+       input_data = test_istream_create_data(sized_input, sized_input_len);
+       test_istream_set_allow_eof(input_data, FALSE);
+       input = i_stream_create_sized(input_data, sized_size);
+
+       for (i = 1; i < sized_input_len; i++) {
+               test_istream_set_size(input_data, i);
+               while ((ret = i_stream_read(input)) > 0) ;
+               if (ret == -1 && stream_errno != 0)
+                       break;
+               test_assert(ret == 0);
+       }
+       if (ret == 0) {
+               test_istream_set_allow_eof(input_data, TRUE);
+               test_istream_set_size(input_data, i);
+               while ((ret = i_stream_read(input)) > 0) ;
+       }
+       test_assert(ret == -1);
+       test_assert(input->stream_errno == stream_errno);
+
+       data = i_stream_get_data(input, &size);
+       test_assert(size == I_MIN(sized_input_len, sized_size));
+       if (size > 0)
+               test_assert(memcmp(data, sized_input, size) == 0);
+       i_stream_unref(&input);
+       i_stream_unref(&input_data);
+}
+
+void test_istream_sized(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < N_ELEMENTS(tests); i++) {
+               test_begin(t_strdup_printf("istream sized %u", i+1));
+               run_test(tests[i].input, tests[i].size, tests[i].stream_errno);
+               test_end();
+       }
+}