Skip to content

Commit e7d04ee

Browse files
committed
vcs-svn: make reading of properties binary-safe
svn-fe errors out on revision 59151 of the ASF repository: fatal: invalid dump: unexpected end of file The proximate cause is a property with an embedded NUL character. Previously such anomalies were ignored but commit c9d1c8b (2010-12-28) introduced a check strlen(val) == len to avoid reading uninitialized data when a property list ends early and unfortunately this test does not distinguish between "foo" followed by EOF and the string "foo\0bar\0baz". Fix it by using buffer_read_binary to read to a strbuf and checking the actual length read. Most consumers of properties still use C-style strings, so in practice an author or log message with embedded NULs will be truncated, but a least this way svn-fe won't error out (fixing the regression). Reported-by: David Barr <david.barr@cordelta.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
1 parent 41b9dd9 commit e7d04ee

2 files changed

Lines changed: 37 additions & 14 deletions

File tree

t/t9010-svn-fe.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,33 @@ test_expect_failure 'change file mode but keep old content' '
370370
test_cmp hello actual.target
371371
'
372372

373+
test_expect_success 'NUL in property value' '
374+
reinit_git &&
375+
echo "commit message" >expect.message &&
376+
{
377+
properties \
378+
unimportant "something with a NUL (Q)" \
379+
svn:log "commit message"&&
380+
echo PROPS-END
381+
} |
382+
q_to_nul >props &&
383+
{
384+
cat <<-\EOF &&
385+
SVN-fs-dump-format-version: 3
386+
387+
Revision-number: 1
388+
EOF
389+
echo Prop-content-length: $(wc -c <props) &&
390+
echo Content-length: $(wc -c <props) &&
391+
echo &&
392+
cat props
393+
} >nulprop.dump &&
394+
test-svn-fe nulprop.dump >stream &&
395+
git fast-import <stream &&
396+
git diff-tree --always -s --format=%s HEAD >actual.message &&
397+
test_cmp expect.message actual.message
398+
'
399+
373400
test_expect_success 'change file mode and reiterate content' '
374401
reinit_git &&
375402
cat >expect <<-\EOF &&

vcs-svn/svndump.c

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ static void die_short_read(void)
147147
static void read_props(void)
148148
{
149149
static struct strbuf key = STRBUF_INIT;
150+
static struct strbuf val = STRBUF_INIT;
150151
const char *t;
151152
/*
152153
* NEEDSWORK: to support simple mode changes like
@@ -163,38 +164,33 @@ static void read_props(void)
163164
uint32_t type_set = 0;
164165
while ((t = buffer_read_line(&input)) && strcmp(t, "PROPS-END")) {
165166
uint32_t len;
166-
const char *val;
167167
const char type = t[0];
168168
int ch;
169169

170170
if (!type || t[1] != ' ')
171171
die("invalid property line: %s\n", t);
172172
len = atoi(&t[2]);
173-
val = buffer_read_string(&input, len);
174-
if (!val || strlen(val) != len)
173+
strbuf_reset(&val);
174+
buffer_read_binary(&input, &val, len);
175+
if (val.len < len)
175176
die_short_read();
176177

177178
/* Discard trailing newline. */
178179
ch = buffer_read_char(&input);
179180
if (ch == EOF)
180181
die_short_read();
181182
if (ch != '\n')
182-
die("invalid dump: expected newline after %s", val);
183+
die("invalid dump: expected newline after %s", val.buf);
183184

184185
switch (type) {
185186
case 'K':
187+
strbuf_swap(&key, &val);
188+
continue;
186189
case 'D':
187-
strbuf_reset(&key);
188-
if (val)
189-
strbuf_add(&key, val, len);
190-
if (type == 'K')
191-
continue;
192-
assert(type == 'D');
193-
val = NULL;
194-
len = 0;
195-
/* fall through */
190+
handle_property(&val, NULL, 0, &type_set);
191+
continue;
196192
case 'V':
197-
handle_property(&key, val, len, &type_set);
193+
handle_property(&key, val.buf, len, &type_set);
198194
strbuf_reset(&key);
199195
continue;
200196
default:

0 commit comments

Comments
 (0)