[master] 8aa9494 Don't assume esi-spec lengths match up with storage segments.

Poul-Henning Kamp phk at varnish-cache.org
Thu Mar 31 18:58:31 CEST 2011


commit 8aa949400268d83069173bac1a155f175e66aacf
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Thu Mar 31 16:58:05 2011 +0000

    Don't assume esi-spec lengths match up with storage segments.

diff --git a/bin/varnishd/cache_esi_deliver.c b/bin/varnishd/cache_esi_deliver.c
index b074cd5..71bbb4b 100644
--- a/bin/varnishd/cache_esi_deliver.c
+++ b/bin/varnishd/cache_esi_deliver.c
@@ -225,7 +225,7 @@ ESI_Deliver(struct sess *sp)
 	struct storage *st;
 	uint8_t *p, *e, *q, *r;
 	unsigned off;
-	ssize_t l, l_icrc = 0;
+	ssize_t l, l2, l_icrc = 0;
 	uint32_t icrc = 0;
 	uint8_t tailbuf[8 + 5];
 	int isgzip;
@@ -291,7 +291,6 @@ ESI_Deliver(struct sess *sp)
 		case VEC_V2:
 		case VEC_V8:
 			l = ved_decode_len(&p);
-			r = p;
 			if (isgzip) {
 				assert(*p == VEC_C1 || *p == VEC_C2 ||
 				    *p == VEC_C8);
@@ -299,45 +298,76 @@ ESI_Deliver(struct sess *sp)
 				icrc = vbe32dec(p);
 				p += 4;
 			}
-			if (sp->wrk->gzip_resp && isgzip) {
-				/*
-				 * We have a gzip'ed VEC and delivers a
-				 * gzip'ed ESI response.
-				 */
-				sp->wrk->crc = crc32_combine(
-				    sp->wrk->crc, icrc, l_icrc);
-				sp->wrk->l_crc += l_icrc;
-				WRW_Write(sp->wrk, st->ptr + off, l);
-			} else if (sp->wrk->gzip_resp) {
-				/*
-				 * A gzip'ed ESI response, but the VEC was
-				 * not gzip'ed.
-				 */
-				ved_pretend_gzip(sp, st->ptr + off, l);
-				off += l;
-			} else if (isgzip) {
-				/*
-				 * A gzip'ed VEC, but ungzip'ed ESI response
-				 */
-				AN(vgz);
-				i = VGZ_WrwGunzip(sp, vgz,
-					st->ptr + off, l,
-					obuf, sizeof obuf, &obufl);
-				assert (i == VGZ_OK || i == VGZ_END);
-			} else {
-				/*
-				 * Ungzip'ed VEC, ungzip'ed ESI response
-				 */
-				WRW_Write(sp->wrk, st->ptr + off, l);
+			/*
+			 * There is no guarantee that the 'l' bytes are all
+			 * in the same storage segment, so loop over storage
+			 * until we have processed them all.
+			 */
+			while (l > 0) {
+				l2 = l;
+				if (l2 > st->len - off)
+					l2 = st->len - off;
+				l -= l2;
+
+				if (sp->wrk->gzip_resp && isgzip) {
+					/*
+					 * We have a gzip'ed VEC and delivers
+					 * a gzip'ed ESI response.
+					 */
+					sp->wrk->crc = crc32_combine(
+					    sp->wrk->crc, icrc, l_icrc);
+					sp->wrk->l_crc += l_icrc;
+					WRW_Write(sp->wrk, st->ptr + off, l2);
+				} else if (sp->wrk->gzip_resp) {
+					/*
+					 * A gzip'ed ESI response, but the VEC
+					 * was not gzip'ed.
+					 */
+					ved_pretend_gzip(sp, st->ptr + off, l2);
+				} else if (isgzip) {
+					/*
+					 * A gzip'ed VEC, but ungzip'ed ESI
+					 * response
+					 */
+					AN(vgz);
+					i = VGZ_WrwGunzip(sp, vgz,
+						st->ptr + off, l2,
+						obuf, sizeof obuf, &obufl);
+					assert (i == VGZ_OK || i == VGZ_END);
+				} else {
+					/*
+					 * Ungzip'ed VEC, ungzip'ed ESI response
+					 */
+					WRW_Write(sp->wrk, st->ptr + off, l2);
+				}
+				off += l2;
+				if (off == st->len) {
+					st = VTAILQ_NEXT(st, list);
+					off = 0;
+				}
 			}
-			off += l;
 			break;
 		case VEC_S1:
 		case VEC_S2:
 		case VEC_S8:
 			l = ved_decode_len(&p);
 			Debug("SKIP1(%d)\n", (int)l);
-			off += l;
+			/*
+			 * There is no guarantee that the 'l' bytes are all
+			 * in the same storage segment, so loop over storage
+			 * until we have processed them all.
+			 */
+			while (l > 0) {
+				l2 = l;
+				if (l2 > st->len - off)
+					l2 = st->len - off;
+				l -= l2;
+				off += l2;
+				if (off == st->len) {
+					st = VTAILQ_NEXT(st, list);
+					off = 0;
+				}
+			}
 			break;
 		case VEC_INCL:
 			p++;



More information about the varnish-commit mailing list