=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/rcs/ci.c,v retrieving revision 1.182 retrieving revision 1.183 diff -c -r1.182 -r1.183 *** src/usr.bin/rcs/ci.c 2006/07/27 02:57:17 1.182 --- src/usr.bin/rcs/ci.c 2006/08/02 03:18:40 1.183 *************** *** 1,4 **** ! /* $OpenBSD: ci.c,v 1.182 2006/07/27 02:57:17 deraadt Exp $ */ /* * Copyright (c) 2005, 2006 Niall O'Higgins * All rights reserved. --- 1,4 ---- ! /* $OpenBSD: ci.c,v 1.183 2006/08/02 03:18:40 ray Exp $ */ /* * Copyright (c) 2005, 2006 Niall O'Higgins * All rights reserved. *************** *** 51,56 **** --- 51,59 ---- #define KW_NUMTOKS_STATE 3 #define KW_NUMTOKS_REVISION 3 + /* Maximum number of tokens in a keyword. */ + #define KW_NUMTOKS_MAX 10 + #define RCSNUM_ZERO_ENDING(x) (x->rn_id[x->rn_len - 1] == 0) extern struct rcs_kw rcs_expkw[]; *************** *** 74,80 **** static BUF *checkin_diff_file(struct checkin_params *); static char *checkin_getlogmsg(RCSNUM *, RCSNUM *, int); static int checkin_init(struct checkin_params *); ! static int checkin_keywordscan(char *, RCSNUM **, time_t *, char **, char **); static int checkin_keywordtype(char *); static void checkin_mtimedate(struct checkin_params *); --- 77,83 ---- static BUF *checkin_diff_file(struct checkin_params *); static char *checkin_getlogmsg(RCSNUM *, RCSNUM *, int); static int checkin_init(struct checkin_params *); ! static int checkin_keywordscan(BUF *, RCSNUM **, time_t *, char **, char **); static int checkin_keywordtype(char *); static void checkin_mtimedate(struct checkin_params *); *************** *** 601,607 **** /* Get default values from working copy if -k specified */ if (pb->flags & CI_KEYWORDSCAN) ! checkin_keywordscan((char *)rcs_buf_get(bp), &pb->newrev, &pb->date, &pb->state, &pb->author); if (pb->flags & CI_SKIPDESC) --- 604,610 ---- /* Get default values from working copy if -k specified */ if (pb->flags & CI_KEYWORDSCAN) ! checkin_keywordscan(bp, &pb->newrev, &pb->date, &pb->state, &pb->author); if (pb->flags & CI_SKIPDESC) *************** *** 808,823 **** * On success, return 0. On error return -1. */ static int ! checkin_keywordscan(char *data, RCSNUM **rev, time_t *date, char **author, char **state) { ! size_t end; u_int j; ! char *c, *kwstr, *start, buf[128]; kwstr = NULL; ! for (c = data; (c = strchr(c, '$')) != NULL;) { size_t len; start = c; --- 811,832 ---- * On success, return 0. On error return -1. */ static int ! checkin_keywordscan(BUF *data, RCSNUM **rev, time_t *date, char **author, char **state) { ! BUF *buf; ! size_t left; u_int j; ! char *kwstr; ! unsigned char *c, *end, *start; + end = rcs_buf_get(data) + rcs_buf_len(data) - 1; kwstr = NULL; ! left = rcs_buf_len(data); ! for (c = rcs_buf_get(data); ! c <= end && (c = memchr(c, '$', left)) != NULL; ! left = end - c + 1) { size_t len; start = c; *************** *** 828,834 **** /* look for any matching keywords */ for (j = 0; j < 10; j++) { len = strlen(rcs_expkw[j].kw_str); ! if (strncmp(c, rcs_expkw[j].kw_str, len) != 0) { kwstr = rcs_expkw[j].kw_str; break; } --- 837,845 ---- /* look for any matching keywords */ for (j = 0; j < 10; j++) { len = strlen(rcs_expkw[j].kw_str); ! if (left < len) ! continue; ! if (memcmp(c, rcs_expkw[j].kw_str, len) != 0) { kwstr = rcs_expkw[j].kw_str; break; } *************** *** 839,856 **** continue; c += len; ! if (*c != ':') continue; /* Find end of line or end of keyword. */ ! c += strcspn(c, "$\n"); ! if (*c != '$') ! continue; ! end = c - start + 2; ! if (strlcpy(buf, start, end) >= end) ! errx(1, "keyword buffer too small!"); ! checkin_parsekeyword(buf, rev, date, author, state); } if (kwstr == NULL) return (-1); --- 850,883 ---- continue; c += len; ! if (c > end) { ! kwstr = NULL; ! break; ! } ! if (*c != ':') { ! kwstr = NULL; continue; + } /* Find end of line or end of keyword. */ ! while (++c <= end) { ! if (*c == '\n') { ! /* Skip newline since it is definitely not `$'. */ ! ++c; ! goto loopend; ! } ! if (*c == '$') ! break; ! } ! len = c - start + 1; ! buf = rcs_buf_alloc(len + 1, 0); ! rcs_buf_append(buf, start, len); ! ! /* XXX - Not binary safe. */ ! rcs_buf_putc(buf, '\0'); ! checkin_parsekeyword(rcs_buf_get(buf), rev, date, author, state); ! loopend: } if (kwstr == NULL) return (-1); *************** *** 893,953 **** * Do the actual parsing of an RCS keyword string, setting the values passed * to the function to whatever is found. * */ static void ! checkin_parsekeyword(char *keystring, RCSNUM **rev, time_t *date, char **author, char **state) { ! char *tokens[10], *p, *datestring; size_t len = 0; int i = 0; /* Parse data out of the expanded keyword */ switch (checkin_keywordtype(keystring)) { case KW_TYPE_ID: ! for ((p = strtok(keystring, " ")); p; ! (p = strtok(NULL, " "))) { ! if (i < KW_NUMTOKS_ID - 1) ! tokens[i++] = p; ! } ! tokens[i] = NULL; ! if (*author != NULL) ! xfree(*author); ! if (*state != NULL) ! xfree(*state); /* only parse revision if one is not already set */ if (*rev == NULL) { if ((*rev = rcsnum_parse(tokens[2])) == NULL) errx(1, "could not parse rcsnum"); } ! *author = xstrdup(tokens[5]); ! *state = xstrdup(tokens[6]); len = strlen(tokens[3]) + strlen(tokens[4]) + 2; datestring = xmalloc(len); if (strlcpy(datestring, tokens[3], len) >= len || strlcat(datestring, " ", len) >= len || ! strlcat(datestring, tokens[4], len) >= len) errx(1, "date too long"); ! if ((*date = rcs_date_parse(datestring)) <= 0) errx(1, "could not parse date"); xfree(datestring); break; case KW_TYPE_AUTHOR: ! for ((p = strtok(keystring, " ")); p; ! (p = strtok(NULL, " "))) { ! if (i < KW_NUMTOKS_AUTHOR - 1) ! tokens[i++] = p; ! } if (*author != NULL) xfree(*author); *author = xstrdup(tokens[1]); break; case KW_TYPE_DATE: ! for ((p = strtok(keystring, " ")); p; ! (p = strtok(NULL, " "))) { ! if (i < KW_NUMTOKS_DATE - 1) ! tokens[i++] = p; ! } len = strlen(tokens[1]) + strlen(tokens[2]) + 2; datestring = xmalloc(len); if (strlcpy(datestring, tokens[1], len) >= len || --- 920,988 ---- * Do the actual parsing of an RCS keyword string, setting the values passed * to the function to whatever is found. * + * XXX - Don't error out on malformed keywords. */ static void ! checkin_parsekeyword(char *keystring, RCSNUM **rev, time_t *date, char **author, char **state) { ! char *tokens[KW_NUMTOKS_MAX], *p, *datestring; size_t len = 0; int i = 0; + for ((p = strtok(keystring, " ")); p; (p = strtok(NULL, " "))) { + if (i < KW_NUMTOKS_MAX - 1) + tokens[i++] = p; + else + break; + } + /* Parse data out of the expanded keyword */ switch (checkin_keywordtype(keystring)) { case KW_TYPE_ID: ! if (i < 3) ! break; /* only parse revision if one is not already set */ if (*rev == NULL) { if ((*rev = rcsnum_parse(tokens[2])) == NULL) errx(1, "could not parse rcsnum"); } ! ! if (i < 5) ! break; len = strlen(tokens[3]) + strlen(tokens[4]) + 2; datestring = xmalloc(len); + /* XXX - use snprintf */ if (strlcpy(datestring, tokens[3], len) >= len || strlcat(datestring, " ", len) >= len || ! strlcat(datestring, tokens[4], len) >= len) { errx(1, "date too long"); ! } else if ((*date = rcs_date_parse(datestring)) <= 0) errx(1, "could not parse date"); xfree(datestring); + + if (i < 6) + break; + if (*author != NULL) + xfree(*author); + *author = xstrdup(tokens[5]); + + if (i < 7) + break; + if (*state != NULL) + xfree(*state); + *state = xstrdup(tokens[6]); break; case KW_TYPE_AUTHOR: ! if (i < 2) ! break; if (*author != NULL) xfree(*author); *author = xstrdup(tokens[1]); break; case KW_TYPE_DATE: ! if (i < 3) ! break; len = strlen(tokens[1]) + strlen(tokens[2]) + 2; datestring = xmalloc(len); if (strlcpy(datestring, tokens[1], len) >= len || *************** *** 959,982 **** xfree(datestring); break; case KW_TYPE_STATE: ! for ((p = strtok(keystring, " ")); p; ! (p = strtok(NULL, " "))) { ! if (i < KW_NUMTOKS_STATE - 1) ! tokens[i++] = p; ! } if (*state != NULL) xfree(*state); *state = xstrdup(tokens[1]); break; case KW_TYPE_REVISION: /* only parse revision if one is not already set */ if (*rev != NULL) break; - for ((p = strtok(keystring, " ")); p; - (p = strtok(NULL, " "))) { - if (i < KW_NUMTOKS_REVISION - 1) - tokens[i++] = p; - } if ((*rev = rcsnum_parse(tokens[1])) == NULL) errx(1, "could not parse rcsnum"); break; --- 994,1011 ---- xfree(datestring); break; case KW_TYPE_STATE: ! if (i < 2) ! break; if (*state != NULL) xfree(*state); *state = xstrdup(tokens[1]); break; case KW_TYPE_REVISION: + if (i < 2) + break; /* only parse revision if one is not already set */ if (*rev != NULL) break; if ((*rev = rcsnum_parse(tokens[1])) == NULL) errx(1, "could not parse rcsnum"); break;