summaryrefslogtreecommitdiff
path: root/subversion/tests/libsvn_subr/stream-test.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/tests/libsvn_subr/stream-test.c')
-rw-r--r--subversion/tests/libsvn_subr/stream-test.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/subversion/tests/libsvn_subr/stream-test.c b/subversion/tests/libsvn_subr/stream-test.c
index 0083d41..1a36ce0 100644
--- a/subversion/tests/libsvn_subr/stream-test.c
+++ b/subversion/tests/libsvn_subr/stream-test.c
@@ -1000,6 +1000,71 @@ test_stream_readline_file_crlf(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_stream_readline_file_nul(apr_pool_t *pool)
+{
+ /* Test is written based on the problem report in
+ https://lists.apache.org/thread.html/c96eb5618ac0bf6e083345e0fdcdcf834e30913f26eabe6ada7bab62@%3Cusers.subversion.apache.org%3E
+ where the user had an OOM when calling `svndumpfilter` with
+ a (most likely) invalid dump containing nul bytes.
+ */
+ const char data[] =
+ {
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n',
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n',
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n',
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n',
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n',
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n',
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n',
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n',
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n',
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n',
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n',
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n',
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n',
+ 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n'
+ };
+ const char *tmp_dir;
+ const char *tmp_file;
+ svn_stream_t *stream;
+
+ SVN_ERR(svn_dirent_get_absolute(&tmp_dir, "test_stream_readline_file_nul", pool));
+ SVN_ERR(svn_io_remove_dir2(tmp_dir, TRUE, NULL, NULL, pool));
+ SVN_ERR(svn_io_make_dir_recursively(tmp_dir, pool));
+ svn_test_add_dir_cleanup(tmp_dir);
+
+ tmp_file = svn_dirent_join(tmp_dir, "file", pool);
+ SVN_ERR(svn_io_file_create_bytes(tmp_file, data, sizeof(data), pool));
+ SVN_ERR(svn_stream_open_readonly(&stream, tmp_file, pool, pool));
+
+ while (1)
+ {
+ svn_boolean_t eof;
+ svn_stringbuf_t *line;
+
+ SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, pool));
+ if (eof)
+ break;
+
+ /* Don't check the contents of the `line` here, at least for now.
+
+ In other words, we just test that this case does not crash or cause
+ unexpected errors. The reason is that currently our `readline_fn`
+ implementations have inconsistent behavior when dealing with \0 bytes,
+ handling those differently, either in strchr() or memchr() styles.
+
+ Once we make them consistent (or even decide to bail out with an error
+ for \0), this part of the test should start properly checking `data`;
+ maybe also for non-file streams.
+ */
+ }
+
+ SVN_ERR(svn_stream_close(stream));
+
+ return SVN_NO_ERROR;
+}
+
/* The test table. */
static int max_threads = 1;
@@ -1037,6 +1102,8 @@ static struct svn_test_descriptor_t test_funcs[] =
"test reading LF-terminated lines from file"),
SVN_TEST_PASS2(test_stream_readline_file_crlf,
"test reading CRLF-terminated lines from file"),
+ SVN_TEST_PASS2(test_stream_readline_file_nul,
+ "test reading line from file with nul bytes"),
SVN_TEST_NULL
};