Skip to content

Commit c23290d

Browse files
andyparkinsJunio C Hamano
authored andcommitted
Fix mishandling of $Id$ expanded in the repository copy in convert.c
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6d9d26d commit c23290d

File tree

1 file changed

+37
-2
lines changed

1 file changed

+37
-2
lines changed

convert.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -509,36 +509,71 @@ static char *ident_to_worktree(const char *path, const char *src, unsigned long
509509

510510
for (dst = buf; size; size--) {
511511
const char *cp;
512+
/* Fetch next source character, move the pointer on */
512513
char ch = *src++;
514+
/* Copy the current character to the destination */
513515
*dst++ = ch;
516+
/* If the current character is "$" or there are less than three
517+
* remaining bytes or the two bytes following this one are not
518+
* "Id", then simply read the next character */
514519
if ((ch != '$') || (size < 3) || memcmp("Id", src, 2))
515520
continue;
521+
/*
522+
* Here when
523+
* - There are more than 2 bytes remaining
524+
* - The current three bytes are "$Id"
525+
* with
526+
* - ch == "$"
527+
* - src[0] == "I"
528+
*/
516529

530+
/*
531+
* It's possible that an expanded Id has crept its way into the
532+
* repository, we cope with that by stripping the expansion out
533+
*/
517534
if (src[2] == ':') {
535+
/* Expanded keywords have "$Id:" at the front */
536+
518537
/* discard up to but not including the closing $ */
519538
unsigned long rem = size - 3;
539+
/* Point at first byte after the ":" */
520540
cp = src + 3;
541+
/*
542+
* Throw away characters until either
543+
* - we reach a "$"
544+
* - we run out of bytes (rem == 0)
545+
*/
521546
do {
522-
ch = *cp++;
547+
ch = *cp;
523548
if (ch == '$')
524549
break;
550+
cp++;
525551
rem--;
526552
} while (rem);
553+
/* If the above finished because it ran out of characters, then
554+
* this is an incomplete keyword, so don't run the expansion */
527555
if (!rem)
528556
continue;
529-
size -= (cp - src);
530557
} else if (src[2] == '$')
531558
cp = src + 2;
532559
else
560+
/* Anything other than "$Id:XXX$" or $Id$ and we skip the
561+
* expansion */
533562
continue;
534563

564+
/* cp is now pointing at the last $ of the keyword */
565+
535566
memcpy(dst, "Id: ", 4);
536567
dst += 4;
537568
memcpy(dst, sha1_to_hex(sha1), 40);
538569
dst += 40;
539570
*dst++ = ' ';
571+
572+
/* Adjust for the characters we've discarded */
540573
size -= (cp - src);
541574
src = cp;
575+
576+
/* Copy the final "$" */
542577
*dst++ = *src++;
543578
size--;
544579
}

0 commit comments

Comments
 (0)