summaryrefslogtreecommitdiff
path: root/usr.bin/cvs
diff options
context:
space:
mode:
authorNiall O'Higgins <niallo@cvs.openbsd.org>2007-01-11 17:44:19 +0000
committerNiall O'Higgins <niallo@cvs.openbsd.org>2007-01-11 17:44:19 +0000
commitd85c0dc058186c85cfed44b898af95f7d7ec453d (patch)
treea7da1e2066182857b36823351e715a72d4a32795 /usr.bin/cvs
parent97a8f0e03dbb1ac15c84940d8f111ff4fedfe002 (diff)
rework opencvs so that we can deal with binary files. previously we assumed all files were ascii,
which broke things in real-world usage. now a checkout of src should work, albeit using lots of memory and cpu. fixing this is the next step. testing by many. ok & some input joris@
Diffstat (limited to 'usr.bin/cvs')
-rw-r--r--usr.bin/cvs/annotate.c6
-rw-r--r--usr.bin/cvs/diff3.c23
-rw-r--r--usr.bin/cvs/rcs.c52
-rw-r--r--usr.bin/cvs/update.c9
-rw-r--r--usr.bin/cvs/util.c55
-rw-r--r--usr.bin/cvs/util.h11
6 files changed, 87 insertions, 69 deletions
diff --git a/usr.bin/cvs/annotate.c b/usr.bin/cvs/annotate.c
index 5e26f7a425f..50a2440fca4 100644
--- a/usr.bin/cvs/annotate.c
+++ b/usr.bin/cvs/annotate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: annotate.c,v 1.33 2007/01/11 02:35:55 joris Exp $ */
+/* $OpenBSD: annotate.c,v 1.34 2007/01/11 17:44:18 niallo Exp $ */
/*
* Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org>
*
@@ -112,6 +112,7 @@ cvs_annotate_local(struct cvs_file *cf)
BUF *b;
RCSNUM *ann_rev;
char *content;
+ size_t len;
ann_rev = NULL;
@@ -136,8 +137,9 @@ cvs_annotate_local(struct cvs_file *cf)
b = rcs_getrev(cf->file_rcs, ann_rev);
cvs_buf_putc(b, '\0');
+ len = cvs_buf_len(b);
content = cvs_buf_release(b);
- if ((lines = cvs_splitlines(content)) == NULL)
+ if ((lines = cvs_splitlines(content, len)) == NULL)
fatal("cvs_annotate_local: cvs_splitlines failed");
xfree(content);
diff --git a/usr.bin/cvs/diff3.c b/usr.bin/cvs/diff3.c
index e6df284e4ad..8dc97f1f011 100644
--- a/usr.bin/cvs/diff3.c
+++ b/usr.bin/cvs/diff3.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: diff3.c,v 1.29 2006/11/10 08:32:37 xsa Exp $ */
+/* $OpenBSD: diff3.c,v 1.30 2007/01/11 17:44:18 niallo Exp $ */
/*
* Copyright (C) Caldera International Inc. 2001-2002.
@@ -72,7 +72,7 @@ static const char copyright[] =
#ifndef lint
static const char rcsid[] =
- "$OpenBSD: diff3.c,v 1.29 2006/11/10 08:32:37 xsa Exp $";
+ "$OpenBSD: diff3.c,v 1.30 2007/01/11 17:44:18 niallo Exp $";
#endif /* not lint */
#include "includes.h"
@@ -163,6 +163,7 @@ cvs_diff3(RCSFILE *rf, char *workfile, int workfd, RCSNUM *rev1,
char *argv[5], r1[16], r2[16];
char *dp13, *dp23, *path1, *path2, *path3;
BUF *b1, *b2, *b3, *d1, *d2, *diffb;
+ size_t dlen, plen;
b1 = b2 = b3 = d1 = d2 = diffb = NULL;
@@ -230,11 +231,13 @@ cvs_diff3(RCSFILE *rf, char *workfile, int workfd, RCSNUM *rev1,
cvs_buf_putc(diffb, '\0');
cvs_buf_putc(b1, '\0');
+ plen = cvs_buf_len(diffb);
patch = cvs_buf_release(diffb);
+ dlen = cvs_buf_len(b1);
data = cvs_buf_release(b1);
diffb = b1 = NULL;
- if ((diffb = cvs_patchfile(data, patch, ed_patch_lines)) == NULL)
+ if ((diffb = cvs_patchfile(data, dlen, patch, plen, ed_patch_lines)) == NULL)
goto out;
if (verbose == 1 && diff3_conflicts != 0) {
@@ -319,6 +322,7 @@ ed_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines)
char op, *ep;
struct cvs_line *sort, *lp, *dlp, *ndlp, *insert_after;
int start, end, i, lineno;
+ u_char tmp;
dlp = TAILQ_FIRST(&(dlines->l_lines));
lp = TAILQ_FIRST(&(plines->l_lines));
@@ -326,10 +330,17 @@ ed_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines)
end = 0;
for (lp = TAILQ_NEXT(lp, l_list); lp != NULL;
lp = TAILQ_NEXT(lp, l_list)) {
- if (lp->l_line[0] == '\0')
- fatal("ed_patch_lines");
+ /* Skip blank lines */
+ if (lp->l_len < 2)
+ continue;
+ /* NUL-terminate line buffer for strtol() safety. */
+ tmp = lp->l_line[lp->l_len - 1];
+ lp->l_line[lp->l_len - 1] = '\0';
+ /* len - 1 is NUL terminator so we use len - 2 for 'op' */
op = lp->l_line[strlen(lp->l_line) - 1];
start = (int)strtol(lp->l_line, &ep, 10);
+ /* Restore the last byte of the buffer */
+ lp->l_line[lp->l_len - 1] = tmp;
if (op == 'a') {
if (start > dlines->l_nblines ||
start < 0 || *ep != 'a')
@@ -386,7 +397,7 @@ ed_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines)
if (lp == NULL)
fatal("ed_patch_lines");
- if (!strcmp(lp->l_line, "."))
+ if (!memcmp(lp->l_line, ".", 1))
break;
TAILQ_REMOVE(&(plines->l_lines), lp, l_list);
diff --git a/usr.bin/cvs/rcs.c b/usr.bin/cvs/rcs.c
index 65a4a812c50..7084d97fd56 100644
--- a/usr.bin/cvs/rcs.c
+++ b/usr.bin/cvs/rcs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rcs.c,v 1.192 2006/12/21 15:03:15 niallo Exp $ */
+/* $OpenBSD: rcs.c,v 1.193 2007/01/11 17:44:18 niallo Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -493,11 +493,6 @@ rcs_write(RCSFILE *rfp)
fputs("@\ntext\n@", fp);
if (rdp->rd_text != NULL) {
rcs_strprint(rdp->rd_text, rdp->rd_tlen, fp);
-
- if (rdp->rd_tlen != 0) {
- if (rdp->rd_text[rdp->rd_tlen-1] != '\n')
- fputc('\n', fp);
- }
}
fputs("@\n", fp);
}
@@ -1078,6 +1073,7 @@ rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines)
char op, *ep;
struct cvs_line *lp, *dlp, *ndlp;
int i, lineno, nbln;
+ u_char tmp;
dlp = TAILQ_FIRST(&(dlines->l_lines));
lp = TAILQ_FIRST(&(plines->l_lines));
@@ -1085,15 +1081,21 @@ rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines)
/* skip first bogus line */
for (lp = TAILQ_NEXT(lp, l_list); lp != NULL;
lp = TAILQ_NEXT(lp, l_list)) {
+ if (lp->l_len < 2)
+ fatal("line too short, RCS patch seems broken");
op = *(lp->l_line);
+ /* NUL-terminate line buffer for strtol() safety. */
+ tmp = lp->l_line[lp->l_len - 1];
+ lp->l_line[lp->l_len - 1] = '\0';
lineno = (int)strtol((lp->l_line + 1), &ep, 10);
- if (lineno > dlines->l_nblines || lineno < 0 ||
- *ep != ' ')
- fatal("invalid line specification in RCS patch: %s",
- ep);
+ if (lineno - 1 > dlines->l_nblines || lineno < 0) {
+ fatal("invalid line specification in RCS patch");
+ }
ep++;
nbln = (int)strtol(ep, &ep, 10);
- if (nbln < 0 || *ep != '\0')
+ /* Restore the last byte of the buffer */
+ lp->l_line[lp->l_len - 1] = tmp;
+ if (nbln < 0)
fatal("invalid line number specification in RCS patch");
/* find the appropriate line */
@@ -1170,13 +1172,13 @@ rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines)
BUF*
rcs_getrev(RCSFILE *rfp, RCSNUM *frev)
{
- size_t i;
+ size_t i, dlen, plen;
int done, nextroot, found;
BUF *rcsbuf;
RCSNUM *tnum, *bnum;
struct rcs_branch *brp;
struct rcs_delta *hrdp, *trdp, *rdp;
- char *data;
+ u_char *data, *patch;
if ((hrdp = rcs_findrev(rfp, rfp->rf_head)) == NULL)
fatal("rcs_getrev: no HEAD revision");
@@ -1223,13 +1225,15 @@ again:
}
}
- cvs_buf_putc(rcsbuf, '\0');
+ plen = rdp->rd_tlen;
+ dlen = cvs_buf_len(rcsbuf);
+ patch = rdp->rd_text;
data = cvs_buf_release(rcsbuf);
-
- rcsbuf = cvs_patchfile(data, rdp->rd_text, rcs_patch_lines);
+ rcsbuf = cvs_patchfile(data, dlen, patch, plen,
+ rcs_patch_lines);
+ xfree(data);
if (rcsbuf == NULL)
fatal("rcs_getrev: failed to apply rcsdiff");
- xfree(data);
if (!rcsnum_differ(rdp->rd_num, bnum))
break;
@@ -2102,11 +2106,15 @@ rcs_parse_deltatext(RCSFILE *rfp)
return (-1);
}
- rdp->rd_text = xmalloc(RCS_TOKLEN(rfp) + 1);
- if (strlcpy(rdp->rd_text, RCS_TOKSTR(rfp), (RCS_TOKLEN(rfp) + 1)) >=
- RCS_TOKLEN(rfp) + 1)
- fatal("rcs_parse_deltatext: strlcpy");
- rdp->rd_tlen = RCS_TOKLEN(rfp);
+ if (RCS_TOKLEN(rfp) == 0) {
+ rdp->rd_text = xmalloc(1);
+ rdp->rd_text[0] = '\0';
+ rdp->rd_tlen = 0;
+ } else {
+ rdp->rd_text = xmalloc(RCS_TOKLEN(rfp));
+ memcpy(rdp->rd_text, RCS_TOKSTR(rfp), RCS_TOKLEN(rfp));
+ rdp->rd_tlen = RCS_TOKLEN(rfp);
+ }
return (1);
}
diff --git a/usr.bin/cvs/update.c b/usr.bin/cvs/update.c
index afe1aae7124..19108f9f73d 100644
--- a/usr.bin/cvs/update.c
+++ b/usr.bin/cvs/update.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: update.c,v 1.82 2007/01/11 02:35:55 joris Exp $ */
+/* $OpenBSD: update.c,v 1.83 2007/01/11 17:44:18 niallo Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -419,6 +419,7 @@ update_has_conflict_markers(struct cvs_file *cf)
char *content;
struct cvs_line *lp;
struct cvs_lines *lines;
+ size_t len;
cvs_log(LP_TRACE, "update_has_conflict_markers(%s)", cf->file_path);
@@ -430,12 +431,11 @@ update_has_conflict_markers(struct cvs_file *cf)
cf->file_path);
cvs_buf_putc(bp, '\0');
+ len = cvs_buf_len(bp);
content = cvs_buf_release(bp);
- if ((lines = cvs_splitlines(content)) == NULL)
+ if ((lines = cvs_splitlines(content, len)) == NULL)
fatal("update_has_conflict_markers: failed to split lines");
- xfree(content);
-
conflict = 0;
TAILQ_FOREACH(lp, &(lines->l_lines), l_list) {
if (lp->l_line == NULL)
@@ -453,5 +453,6 @@ update_has_conflict_markers(struct cvs_file *cf)
}
cvs_freelines(lines);
+ xfree(content);
return (conflict);
}
diff --git a/usr.bin/cvs/util.c b/usr.bin/cvs/util.c
index 11c21f59780..34e1de8d0ac 100644
--- a/usr.bin/cvs/util.c
+++ b/usr.bin/cvs/util.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.c,v 1.96 2007/01/07 01:53:12 joris Exp $ */
+/* $OpenBSD: util.c,v 1.97 2007/01/11 17:44:18 niallo Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* Copyright (c) 2005, 2006 Joris Vink <joris@openbsd.org>
@@ -738,32 +738,33 @@ cvs_mkpath(const char *path)
* Split the contents of a file into a list of lines.
*/
struct cvs_lines *
-cvs_splitlines(const char *fcont)
+cvs_splitlines(const u_char *data, size_t len)
{
- char *dcp;
+ u_char *p, *c;
+ size_t i, tlen;
struct cvs_lines *lines;
struct cvs_line *lp;
lines = xmalloc(sizeof(*lines));
+ memset(lines, 0, sizeof(*lines));
TAILQ_INIT(&(lines->l_lines));
- lines->l_nblines = 0;
- lines->l_data = xstrdup(fcont);
lp = xmalloc(sizeof(*lp));
- lp->l_line = NULL;
- lp->l_lineno = 0;
+ memset(lp, 0, sizeof(*lp));
TAILQ_INSERT_TAIL(&(lines->l_lines), lp, l_list);
- for (dcp = lines->l_data; *dcp != '\0';) {
- lp = xmalloc(sizeof(*lp));
- lp->l_line = dcp;
- lp->l_lineno = ++(lines->l_nblines);
- TAILQ_INSERT_TAIL(&(lines->l_lines), lp, l_list);
-
- dcp = strchr(dcp, '\n');
- if (dcp == NULL)
- break;
- *(dcp++) = '\0';
+ p = c = data;
+ for (i = 0; i < len; i++) {
+ if (*p == '\n' || (i == len - 1)) {
+ tlen = p - c + 1;
+ lp = xmalloc(sizeof(*lp));
+ lp->l_line = c;
+ lp->l_len = tlen;
+ lp->l_lineno = ++(lines->l_nblines);
+ TAILQ_INSERT_TAIL(&(lines->l_lines), lp, l_list);
+ c = p + 1;
+ }
+ p++;
}
return (lines);
@@ -779,26 +780,21 @@ cvs_freelines(struct cvs_lines *lines)
xfree(lp);
}
- xfree(lines->l_data);
xfree(lines);
}
BUF *
-cvs_patchfile(const char *data, const char *patch,
+cvs_patchfile(const u_char *data, size_t dlen, const u_char *patch, size_t plen,
int (*p)(struct cvs_lines *, struct cvs_lines *))
{
struct cvs_lines *dlines, *plines;
struct cvs_line *lp;
- size_t len;
- int lineno;
BUF *res;
- len = strlen(data);
-
- if ((dlines = cvs_splitlines(data)) == NULL)
+ if ((dlines = cvs_splitlines(data, dlen)) == NULL)
return (NULL);
- if ((plines = cvs_splitlines(patch)) == NULL)
+ if ((plines = cvs_splitlines(patch, plen)) == NULL)
return (NULL);
if (p(dlines, plines) < 0) {
@@ -807,12 +803,11 @@ cvs_patchfile(const char *data, const char *patch,
return (NULL);
}
- lineno = 0;
- res = cvs_buf_alloc(len, BUF_AUTOEXT);
+ res = cvs_buf_alloc(1024, BUF_AUTOEXT);
TAILQ_FOREACH(lp, &dlines->l_lines, l_list) {
- if (lineno != 0)
- cvs_buf_fappend(res, "%s\n", lp->l_line);
- lineno++;
+ if (lp->l_line == NULL)
+ continue;
+ cvs_buf_append(res, lp->l_line, lp->l_len);
}
cvs_freelines(dlines);
diff --git a/usr.bin/cvs/util.h b/usr.bin/cvs/util.h
index c7e89dd859e..1441e6fce2b 100644
--- a/usr.bin/cvs/util.h
+++ b/usr.bin/cvs/util.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.h,v 1.12 2007/01/07 01:53:12 joris Exp $ */
+/* $OpenBSD: util.h,v 1.13 2007/01/11 17:44:18 niallo Exp $ */
/*
* Copyright (c) 2006 Niall O'Higgins <niallo@openbsd.org>
* All rights reserved.
@@ -50,6 +50,7 @@ u_int cvs_revision_select(RCSFILE *, char *);
struct cvs_line {
char *l_line;
+ size_t l_len;
int l_lineno;
TAILQ_ENTRY(cvs_line) l_list;
};
@@ -58,7 +59,6 @@ TAILQ_HEAD(cvs_tqh, cvs_line);
struct cvs_lines {
int l_nblines;
- char *l_data;
struct cvs_tqh l_lines;
};
@@ -67,9 +67,10 @@ struct cvs_argvector {
char **argv;
};
-BUF *cvs_patchfile(const char *, const char *,
- int (*p)(struct cvs_lines *, struct cvs_lines *));
-struct cvs_lines *cvs_splitlines(const char *);
+BUF *cvs_patchfile(const u_char *, size_t, const u_char *,
+ size_t, int (*p)(struct cvs_lines *,
+ struct cvs_lines *));
+struct cvs_lines *cvs_splitlines(const u_char *, size_t);
void cvs_freelines(struct cvs_lines *);
struct cvs_argvector *cvs_strsplit(char *, const char *);
void cvs_argv_destroy(struct cvs_argvector *);