From: Andy Parkins <andyparkins@gmail.com>
To: git@vger.kernel.org
Subject: [PATCH] Fix mishandling of $Id$ expanded in the repository copy in convert.c
Date: Fri, 25 May 2007 11:50:08 +0100 [thread overview]
Message-ID: <200705251150.09439.andyparkins@gmail.com> (raw)
If the repository contained an expanded ident keyword (i.e. $Id:XXXX$),
then the wrong bytes were discarded, and the Id keyword was not
expanded. The fault was in convert.c:ident_to_worktree().
Previously, when a "$Id:" was found in the repository version,
ident_to_worktree() would search for the next "$" after this, and
discarded everything it found until then. That was done with the loop:
do {
ch = *cp++;
if (ch == '$')
break;
rem--;
} while (rem);
The above loop left cp pointing one character _after_ the final "$"
(because of ch = *cp++). This was different from the non-expanded case,
were cp is left pointing at the "$", and was different from the comment
which stated "discard up to but not including the closing $". This
patch fixes that by making the loop:
do {
ch = *cp;
if (ch == '$')
break;
cp++;
rem--;
} while (rem);
That is, cp is tested _then_ incremented.
This loop exits if it finds a "$" or if it runs out of bytes in the
source. After this loop, if there was no closing "$" the expansion is
skipped, and the outer loop is allowed to continue leaving this
non-keyword as it was. However, when the "$" is found, size is
corrected, before running the expansion:
size -= (cp - src);
This is wrong; size is going to be corrected anyway after the expansion,
so there is no need to do it here. This patch removes that redundant
correction.
To help find this bug, I heavily commented the routine; those comments
are included here as a bonus.
Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
You wouldn't believe that I managed to get a file into the repository
with $Id$ stored expanded would you? :-)
Anyway, it's fortunate that I did, because it revealed the above bugs
in the ident_to_worktree() code.
I've included the comments I wrote while debugging in this patch, which
I'm sure will annoy you, because you'd rather the fix and the comments
separately. I'll supply that if you wish - just holler.
convert.c | 39 +++++++++++++++++++++++++++++++++++++--
1 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/convert.c b/convert.c
index 4b26b1a..3c44e3d 100644
--- a/convert.c
+++ b/convert.c
@@ -509,36 +509,71 @@ static char *ident_to_worktree(const char *path, const char *src, unsigned long
for (dst = buf; size; size--) {
const char *cp;
+ /* Fetch next source character, move the pointer on */
char ch = *src++;
+ /* Copy the current character to the destination */
*dst++ = ch;
+ /* If the current character is "$" or there are less than three
+ * remaining bytes or the two bytes following this one are not
+ * "Id", then simply read the next character */
if ((ch != '$') || (size < 3) || memcmp("Id", src, 2))
continue;
+ /*
+ * Here when
+ * - There are more than 2 bytes remaining
+ * - The current three bytes are "$Id$"
+ * with
+ * - ch == "$"
+ * - src[0] == "I"
+ */
+ /*
+ * It's possible that an expanded Id has crept its way into the
+ * repository, we cope with that by stripping the expansion out
+ */
if (src[2] == ':') {
+ /* Expanded keywords have "$Id:" at the front */
+
/* discard up to but not including the closing $ */
unsigned long rem = size - 3;
+ /* Point at first byte after the ":" */
cp = src + 3;
+ /*
+ * Throw away characters until either
+ * - we reach a "$"
+ * - we run out of bytes (rem == 0)
+ */
do {
- ch = *cp++;
+ ch = *cp;
if (ch == '$')
break;
+ cp++;
rem--;
} while (rem);
+ /* If the above finished because it ran out of characters, then
+ * this is an incomplete keyword, so don't run the expansion */
if (!rem)
continue;
- size -= (cp - src);
} else if (src[2] == '$')
cp = src + 2;
else
+ /* Anything other than "$Id:XXX$" or $Id$ and we skip the
+ * expansion */
continue;
+ /* cp is now pointing at the last $ of the keyword */
+
memcpy(dst, "Id: ", 4);
dst += 4;
memcpy(dst, sha1_to_hex(sha1), 40);
dst += 40;
*dst++ = ' ';
+
+ /* Adjust for the characters we've discarded */
size -= (cp - src);
src = cp;
+
+ /* Copy the final "$" */
*dst++ = *src++;
size--;
}
--
1.5.2.763.g8c5e-dirty
next reply other threads:[~2007-05-25 10:50 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-05-25 10:50 Andy Parkins [this message]
2007-05-25 10:58 ` [PATCH] Fix mishandling of $Id$ expanded in the repository copy in convert.c Joshua N Pritikin
2007-05-25 13:12 ` Andy Parkins
2007-05-25 13:13 ` [PATCH] Don't allow newlines to occur in $Id:$ collapse Andy Parkins
2007-05-25 13:28 ` Joshua N Pritikin
2007-05-25 13:47 ` Nicolas Pitre
2007-05-25 13:50 ` Andy Parkins
2007-05-25 14:40 ` Joshua N Pritikin
2007-05-26 8:09 ` [PATCH] Fix mishandling of $Id$ expanded in the repository copy in convert.c Junio C Hamano
2007-05-26 9:12 ` Andy Parkins
2007-05-26 19:05 ` Junio C Hamano
2007-05-27 10:50 ` Andy Parkins
2007-05-27 10:52 ` [PATCH] Add test case for $Id$ expanded in the repository Andy Parkins
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200705251150.09439.andyparkins@gmail.com \
--to=andyparkins@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).