summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Stoeckmann <tobias@cvs.openbsd.org>2008-06-14 04:34:09 +0000
committerTobias Stoeckmann <tobias@cvs.openbsd.org>2008-06-14 04:34:09 +0000
commit5267e13e6a0385ddc7c3db92e270bfc435bb4315 (patch)
treebd55b1a2655cc43467d17b0f982a8456c90ca222
parent7d54e7807fd98844ba963369bffbc1a25397f82b (diff)
Conforming to RCS specification, it is possible but unlikely to encounter
an RCS file which has no head revision set. Some commands actually can work with them (log, status) so support these files. Fixes A LOT of possible segmentation faults. ok joris
-rw-r--r--usr.bin/cvs/add.c20
-rw-r--r--usr.bin/cvs/admin.c8
-rw-r--r--usr.bin/cvs/annotate.c4
-rw-r--r--usr.bin/cvs/checkout.c4
-rw-r--r--usr.bin/cvs/commit.c9
-rw-r--r--usr.bin/cvs/diff.c8
-rw-r--r--usr.bin/cvs/getlog.c4
-rw-r--r--usr.bin/cvs/import.c5
-rw-r--r--usr.bin/cvs/rcs.c29
-rw-r--r--usr.bin/cvs/status.c28
-rw-r--r--usr.bin/cvs/update.c37
11 files changed, 102 insertions, 54 deletions
diff --git a/usr.bin/cvs/add.c b/usr.bin/cvs/add.c
index b0c35f877d6..c5e5fbc67b2 100644
--- a/usr.bin/cvs/add.c
+++ b/usr.bin/cvs/add.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: add.c,v 1.103 2008/06/14 03:19:15 joris Exp $ */
+/* $OpenBSD: add.c,v 1.104 2008/06/14 04:34:07 tobias Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2005, 2006 Xavier Santolaria <xsa@openbsd.org>
@@ -335,7 +335,7 @@ add_file(struct cvs_file *cf)
{
int added, nb, stop;
char revbuf[CVS_REV_BUFSZ];
- RCSNUM *head;
+ RCSNUM *head = NULL;
char *tag;
cvs_parse_tagfile(cf->file_wd, &tag, NULL, &nb);
@@ -346,11 +346,11 @@ add_file(struct cvs_file *cf)
if (cf->file_rcs != NULL) {
head = rcs_head_get(cf->file_rcs);
- if (head == NULL)
- fatal("RCS head empty or missing in %s",
- cf->file_rcs->rf_path);
+ if (head == NULL) {
+ cvs_log(LP_NOTICE, "no head revision in RCS file for "
+ "%s", cf->file_path);
+ }
rcsnum_tostr(head, revbuf, sizeof(revbuf));
- rcsnum_free(head);
}
added = stop = 0;
@@ -370,12 +370,7 @@ add_file(struct cvs_file *cf)
add_entry(cf);
/* Restore the file. */
- head = rcs_head_get(cf->file_rcs);
- if (head == NULL)
- fatal("RCS head empty or missing in %s",
- cf->file_rcs->rf_path);
cvs_checkout_file(cf, head, NULL, 0);
- rcsnum_free(head);
cvs_printf("U %s\n", cf->file_path);
@@ -414,6 +409,9 @@ add_file(struct cvs_file *cf)
break;
}
+ if (head != NULL)
+ rcsnum_free(head);
+
if (stop == 1)
return;
diff --git a/usr.bin/cvs/admin.c b/usr.bin/cvs/admin.c
index 15228fcce75..cf78de7d35e 100644
--- a/usr.bin/cvs/admin.c
+++ b/usr.bin/cvs/admin.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: admin.c,v 1.61 2008/06/13 17:15:13 joris Exp $ */
+/* $OpenBSD: admin.c,v 1.62 2008/06/14 04:34:08 tobias Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* Copyright (c) 2005 Joris Vink <joris@openbsd.org>
@@ -364,10 +364,14 @@ cvs_admin_local(struct cvs_file *cf)
xfree(state);
return;
}
- } else {
+ } else if (cf->file_rcs->rf_head != NULL) {
state = xstrdup(statestr);
logrev = rcsnum_alloc();
rcsnum_cpy(cf->file_rcs->rf_head, logrev, 0);
+ } else {
+ cvs_log(LP_ERR, "head revision missing");
+ cvs_argv_destroy(sargv);
+ return;
}
if (rcs_state_check(state) < 0) {
diff --git a/usr.bin/cvs/annotate.c b/usr.bin/cvs/annotate.c
index 2aaf612faf5..eaaa9bd45af 100644
--- a/usr.bin/cvs/annotate.c
+++ b/usr.bin/cvs/annotate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: annotate.c,v 1.59 2008/06/14 03:58:29 tobias Exp $ */
+/* $OpenBSD: annotate.c,v 1.60 2008/06/14 04:34:08 tobias Exp $ */
/*
* Copyright (c) 2007 Tobias Stoeckmann <tobias@openbsd.org>
* Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org>
@@ -163,7 +163,7 @@ cvs_annotate_local(struct cvs_file *cf)
cvs_file_classify(cf, cvs_directory_tag);
- if (cf->file_rcs == NULL)
+ if (cf->file_rcs == NULL || cf->file_rcs->rf_head == NULL)
return;
if (cvs_specified_tag != NULL) {
diff --git a/usr.bin/cvs/checkout.c b/usr.bin/cvs/checkout.c
index 0dcdd75c383..717a05c17a3 100644
--- a/usr.bin/cvs/checkout.c
+++ b/usr.bin/cvs/checkout.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: checkout.c,v 1.154 2008/06/14 03:58:29 tobias Exp $ */
+/* $OpenBSD: checkout.c,v 1.155 2008/06/14 04:34:08 tobias Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -469,6 +469,8 @@ cvs_checkout_file(struct cvs_file *cf, RCSNUM *rnum, char *tag, int co_flags)
if (!(co_flags & CO_REMOVE))
rcsnum_tostr(rnum, rev, sizeof(rev));
+ else
+ rev[0] = '\0';
cvs_log(LP_TRACE, "cvs_checkout_file(%s, %s, %d) -> %s",
cf->file_path, rev, co_flags,
diff --git a/usr.bin/cvs/commit.c b/usr.bin/cvs/commit.c
index ecfdf49741b..1d3c34dd8b5 100644
--- a/usr.bin/cvs/commit.c
+++ b/usr.bin/cvs/commit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: commit.c,v 1.141 2008/06/14 03:19:15 joris Exp $ */
+/* $OpenBSD: commit.c,v 1.142 2008/06/14 04:34:08 tobias Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org>
@@ -472,8 +472,8 @@ cvs_commit_local(struct cvs_file *cf)
rrev = rcs_head_get(cf->file_rcs);
crev = rcs_head_get(cf->file_rcs);
if (crev == NULL || rrev == NULL)
- fatal("RCS head empty or missing in %s\n",
- cf->file_rcs->rf_path);
+ fatal("no head revision in RCS file for %s",
+ cf->file_path);
tag = cvs_directory_tag;
if (cf->file_ent != NULL && cf->file_ent->ce_tag != NULL)
@@ -571,6 +571,9 @@ cvs_commit_local(struct cvs_file *cf)
cvs_printf("old revision: %s; ", rbuf);
}
+ if (isnew == 0 && cf->file_rcs->rf_head == NULL)
+ fatal("no head revision in RCS file for %s", cf->file_path);
+
if (isnew == 0 && onbranch == 0)
d = commit_diff(cf, cf->file_rcs->rf_head, 0);
diff --git a/usr.bin/cvs/diff.c b/usr.bin/cvs/diff.c
index 5e13804c322..b0e15a3ce6a 100644
--- a/usr.bin/cvs/diff.c
+++ b/usr.bin/cvs/diff.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: diff.c,v 1.140 2008/06/11 20:55:34 joris Exp $ */
+/* $OpenBSD: diff.c,v 1.141 2008/06/14 04:34:08 tobias Exp $ */
/*
* Copyright (c) 2008 Tobias Stoeckmann <tobias@openbsd.org>
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
@@ -315,6 +315,12 @@ cvs_diff_local(struct cvs_file *cf)
date1 == -1 && date2 == -1)
return;
+ if (cf->file_rcs->rf_head == NULL) {
+ cvs_log(LP_ERR, "no head revision in RCS file for %s\n",
+ cf->file_path);
+ return;
+ }
+
if (kflag && cf->file_rcs != NULL)
rcs_kwexp_set(cf->file_rcs, kflag);
diff --git a/usr.bin/cvs/getlog.c b/usr.bin/cvs/getlog.c
index 25916fb69e8..b64a58c964b 100644
--- a/usr.bin/cvs/getlog.c
+++ b/usr.bin/cvs/getlog.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: getlog.c,v 1.88 2008/06/09 23:33:15 joris Exp $ */
+/* $OpenBSD: getlog.c,v 1.89 2008/06/14 04:34:08 tobias Exp $ */
/*
* Copyright (c) 2005, 2006 Xavier Santolaria <xsa@openbsd.org>
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
@@ -195,7 +195,7 @@ cvs_log_local(struct cvs_file *cf)
cvs_file_classify(cf, cvs_directory_tag);
- if (cf->file_status == FILE_UNKNOWN) {
+ if (cf->file_rcs == NULL) {
return;
} else if (cf->file_status == FILE_ADDED) {
if (verbosity > 0)
diff --git a/usr.bin/cvs/import.c b/usr.bin/cvs/import.c
index 2c864660569..5fbb3111ba9 100644
--- a/usr.bin/cvs/import.c
+++ b/usr.bin/cvs/import.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: import.c,v 1.95 2008/06/10 20:30:17 joris Exp $ */
+/* $OpenBSD: import.c,v 1.96 2008/06/14 04:34:08 tobias Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -383,6 +383,9 @@ import_update(struct cvs_file *cf)
cvs_log(LP_TRACE, "import_update(%s)", cf->file_path);
+ if (cf->file_rcs->rf_head == NULL)
+ fatal("no head revision in RCS file for `%s'", cf->file_path);
+
if ((rev = rcs_translate_tag(import_branch, cf->file_rcs)) == NULL)
fatal("import_update: could not translate tag `%s'",
import_branch);
diff --git a/usr.bin/cvs/rcs.c b/usr.bin/cvs/rcs.c
index adad03473b2..0cb8a0fa67a 100644
--- a/usr.bin/cvs/rcs.c
+++ b/usr.bin/cvs/rcs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rcs.c,v 1.274 2008/06/14 03:58:29 tobias Exp $ */
+/* $OpenBSD: rcs.c,v 1.275 2008/06/14 04:34:08 tobias Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -776,7 +776,7 @@ rcs_sym_getrev(RCSFILE *file, const char *sym)
RCSNUM *num;
struct rcs_sym *symp;
- if (!rcs_sym_check(sym))
+ if (!rcs_sym_check(sym) || file->rf_head == NULL)
return (NULL);
if (!strcmp(sym, RCS_HEAD_BRANCH)) {
@@ -1185,8 +1185,12 @@ rcs_rev_add(RCSFILE *rf, RCSNUM *rev, const char *msg, time_t date,
if (rf->rf_flags & RCS_CREATE) {
if ((rev = rcsnum_parse(RCS_HEAD_INIT)) == NULL)
return (-1);
+ if (rf->rf_head != NULL)
+ xfree(rf->rf_head);
rf->rf_head = rcsnum_alloc();
rcsnum_cpy(rev, rf->rf_head, 0);
+ } else if (rf->rf_head == NULL) {
+ return (-1);
} else {
rev = rcsnum_inc(rf->rf_head);
}
@@ -1289,6 +1293,9 @@ rcs_rev_remove(RCSFILE *rf, RCSNUM *rev)
if (rev == RCS_HEAD_REV)
rev = rf->rf_head;
+ if (rev == NULL)
+ return (-1);
+
/* do we actually have that revision? */
if ((rdp = rcs_findrev(rf, rev)) == NULL)
return (-1);
@@ -1663,6 +1670,10 @@ rcs_parse_admin(RCSFILE *rfp)
* that we are dealing with an empty RCS file and
* we just found the description.
*/
+ if (!(hmask & (1 << RCS_TOK_HEAD))) {
+ cvs_log(LP_ERR, "head missing");
+ goto fail;
+ }
rcs_pushtok(rfp, RCS_TOKSTR(rfp), tok);
return (tok);
}
@@ -1695,8 +1706,12 @@ rcs_parse_admin(RCSFILE *rfp)
if (tok == RCS_TOK_HEAD) {
if (rfp->rf_head == NULL)
rfp->rf_head = rcsnum_alloc();
- rcsnum_aton(RCS_TOKSTR(rfp), NULL,
- rfp->rf_head);
+ if (RCS_TOKSTR(rfp)[0] == '\0' ||
+ rcsnum_aton(RCS_TOKSTR(rfp), NULL,
+ rfp->rf_head) < 0) {
+ rcsnum_free(rfp->rf_head);
+ rfp->rf_head = NULL;
+ }
} else if (tok == RCS_TOK_BRANCH) {
if (rfp->rf_branch == NULL)
rfp->rf_branch = rcsnum_alloc();
@@ -2634,6 +2649,9 @@ rcs_get_revision(const char *revstr, RCSFILE *rfp)
* the minimum of both revision lengths is taken
* instead of just 2.
*/
+ if (rfp->rf_head == NULL)
+ return NULL;
+
if (rcsnum_cmp(rev, rfp->rf_head,
MIN(rfp->rf_head->rn_len, rev->rn_len)) < 0) {
rcsnum_free(rev);
@@ -2691,7 +2709,8 @@ rcs_rev_getlines(RCSFILE *rfp, RCSNUM *frev, struct cvs_line ***alines)
struct cvs_line *line, *nline;
struct cvs_lines *dlines, *plines;
- if ((hrdp = rcs_findrev(rfp, rfp->rf_head)) == NULL)
+ if (rfp->rf_head == NULL ||
+ (hrdp = rcs_findrev(rfp, rfp->rf_head)) == NULL)
fatal("rcs_rev_getlines: no HEAD revision");
tnum = frev;
diff --git a/usr.bin/cvs/status.c b/usr.bin/cvs/status.c
index 70e88240396..b51a2d1adae 100644
--- a/usr.bin/cvs/status.c
+++ b/usr.bin/cvs/status.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: status.c,v 1.87 2008/06/11 02:19:13 tobias Exp $ */
+/* $OpenBSD: status.c,v 1.88 2008/06/14 04:34:08 tobias Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2005-2008 Xavier Santolaria <xsa@openbsd.org>
@@ -134,24 +134,23 @@ cvs_status_local(struct cvs_file *cf)
return;
}
- if (cf->file_rcs != NULL) {
+ if (cf->file_rcs != NULL)
head = rcs_head_get(cf->file_rcs);
- if (head == NULL && cf->file_status != FILE_REMOVE_ENTRY)
- return;
- } else {
+ else
head = NULL;
- }
cvs_printf("%s\n", CVS_STATUS_SEP);
- status = status_tab[cf->file_status];
+ if (cf->file_rcs != NULL && head == NULL)
+ status = status_tab[FILE_UNKNOWN];
+ else
+ status = status_tab[cf->file_status];
+
if (cf->file_status == FILE_MODIFIED &&
cf->file_ent->ce_conflict != NULL)
status = "File had conflicts on merge";
- if (cf->file_status == FILE_LOST ||
- cf->file_status == FILE_REMOVE_ENTRY ||
- (cf->file_rcs != NULL && cf->in_attic == 1 && cf->fd == -1)) {
+ if (cf->fd == -1) {
(void)xsnprintf(buf, sizeof(buf), "no file %s\t",
cf->file_name);
} else
@@ -163,8 +162,7 @@ cvs_status_local(struct cvs_file *cf)
if (cf->file_ent == NULL) {
(void)xsnprintf(buf, sizeof(buf),
"No entry for %s", cf->file_name);
- } else if (cf->file_status == FILE_ADDED ||
- cf->file_status == FILE_REMOVE_ENTRY) {
+ } else if (cf->file_ent->ce_status == CVS_ENT_ADDED) {
len = strlcpy(buf, "New file!", sizeof(buf));
if (len >= sizeof(buf))
fatal("cvs_status_local: truncation");
@@ -192,10 +190,14 @@ cvs_status_local(struct cvs_file *cf)
cvs_printf(" Working revision:\t%s\n", buf);
buf[0] = '\0';
- if (cf->file_rcs == NULL || head == NULL) {
+ if (cf->file_rcs == NULL) {
len = strlcat(buf, "No revision control file", sizeof(buf));
if (len >= sizeof(buf))
fatal("cvs_status_local: truncation");
+ } else if (head == NULL) {
+ len = strlcat(buf, "No head revision", sizeof(buf));
+ if (len >= sizeof(buf))
+ fatal("cvs_status_local: truncation");
} else {
rcsnum_tostr(head, revbuf, sizeof(revbuf));
rcsnum_free(head);
diff --git a/usr.bin/cvs/update.c b/usr.bin/cvs/update.c
index ac7792d48d6..e4ef04e14b9 100644
--- a/usr.bin/cvs/update.c
+++ b/usr.bin/cvs/update.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: update.c,v 1.153 2008/06/14 03:58:29 tobias Exp $ */
+/* $OpenBSD: update.c,v 1.154 2008/06/14 04:34:08 tobias Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -351,24 +351,29 @@ cvs_update_local(struct cvs_file *cf)
else
cf->file_status = FILE_CHECKOUT;
- cf->file_rcsrev = rcs_head_get(cf->file_rcs);
+ if ((cf->file_rcsrev = rcs_head_get(cf->file_rcs)) == NULL)
+ fatal("no head revision in RCS file for %s",
+ cf->file_path);
/* might be a bit overkill */
if (cvs_server_active == 1)
cvs_server_clear_sticky(cf->file_wd);
}
- if (print_stdout && cf->file_status != FILE_UNKNOWN &&
- !cf->file_rcs->rf_dead) {
- rcsnum_tostr(cf->file_rcsrev, rbuf, sizeof(rbuf));
- if (verbosity > 1) {
- cvs_log(LP_RCS, RCS_DIFF_DIV);
- cvs_log(LP_RCS, "Checking out %s", cf->file_path);
- cvs_log(LP_RCS, "RCS: %s", cf->file_rpath);
- cvs_log(LP_RCS, "VERS: %s", rbuf);
- cvs_log(LP_RCS, "***************");
+ if (print_stdout) {
+ if (cf->file_status != FILE_UNKNOWN && cf->file_rcs != NULL &&
+ cf->file_rcsrev != NULL && !cf->file_rcs->rf_dead) {
+ rcsnum_tostr(cf->file_rcsrev, rbuf, sizeof(rbuf));
+ if (verbosity > 1) {
+ cvs_log(LP_RCS, RCS_DIFF_DIV);
+ cvs_log(LP_RCS, "Checking out %s",
+ cf->file_path);
+ cvs_log(LP_RCS, "RCS: %s", cf->file_rpath);
+ cvs_log(LP_RCS, "VERS: %s", rbuf);
+ cvs_log(LP_RCS, "***************");
+ }
+ cvs_checkout_file(cf, cf->file_rcsrev, tag, CO_DUMP);
}
- cvs_checkout_file(cf, cf->file_rcsrev, tag, CO_DUMP);
return;
}
@@ -376,7 +381,7 @@ cvs_update_local(struct cvs_file *cf)
if (cf->file_ent->ce_opts == NULL) {
if (kflag)
cf->file_status = FILE_CHECKOUT;
- } else {
+ } else if (cf->file_rcs != NULL) {
if (strlen(cf->file_ent->ce_opts) < 3)
fatal("malformed option for file %s",
cf->file_path);
@@ -631,6 +636,12 @@ update_join_file(struct cvs_file *cf)
goto out;
}
+ if (cf->file_rcsrev == NULL) {
+ cvs_printf("non-mergable file: %s has no head revision!\n",
+ cf->file_path);
+ goto out;
+ }
+
if (rev1 == NULL || !strcmp(state1, RCS_STATE_DEAD)) {
if (cf->fd != -1) {
cvs_printf("%s exists but has been added in %s\n",