Skip to content

Commit 8ada1d8

Browse files
committed
Merge branch 'jk/always-allow-large-packets'
"git push" and "git fetch" did not communicate an overlong refname correctly. * jk/always-allow-large-packets: pkt-line: allow writing of LARGE_PACKET_MAX buffers
2 parents 3dadfc7 + 8e9faf2 commit 8ada1d8

File tree

2 files changed

+52
-18
lines changed

2 files changed

+52
-18
lines changed

pkt-line.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -64,44 +64,45 @@ void packet_buf_flush(struct strbuf *buf)
6464
}
6565

6666
#define hex(a) (hexchar[(a) & 15])
67-
static char buffer[1000];
68-
static unsigned format_packet(const char *fmt, va_list args)
67+
static void format_packet(struct strbuf *out, const char *fmt, va_list args)
6968
{
7069
static char hexchar[] = "0123456789abcdef";
71-
unsigned n;
70+
size_t orig_len, n;
7271

73-
n = vsnprintf(buffer + 4, sizeof(buffer) - 4, fmt, args);
74-
if (n >= sizeof(buffer)-4)
72+
orig_len = out->len;
73+
strbuf_addstr(out, "0000");
74+
strbuf_vaddf(out, fmt, args);
75+
n = out->len - orig_len;
76+
77+
if (n > LARGE_PACKET_MAX)
7578
die("protocol error: impossibly long line");
76-
n += 4;
77-
buffer[0] = hex(n >> 12);
78-
buffer[1] = hex(n >> 8);
79-
buffer[2] = hex(n >> 4);
80-
buffer[3] = hex(n);
81-
packet_trace(buffer+4, n-4, 1);
82-
return n;
79+
80+
out->buf[orig_len + 0] = hex(n >> 12);
81+
out->buf[orig_len + 1] = hex(n >> 8);
82+
out->buf[orig_len + 2] = hex(n >> 4);
83+
out->buf[orig_len + 3] = hex(n);
84+
packet_trace(out->buf + orig_len + 4, n - 4, 1);
8385
}
8486

8587
void packet_write(int fd, const char *fmt, ...)
8688
{
89+
static struct strbuf buf = STRBUF_INIT;
8790
va_list args;
88-
unsigned n;
8991

92+
strbuf_reset(&buf);
9093
va_start(args, fmt);
91-
n = format_packet(fmt, args);
94+
format_packet(&buf, fmt, args);
9295
va_end(args);
93-
write_or_die(fd, buffer, n);
96+
write_or_die(fd, buf.buf, buf.len);
9497
}
9598

9699
void packet_buf_write(struct strbuf *buf, const char *fmt, ...)
97100
{
98101
va_list args;
99-
unsigned n;
100102

101103
va_start(args, fmt);
102-
n = format_packet(fmt, args);
104+
format_packet(buf, fmt, args);
103105
va_end(args);
104-
strbuf_add(buf, buffer, n);
105106
}
106107

107108
static int get_packet_data(int fd, char **src_buf, size_t *src_size,

t/t5527-fetch-odd-refs.sh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,37 @@ test_expect_success 'suffix ref is ignored during fetch' '
2626
test_cmp expect actual
2727
'
2828

29+
test_expect_success 'try to create repo with absurdly long refname' '
30+
ref240=$_z40/$_z40/$_z40/$_z40/$_z40/$_z40 &&
31+
ref1440=$ref240/$ref240/$ref240/$ref240/$ref240/$ref240 &&
32+
git init long &&
33+
(
34+
cd long &&
35+
test_commit long &&
36+
test_commit master
37+
) &&
38+
if git -C long update-ref refs/heads/$ref1440 long; then
39+
test_set_prereq LONG_REF
40+
else
41+
echo >&2 "long refs not supported"
42+
fi
43+
'
44+
45+
test_expect_success LONG_REF 'fetch handles extremely long refname' '
46+
git fetch long refs/heads/*:refs/remotes/long/* &&
47+
cat >expect <<-\EOF &&
48+
long
49+
master
50+
EOF
51+
git for-each-ref --format="%(subject)" refs/remotes/long >actual &&
52+
test_cmp expect actual
53+
'
54+
55+
test_expect_success LONG_REF 'push handles extremely long refname' '
56+
git push long :refs/heads/$ref1440 &&
57+
git -C long for-each-ref --format="%(subject)" refs/heads >actual &&
58+
echo master >expect &&
59+
test_cmp expect actual
60+
'
61+
2962
test_done

0 commit comments

Comments
 (0)