Description: Bound case-conversion writes by the workspace reservation
 Preserve the single-string no-copy optimization while checking the
 reservation before writing any converted or unchanged byte.
Author: Walid Boudebouda <walid.boudebouda@gmail.com>
Origin: upstream, https://code.vinyl-cache.org/vinyl-cache/vinyl-cache/commit/853d397f30753bce1587991fcf9193c63fb4d1eb
Bug: https://vinyl-cache.org/security/VSV00020.html
Bug-Debian: https://bugs.debian.org/1148187
Forwarded: not-needed
Last-Update: 2026-10-23

diff --git a/bin/vinyld/cache/cache_vrt.c b/bin/vinyld/cache/cache_vrt.c
index 7bc2e62519..7c1168aef4 100644
--- a/bin/vinyld/cache/cache_vrt.c
+++ b/bin/vinyld/cache/cache_vrt.c
@@ -511,7 +511,7 @@ VRT_UpperLowerStrands(VRT_CTX, VCL_STRANDS s, int up)
 	unsigned u;
 	char *b, *e, *r;
 	const char *p, *q = NULL;
-	int i, copy = 0;
+	int i, copy = 0, op = 0;
 
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
 	CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
@@ -525,15 +525,20 @@ VRT_UpperLowerStrands(VRT_CTX, VCL_STRANDS s, int up)
 		if (q != NULL)
 			copy = 1;
 		for(p = q = s->p[i]; *p != '\0'; p++) {
-			if ((up && vct_islower(*p)) ||
-			    (!up && vct_isupper(*p))) {
-				*b++ = *p ^ 0x20;
+			op = up ? vct_islower(*p) : vct_isupper(*p);
+
+			if (op)
 				copy = 1;
-			} else if (b < e) {
-				*b++ = *p;
-			}
-			if (copy && b == e)
+
+			if (!copy && b == e)
+				continue;
+			else if (b == e)
 				break;
+
+			if (op)
+				*b++ = *p ^ 0x20;
+			else
+				*b++ = *p;
 		}
 		if (copy && b == e) {
 			WS_Release(ctx->ws, 0);
