Web lists-archives.com

[PATCH 04/23] prefix_ref_iterator: don't trim too much




The `trim` parameter can be set independently of `prefix`. So if some
caller were to set `trim` to be greater than `strlen(prefix)`, we
could end up pointing the `refname` field of the iterator past the NUL
of the actual reference name string.

That can't happen currently, because `trim` is always set either to
zero or to `strlen(prefix)`. But even the latter could lead to
confusion, if a refname is exactly equal to the prefix, because then
we would set the outgoing `refname` to the empty string.

And we're about to decouple the `prefix` and `trim` arguments even
more, so let's be cautious here. Skip over any references whose names
are not longer than `trim`.

Signed-off-by: Michael Haggerty <mhagger@xxxxxxxxxxxx>
---
 refs/iterator.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/refs/iterator.c b/refs/iterator.c
index bce1f192f7..f33d1b3a39 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -292,7 +292,19 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
 		if (!starts_with(iter->iter0->refname, iter->prefix))
 			continue;
 
-		iter->base.refname = iter->iter0->refname + iter->trim;
+		if (iter->trim) {
+			/*
+			 * If there wouldn't be at least one character
+			 * left in the refname after trimming, skip
+			 * over it:
+			 */
+			if (memchr(iter->iter0->refname, '\0', iter->trim + 1))
+				continue;
+			iter->base.refname = iter->iter0->refname + iter->trim;
+		} else {
+			iter->base.refname = iter->iter0->refname;
+		}
+
 		iter->base.oid = iter->iter0->oid;
 		iter->base.flags = iter->iter0->flags;
 		return ITER_OK;
-- 
2.11.0