Skip to content

Commit 195b7ca

Browse files
committed
vcs-svn: handle log message with embedded NUL
Pass the log message by strbuf instead of as a C-style string and use fwrite instead of printf to write it to fast-import so embedded '\0' bytes can be preserved. Currently "git log" doesn't show the embedded NULs but "git cat-file commit" can. While at it, stop including system headers from repo_tree.h. git source files need to include git-compat-util.h (or cache.h or builtin.h) sooner to ensure the appropriate feature test macros are defined. Signed-off-by: Jonathan Nieder <[email protected]>
1 parent 4c3169b commit 195b7ca

File tree

6 files changed

+94
-13
lines changed

6 files changed

+94
-13
lines changed

t/t9010-svn-fe.sh

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,83 @@ test_expect_success 'NUL in property value' '
397397
test_cmp expect.message actual.message
398398
'
399399

400+
test_expect_success 'NUL in log message, file content, and property name' '
401+
# Caveat: svnadmin 1.6.16 (r1073529) truncates at \0 in the
402+
# svn:specialQnotreally example.
403+
reinit_git &&
404+
cat >expect <<-\EOF &&
405+
OBJID
406+
:100644 100644 OBJID OBJID M greeting
407+
OBJID
408+
:000000 100644 OBJID OBJID A greeting
409+
EOF
410+
printf "\n%s" "something with an ASCII NUL (Q)" >expect.message &&
411+
printf "%s\n" "helQo" >expect.hello1 &&
412+
printf "%s\n" "link hello" >expect.hello2 &&
413+
{
414+
properties svn:log "something with an ASCII NUL (Q)" &&
415+
echo PROPS-END
416+
} |
417+
q_to_nul >props &&
418+
{
419+
q_to_nul <<-\EOF &&
420+
SVN-fs-dump-format-version: 3
421+
422+
Revision-number: 1
423+
Prop-content-length: 10
424+
Content-length: 10
425+
426+
PROPS-END
427+
428+
Node-path: greeting
429+
Node-kind: file
430+
Node-action: add
431+
Prop-content-length: 10
432+
Text-content-length: 6
433+
Content-length: 16
434+
435+
PROPS-END
436+
helQo
437+
438+
Revision-number: 2
439+
EOF
440+
echo Prop-content-length: $(wc -c <props) &&
441+
echo Content-length: $(wc -c <props) &&
442+
echo &&
443+
cat props &&
444+
q_to_nul <<-\EOF
445+
446+
Node-path: greeting
447+
Node-kind: file
448+
Node-action: change
449+
Prop-content-length: 43
450+
Text-content-length: 11
451+
Content-length: 54
452+
453+
K 21
454+
svn:specialQnotreally
455+
V 1
456+
*
457+
PROPS-END
458+
link hello
459+
EOF
460+
} >8bitclean.dump &&
461+
test-svn-fe 8bitclean.dump >stream &&
462+
git fast-import <stream &&
463+
{
464+
git rev-list HEAD |
465+
git diff-tree --root --stdin |
466+
sed "s/$_x40/OBJID/g"
467+
} >actual &&
468+
git cat-file commit HEAD | nul_to_q | sed -ne "/^\$/,\$ p" >actual.message &&
469+
git cat-file blob HEAD^:greeting | nul_to_q >actual.hello1 &&
470+
git cat-file blob HEAD:greeting | nul_to_q >actual.hello2 &&
471+
test_cmp expect actual &&
472+
test_cmp expect.message actual.message &&
473+
test_cmp expect.hello1 actual.hello1 &&
474+
test_cmp expect.hello2 actual.hello2
475+
'
476+
400477
test_expect_success 'change file mode and reiterate content' '
401478
reinit_git &&
402479
cat >expect <<-\EOF &&

vcs-svn/fast_export.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@ void fast_export_modify(uint32_t depth, uint32_t *path, uint32_t mode,
3131
}
3232

3333
static char gitsvnline[MAX_GITSVN_LINE_LEN];
34-
void fast_export_commit(uint32_t revision, const char *author, char *log,
34+
void fast_export_commit(uint32_t revision, const char *author,
35+
const struct strbuf *log,
3536
const char *uuid, const char *url,
3637
unsigned long timestamp)
3738
{
39+
static const struct strbuf empty = STRBUF_INIT;
3840
if (!log)
39-
log = "";
41+
log = &empty;
4042
if (*uuid && *url) {
4143
snprintf(gitsvnline, MAX_GITSVN_LINE_LEN,
4244
"\n\ngit-svn-id: %s@%"PRIu32" %s\n",
@@ -49,9 +51,9 @@ void fast_export_commit(uint32_t revision, const char *author, char *log,
4951
*author ? author : "nobody",
5052
*author ? author : "nobody",
5153
*uuid ? uuid : "local", timestamp);
52-
printf("data %"PRIu32"\n%s%s\n",
53-
(uint32_t) (strlen(log) + strlen(gitsvnline)),
54-
log, gitsvnline);
54+
printf("data %"PRIuMAX"\n", log->len + strlen(gitsvnline));
55+
fwrite(log->buf, log->len, 1, stdout);
56+
printf("%s\n", gitsvnline);
5557
if (!first_commit_done) {
5658
if (revision > 1)
5759
printf("from refs/heads/master^0\n");

vcs-svn/fast_export.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
#define FAST_EXPORT_H_
33

44
#include "line_buffer.h"
5+
struct strbuf;
56

67
void fast_export_delete(uint32_t depth, uint32_t *path);
78
void fast_export_modify(uint32_t depth, uint32_t *path, uint32_t mode,
89
uint32_t mark);
9-
void fast_export_commit(uint32_t revision, const char *author, char *log,
10-
const char *uuid, const char *url,
11-
unsigned long timestamp);
10+
void fast_export_commit(uint32_t revision, const char *author,
11+
const struct strbuf *log, const char *uuid,
12+
const char *url, unsigned long timestamp);
1213
void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len,
1314
struct line_buffer *input);
1415

vcs-svn/repo_tree.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,9 @@ void repo_diff(uint32_t r1, uint32_t r2)
278278
repo_commit_root_dir(commit_pointer(r2)));
279279
}
280280

281-
void repo_commit(uint32_t revision, const char *author, char *log,
282-
const char *uuid, const char *url, unsigned long timestamp)
281+
void repo_commit(uint32_t revision, const char *author,
282+
const struct strbuf *log, const char *uuid, const char *url,
283+
unsigned long timestamp)
283284
{
284285
fast_export_commit(revision, author, log, uuid, url, timestamp);
285286
dent_commit();

vcs-svn/repo_tree.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef REPO_TREE_H_
22
#define REPO_TREE_H_
33

4-
#include "git-compat-util.h"
4+
struct strbuf;
55

66
#define REPO_MODE_DIR 0040000
77
#define REPO_MODE_BLB 0100644
@@ -18,7 +18,7 @@ uint32_t repo_read_path(const uint32_t *path);
1818
uint32_t repo_read_mode(const uint32_t *path);
1919
void repo_delete(uint32_t *path);
2020
void repo_commit(uint32_t revision, const char *author,
21-
char *log, const char *uuid, const char *url,
21+
const struct strbuf *log, const char *uuid, const char *url,
2222
long unsigned timestamp);
2323
void repo_diff(uint32_t r1, uint32_t r2);
2424
void repo_init(void);

vcs-svn/svndump.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ static void handle_revision(void)
274274
{
275275
if (rev_ctx.revision)
276276
repo_commit(rev_ctx.revision, rev_ctx.author.buf,
277-
rev_ctx.log.buf, dump_ctx.uuid.buf, dump_ctx.url.buf,
277+
&rev_ctx.log, dump_ctx.uuid.buf, dump_ctx.url.buf,
278278
rev_ctx.timestamp);
279279
}
280280

0 commit comments

Comments
 (0)