]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-dcrypt: Avoid infinite loop if istream header is too large.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 5 Sep 2016 23:56:39 +0000 (02:56 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 5 Sep 2016 23:56:39 +0000 (02:56 +0300)
We'll return an error now instead. We can't just return -2 here, because nothing
was actually being returned to the caller. Attempting to do that would just trigger
an assert:

Panic: file istream.c: line 182 (i_stream_read): assertion failed: (_stream->skip != _stream->pos)

src/lib-dcrypt/istream-decrypt.c
src/lib-dcrypt/test-stream.c

index 4f3ca12dfcb279a73849060ba1459b389a5237ed..9da17e8a683035363099c7387b35cecfad19fd67 100644 (file)
@@ -732,6 +732,12 @@ i_stream_decrypt_read(struct istream_private *stream)
 
                        if (hret == 0) {
                                /* see if we can get more data */
+                               if (ret == -2) {
+                                       stream->istream.stream_errno = EINVAL;
+                                       io_stream_set_error(&stream->iostream,
+                                               "Header too large (more than %"PRIuSIZE_T" bytes)", size);
+                                       return -1;
+                               }
                                continue;
                        } else {
                                /* clean up buffer */
index e62eed47847c6b367a2167c68cba931b61c2f371..aa5a7f48dae6fe728a21eeaa87f110605b35f028 100644 (file)
@@ -497,6 +497,22 @@ static void test_read_0_to_400_byte_garbage(void)
        test_end();
 }
 
+static void test_read_large_header(void)
+{
+       test_begin("test_read_large_header");
+
+       struct istream *is = test_istream_create_data(IOSTREAM_CRYPT_MAGIC, sizeof(IOSTREAM_CRYPT_MAGIC));
+       struct istream *ds = i_stream_create_decrypt_callback(is, no_op_cb, NULL);
+       test_istream_set_allow_eof(is, FALSE);
+       test_istream_set_max_buffer_size(is, sizeof(IOSTREAM_CRYPT_MAGIC));
+
+       test_assert(i_stream_read(ds) == -1);
+       i_stream_unref(&ds);
+       i_stream_unref(&is);
+
+       test_end();
+}
+
 static
 void test_free_keys() {
        dcrypt_key_unref_private(&test_v1_kp.priv);
@@ -529,6 +545,7 @@ int main(void) {
                test_write_read_v2_empty,
                test_free_keys,
                test_read_0_to_400_byte_garbage,
+               test_read_large_header,
                NULL
        };