Each window of an svndiff0-format delta includes a section for new data that will be copied into the preimage (in the order it appears in the window, possibly interspersed with other data). Read this data when encountering it. It is not actually necessary to do so --- it would be just as easy to copy straight from the delta to output when interpreting the relevant instructions --- but this way, the code that interprets svndiff0 instructions can proceed more quickly because it does not require any I/O. Subversion's implementation rejects deltas that do not consume all the auxiliary data that is available. Do not check that for now, because it would make it impossible to test the function of this patch until the instructions to consume data are implemented. Do check for truncated data sections. Since Subversion's applier rejects deltas that end before the new-data section is declared to end, it should be safe for this applier to reject such deltas, too. Helped-by: Ramkumar Ramachandra <artagnon@xxxxxxxxx> Helped-by: David Barr <david.barr@xxxxxxxxxxxx> Signed-off-by: Jonathan Nieder <jrnieder@xxxxxxxxx> --- t/t9011-svn-da.sh | 12 ++++++++++++ vcs-svn/svndiff.c | 27 ++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/t/t9011-svn-da.sh b/t/t9011-svn-da.sh index b9aad70..44832b0 100755 --- a/t/t9011-svn-da.sh +++ b/t/t9011-svn-da.sh @@ -117,4 +117,16 @@ test_expect_success 'preimage view: accept truncated preimage' ' test_cmp empty actual.longread ' +test_expect_success 'inline data' ' + printf "SVNQ%b%s%b%s" "QQQQ\003" "bar" "QQQQ\001" "x" | + q_to_nul >inline.clear && + test-svn-fe -d preimage inline.clear 18 >actual && + test_cmp empty actual +' + +test_expect_success 'truncated inline data' ' + printf "SVNQ%b%s" "QQQQ\003" "b" | q_to_nul >inline.trunc && + test_must_fail test-svn-fe -d preimage inline.trunc 10 +' + test_done diff --git a/vcs-svn/svndiff.c b/vcs-svn/svndiff.c index f2876b3..c60d732 100644 --- a/vcs-svn/svndiff.c +++ b/vcs-svn/svndiff.c @@ -23,6 +23,10 @@ #define VLI_DIGIT_MASK 0x7f #define VLI_BITS_PER_DIGIT 7 +struct window { + struct strbuf data; +}; + static int read_magic(struct line_buffer *in, off_t *len) { static const char magic[] = {'S', 'V', 'N', '\0'}; @@ -101,11 +105,25 @@ static int read_length(struct line_buffer *in, size_t *result, off_t *len) return 0; } +static int read_chunk(struct line_buffer *delta, off_t *delta_len, + struct strbuf *buf, size_t len) +{ + if (len > maximum_signed_value_of_type(off_t) || + (off_t) len > *delta_len) + return -1; + strbuf_reset(buf); + buffer_read_binary(buf, len, delta); + *delta_len -= buf->len; + return 0; +} + static int apply_one_window(struct line_buffer *delta, off_t *delta_len) { + struct window ctx = {STRBUF_INIT}; size_t out_len; size_t instructions_len; size_t data_len; + int rv = 0; assert(delta_len); /* "source view" offset and length already handled; */ @@ -115,9 +133,12 @@ static int apply_one_window(struct line_buffer *delta, off_t *delta_len) return -1; if (instructions_len > 0) return error("What do you think I am? A delta applier?"); - if (data_len > 0) - return error("No support for inline data yet"); - return 0; + if (read_chunk(delta, delta_len, &ctx.data, data_len)) + return error("Invalid delta: incomplete data section"); + if (buffer_ferror(delta)) + rv = error("Cannot read delta: %s", strerror(errno)); + strbuf_release(&ctx.data); + return rv; } int svndiff0_apply(struct line_buffer *delta, off_t delta_len, -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html