Skip to content

Commit

Permalink
Merge branch 'jk/pkt-line-cleanup'
Browse files Browse the repository at this point in the history
Clean up pkt-line API, implementation and its callers to make them
more robust.

* jk/pkt-line-cleanup:
  do not use GIT_TRACE_PACKET=3 in tests
  remote-curl: always parse incoming refs
  remote-curl: move ref-parsing code up in file
  remote-curl: pass buffer straight to get_remote_heads
  teach get_remote_heads to read from a memory buffer
  pkt-line: share buffer/descriptor reading implementation
  pkt-line: provide a LARGE_PACKET_MAX static buffer
  pkt-line: move LARGE_PACKET_MAX definition from sideband
  pkt-line: teach packet_read_line to chomp newlines
  pkt-line: provide a generic reading function with options
  pkt-line: drop safe_write function
  pkt-line: move a misplaced comment
  write_or_die: raise SIGPIPE when we get EPIPE
  upload-archive: use argv_array to store client arguments
  upload-archive: do not copy repo name
  send-pack: prefer prefixcmp over memcmp in receive_status
  fetch-pack: fix out-of-bounds buffer offset in get_ack
  upload-pack: remove packet debugging harness
  upload-pack: do not add duplicate objects to shallow list
  upload-pack: use get_sha1_hex to parse "shallow" lines
  • Loading branch information
Junio C Hamano committed Apr 1, 2013
2 parents 900c8ec + 2ad2327 commit e013bda
Show file tree
Hide file tree
Showing 22 changed files with 338 additions and 365 deletions.
17 changes: 7 additions & 10 deletions builtin/archive.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ static int run_remote_archiver(int argc, const char **argv,
const char *remote, const char *exec,
const char *name_hint)
{
char buf[LARGE_PACKET_MAX];
int fd[2], i, len, rv;
char *buf;
int fd[2], i, rv;
struct transport *transport;
struct remote *_remote;

Expand All @@ -53,21 +53,18 @@ static int run_remote_archiver(int argc, const char **argv,
packet_write(fd[1], "argument %s\n", argv[i]);
packet_flush(fd[1]);

len = packet_read_line(fd[0], buf, sizeof(buf));
if (!len)
buf = packet_read_line(fd[0], NULL);
if (!buf)
die(_("git archive: expected ACK/NAK, got EOF"));
if (buf[len-1] == '\n')
buf[--len] = 0;
if (strcmp(buf, "ACK")) {
if (len > 5 && !prefixcmp(buf, "NACK "))
if (!prefixcmp(buf, "NACK "))
die(_("git archive: NACK %s"), buf + 5);
if (len > 4 && !prefixcmp(buf, "ERR "))
if (!prefixcmp(buf, "ERR "))
die(_("remote error: %s"), buf + 4);
die(_("git archive: protocol error"));
}

len = packet_read_line(fd[0], buf, sizeof(buf));
if (len)
if (packet_read_line(fd[0], NULL))
die(_("git archive: expected a flush"));

/* Now, start reading from fd[0] and spit it out to stdout */
Expand Down
11 changes: 4 additions & 7 deletions builtin/fetch-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,11 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
/* in stateless RPC mode we use pkt-line to read
* from stdin, until we get a flush packet
*/
static char line[1000];
for (;;) {
int n = packet_read_line(0, line, sizeof(line));
if (!n)
char *line = packet_read_line(0, NULL);
if (!line)
break;
if (line[n-1] == '\n')
n--;
add_sought_entry_mem(&sought, &nr_sought, &alloc_sought, line, n);
add_sought_entry(&sought, &nr_sought, &alloc_sought, line);
}
}
else {
Expand All @@ -147,7 +144,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
args.verbose ? CONNECT_VERBOSE : 0);
}

get_remote_heads(fd[0], &ref, 0, NULL);
get_remote_heads(fd[0], NULL, 0, &ref, 0, NULL);

ref = fetch_pack(&args, fd, conn, ref, dest,
sought, nr_sought, pack_lockfile_ptr);
Expand Down
10 changes: 4 additions & 6 deletions builtin/receive-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -754,17 +754,15 @@ static struct command *read_head_info(void)
struct command *commands = NULL;
struct command **p = &commands;
for (;;) {
static char line[1000];
char *line;
unsigned char old_sha1[20], new_sha1[20];
struct command *cmd;
char *refname;
int len, reflen;

len = packet_read_line(0, line, sizeof(line));
if (!len)
line = packet_read_line(0, &len);
if (!line)
break;
if (line[len-1] == '\n')
line[--len] = 0;
if (len < 83 ||
line[40] != ' ' ||
line[81] != ' ' ||
Expand Down Expand Up @@ -932,7 +930,7 @@ static void report(struct command *commands, const char *unpack_status)
if (use_sideband)
send_sideband(1, 1, buf.buf, buf.len, use_sideband);
else
safe_write(1, buf.buf, buf.len);
write_or_die(1, buf.buf, buf.len);
strbuf_release(&buf);
}

Expand Down
4 changes: 2 additions & 2 deletions builtin/send-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static void print_helper_status(struct ref *ref)
}
strbuf_addch(&buf, '\n');

safe_write(1, buf.buf, buf.len);
write_or_die(1, buf.buf, buf.len);
}
strbuf_release(&buf);
}
Expand Down Expand Up @@ -207,7 +207,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)

memset(&extra_have, 0, sizeof(extra_have));

get_remote_heads(fd[0], &remote_refs, REF_NORMAL, &extra_have);
get_remote_heads(fd[0], NULL, 0, &remote_refs, REF_NORMAL, &extra_have);

transport_verify_remote_names(nr_refspecs, refspecs);

Expand Down
45 changes: 13 additions & 32 deletions builtin/upload-archive.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "pkt-line.h"
#include "sideband.h"
#include "run-command.h"
#include "argv-array.h"

static const char upload_archive_usage[] =
"git upload-archive <repo>";
Expand All @@ -18,51 +19,31 @@ static const char deadchild[] =

int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix)
{
const char *sent_argv[MAX_ARGS];
struct argv_array sent_argv = ARGV_ARRAY_INIT;
const char *arg_cmd = "argument ";
char *p, buf[4096];
int sent_argc;
int len;

if (argc != 2)
usage(upload_archive_usage);

if (strlen(argv[1]) + 1 > sizeof(buf))
die("insanely long repository name");

strcpy(buf, argv[1]); /* enter-repo smudges its argument */

if (!enter_repo(buf, 0))
die("'%s' does not appear to be a git repository", buf);
if (!enter_repo(argv[1], 0))
die("'%s' does not appear to be a git repository", argv[1]);

/* put received options in sent_argv[] */
sent_argc = 1;
sent_argv[0] = "git-upload-archive";
for (p = buf;;) {
/* This will die if not enough free space in buf */
len = packet_read_line(0, p, (buf + sizeof buf) - p);
if (len == 0)
argv_array_push(&sent_argv, "git-upload-archive");
for (;;) {
char *buf = packet_read_line(0, NULL);
if (!buf)
break; /* got a flush */
if (sent_argc > MAX_ARGS - 2)
die("Too many options (>%d)", MAX_ARGS - 2);
if (sent_argv.argc > MAX_ARGS)
die("Too many options (>%d)", MAX_ARGS - 1);

if (p[len-1] == '\n') {
p[--len] = 0;
}
if (len < strlen(arg_cmd) ||
strncmp(arg_cmd, p, strlen(arg_cmd)))
if (prefixcmp(buf, arg_cmd))
die("'argument' token or flush expected");

len -= strlen(arg_cmd);
memmove(p, p + strlen(arg_cmd), len);
sent_argv[sent_argc++] = p;
p += len;
*p++ = 0;
argv_array_push(&sent_argv, buf + strlen(arg_cmd));
}
sent_argv[sent_argc] = NULL;

/* parse all options sent by the client */
return write_archive(sent_argc, sent_argv, prefix, 0, NULL, 1);
return write_archive(sent_argv.argc, sent_argv.argv, prefix, 0, NULL, 1);
}

__attribute__((format (printf, 1, 2)))
Expand Down
4 changes: 3 additions & 1 deletion cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -1064,7 +1064,9 @@ struct extra_have_objects {
int nr, alloc;
unsigned char (*array)[20];
};
extern struct ref **get_remote_heads(int in, struct ref **list, unsigned int flags, struct extra_have_objects *);
extern struct ref **get_remote_heads(int in, char *src_buf, size_t src_len,
struct ref **list, unsigned int flags,
struct extra_have_objects *);
extern int server_supports(const char *feature);
extern int parse_feature_request(const char *features, const char *feature);
extern const char *server_feature_value(const char *feature, int *len_ret);
Expand Down
13 changes: 7 additions & 6 deletions connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ static void die_initial_contact(int got_at_least_one_head)
/*
* Read all the refs from the other end
*/
struct ref **get_remote_heads(int in, struct ref **list,
unsigned int flags,
struct ref **get_remote_heads(int in, char *src_buf, size_t src_len,
struct ref **list, unsigned int flags,
struct extra_have_objects *extra_have)
{
int got_at_least_one_head = 0;
Expand All @@ -72,18 +72,19 @@ struct ref **get_remote_heads(int in, struct ref **list,
for (;;) {
struct ref *ref;
unsigned char old_sha1[20];
static char buffer[1000];
char *name;
int len, name_len;
char *buffer = packet_buffer;

len = packet_read(in, buffer, sizeof(buffer));
len = packet_read(in, &src_buf, &src_len,
packet_buffer, sizeof(packet_buffer),
PACKET_READ_GENTLE_ON_EOF |
PACKET_READ_CHOMP_NEWLINE);
if (len < 0)
die_initial_contact(got_at_least_one_head);

if (!len)
break;
if (buffer[len-1] == '\n')
buffer[--len] = 0;

if (len > 4 && !prefixcmp(buffer, "ERR "))
die("remote error: %s", buffer + 4);
Expand Down
4 changes: 2 additions & 2 deletions daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,15 +600,15 @@ static void parse_host_arg(char *extra_args, int buflen)

static int execute(void)
{
static char line[1000];
char *line = packet_buffer;
int pktlen, len, i;
char *addr = getenv("REMOTE_ADDR"), *port = getenv("REMOTE_PORT");

if (addr)
loginfo("Connection from %s:%s", addr, port);

alarm(init_timeout ? init_timeout : timeout);
pktlen = packet_read_line(0, line, sizeof(line));
pktlen = packet_read(0, NULL, NULL, packet_buffer, sizeof(packet_buffer), 0);
alarm(0);

len = strlen(line);
Expand Down
18 changes: 9 additions & 9 deletions fetch-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ static void consume_shallow_list(struct fetch_pack_args *args, int fd)
* shallow and unshallow commands every time there
* is a block of have lines exchanged.
*/
char line[1000];
while (packet_read_line(fd, line, sizeof(line))) {
char *line;
while ((line = packet_read_line(fd, NULL))) {
if (!prefixcmp(line, "shallow "))
continue;
if (!prefixcmp(line, "unshallow "))
Expand Down Expand Up @@ -215,17 +215,17 @@ static int write_shallow_commits(struct strbuf *out, int use_pack_protocol)

static enum ack_type get_ack(int fd, unsigned char *result_sha1)
{
static char line[1000];
int len = packet_read_line(fd, line, sizeof(line));
int len;
char *line = packet_read_line(fd, &len);

if (!len)
die("git fetch-pack: expected ACK/NAK, got EOF");
if (line[len-1] == '\n')
line[--len] = 0;
if (!strcmp(line, "NAK"))
return NAK;
if (!prefixcmp(line, "ACK ")) {
if (!get_sha1_hex(line+4, result_sha1)) {
if (len < 45)
return ACK;
if (strstr(line+45, "continue"))
return ACK_continue;
if (strstr(line+45, "common"))
Expand All @@ -245,7 +245,7 @@ static void send_request(struct fetch_pack_args *args,
send_sideband(fd, -1, buf->buf, buf->len, LARGE_PACKET_MAX);
packet_flush(fd);
} else
safe_write(fd, buf->buf, buf->len);
write_or_die(fd, buf->buf, buf->len);
}

static void insert_one_alternate_ref(const struct ref *ref, void *unused)
Expand Down Expand Up @@ -346,11 +346,11 @@ static int find_common(struct fetch_pack_args *args,
state_len = req_buf.len;

if (args->depth > 0) {
char line[1024];
char *line;
unsigned char sha1[20];

send_request(args, fd[1], &req_buf);
while (packet_read_line(fd[0], line, sizeof(line))) {
while ((line = packet_read_line(fd[0], NULL))) {
if (!prefixcmp(line, "shallow ")) {
if (get_sha1_hex(line + 8, sha1))
die("invalid shallow line: %s", line);
Expand Down
8 changes: 4 additions & 4 deletions http-backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ static void format_write(int fd, const char *fmt, ...)
if (n >= sizeof(buffer))
die("protocol error: impossibly long line");

safe_write(fd, buffer, n);
write_or_die(fd, buffer, n);
}

static void http_status(unsigned code, const char *msg)
Expand Down Expand Up @@ -111,7 +111,7 @@ static void hdr_cache_forever(void)

static void end_headers(void)
{
safe_write(1, "\r\n", 2);
write_or_die(1, "\r\n", 2);
}

__attribute__((format (printf, 1, 2)))
Expand Down Expand Up @@ -157,7 +157,7 @@ static void send_strbuf(const char *type, struct strbuf *buf)
hdr_int(content_length, buf->len);
hdr_str(content_type, type);
end_headers();
safe_write(1, buf->buf, buf->len);
write_or_die(1, buf->buf, buf->len);
}

static void send_local_file(const char *the_type, const char *name)
Expand Down Expand Up @@ -185,7 +185,7 @@ static void send_local_file(const char *the_type, const char *name)
die_errno("Cannot read '%s'", p);
if (!n)
break;
safe_write(1, buf, n);
write_or_die(1, buf, n);
}
close(fd);
free(buf);
Expand Down
1 change: 1 addition & 0 deletions http.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "url.h"
#include "credential.h"
#include "version.h"
#include "pkt-line.h"

int active_requests;
int http_is_verbose;
Expand Down
Loading

0 comments on commit e013bda

Please sign in to comment.