Skip to content
This repository was archived by the owner on Jul 30, 2021. It is now read-only.

Commit 85e8468

Browse files
committed
Do not consider a CR by itself as a valid line terminator
Varnish (prior to version 4.0) was not following the standard with regard to line separator. Spotted and analyzed by: Régis Leroy [regilero] regis.leroy@makina-corpus.com
1 parent 9190770 commit 85e8468

File tree

4 files changed

+37
-12
lines changed

4 files changed

+37
-12
lines changed

Diff for: bin/varnishd/cache_http.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p,
502502
/* Find end of next header */
503503
q = r = p;
504504
while (r < t.e) {
505-
if (!vct_iscrlf(*r)) {
505+
if (!vct_iscrlf(r)) {
506506
r++;
507507
continue;
508508
}
@@ -611,8 +611,8 @@ http_splitline(struct worker *w, int fd, struct http *hp,
611611

612612
/* Third field is optional and cannot contain CTL */
613613
q = p;
614-
if (!vct_iscrlf(*p)) {
615-
for (; !vct_iscrlf(*p); p++)
614+
if (!vct_iscrlf(p)) {
615+
for (; !vct_iscrlf(p); p++)
616616
if (!vct_issep(*p) && vct_isctl(*p))
617617
return (400);
618618
}

Diff for: bin/varnishtest/tests/b00040.vtc

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
varnishtest "Do not consider CR as a valid line separator"
2+
3+
server s1 {
4+
rxreq
5+
txresp
6+
} -start
7+
8+
varnish v1 -vcl+backend {
9+
sub vcl_deliver {
10+
if (req.http.foo) {
11+
set resp.http.Foo = req.http.foo;
12+
}
13+
if (req.http.bar) {
14+
set resp.http.Bar = req.http.bar;
15+
}
16+
}
17+
} -start
18+
19+
client c1 {
20+
send "GET / HTTP/1.1\r\nFoo: foo\rBar: bar\r\n\r\n"
21+
rxresp
22+
expect resp.http.foo == "foo\rBar: bar"
23+
expect resp.http.bar == "<undef>"
24+
} -run

Diff for: bin/varnishtest/vtc_http.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -283,17 +283,17 @@ http_splitheader(struct http *hp, int req)
283283
hh[n++] = p;
284284
while (!vct_islws(*p))
285285
p++;
286-
assert(!vct_iscrlf(*p));
286+
assert(!vct_iscrlf(p));
287287
*p++ = '\0';
288288

289289
/* URL/STATUS */
290290
while (vct_issp(*p)) /* XXX: H space only */
291291
p++;
292-
assert(!vct_iscrlf(*p));
292+
assert(!vct_iscrlf(p));
293293
hh[n++] = p;
294294
while (!vct_islws(*p))
295295
p++;
296-
if (vct_iscrlf(*p)) {
296+
if (vct_iscrlf(p)) {
297297
hh[n++] = NULL;
298298
q = p;
299299
p += vct_skipcrlf(p);
@@ -304,7 +304,7 @@ http_splitheader(struct http *hp, int req)
304304
while (vct_issp(*p)) /* XXX: H space only */
305305
p++;
306306
hh[n++] = p;
307-
while (!vct_iscrlf(*p))
307+
while (!vct_iscrlf(p))
308308
p++;
309309
q = p;
310310
p += vct_skipcrlf(p);
@@ -314,10 +314,10 @@ http_splitheader(struct http *hp, int req)
314314

315315
while (*p != '\0') {
316316
assert(n < MAX_HDR);
317-
if (vct_iscrlf(*p))
317+
if (vct_iscrlf(p))
318318
break;
319319
hh[n++] = p++;
320-
while (*p != '\0' && !vct_iscrlf(*p))
320+
while (*p != '\0' && !vct_iscrlf(p))
321321
p++;
322322
q = p;
323323
p += vct_skipcrlf(p);
@@ -408,11 +408,11 @@ http_rxchunk(struct http *hp)
408408
}
409409
l = hp->prxbuf;
410410
(void)http_rxchar(hp, 2, 0);
411-
if(!vct_iscrlf(hp->rxbuf[l]))
411+
if(!vct_iscrlf(&hp->rxbuf[l]))
412412
vtc_log(hp->vl, hp->fatal,
413413
"Wrong chunk tail[0] = %02x",
414414
hp->rxbuf[l] & 0xff);
415-
if(!vct_iscrlf(hp->rxbuf[l + 1]))
415+
if(!vct_iscrlf(&hp->rxbuf[l + 1]))
416416
vtc_log(hp->vl, hp->fatal,
417417
"Wrong chunk tail[1] = %02x",
418418
hp->rxbuf[l + 1] & 0xff);

Diff for: include/vct.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ vct_is(unsigned char x, uint16_t y)
5454

5555
#define vct_issp(x) vct_is(x, VCT_SP)
5656
#define vct_ishex(x) vct_is(x, VCT_HEX)
57-
#define vct_iscrlf(x) vct_is(x, VCT_CRLF)
5857
#define vct_islws(x) vct_is(x, VCT_LWS)
5958
#define vct_isctl(x) vct_is(x, VCT_CTL)
6059
#define vct_isdigit(x) vct_is(x, VCT_DIGIT)
@@ -64,5 +63,7 @@ vct_is(unsigned char x, uint16_t y)
6463
#define vct_isxmlnamestart(x) vct_is(x, VCT_XMLNAMESTART)
6564
#define vct_isxmlname(x) vct_is(x, VCT_XMLNAMESTART | VCT_XMLNAME)
6665

66+
#define vct_iscrlf(p) (((p)[0] == '\r' && (p)[1] == '\n') || (p)[0] == '\n')
67+
6768
/* NB: VCT always operate in ASCII, don't replace 0x0d with \r etc. */
6869
#define vct_skipcrlf(p) (p[0] == 0x0d && p[1] == 0x0a ? 2 : 1)

0 commit comments

Comments
 (0)