[master] 08d3a70d2 add a trivial VRT function to check if a string is a valid header value

Nils Goroll nils.goroll at uplex.de
Fri Oct 9 11:43:06 UTC 2020


commit 08d3a70d258108d0dffb8ae208e6e29891565534
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Wed Sep 9 15:34:42 2020 +0200

    add a trivial VRT function to check if a string is a valid header value
    
    Ref: https://httpwg.org/specs/rfc7230.html#header.fields
    
      field-value    = *( field-content / obs-fold )
      field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
      field-vchar    = VCHAR / obs-text
    
    - we do not accept the obsolete line folding (obs-fold)
    - VCHAR is 0x20 to 0x7e
    - obs-text is 0x80 to 0xff
    
    So we end up with !VCT_CTL || HTAB (LF)
    
    This change would be the basis for new use cases, like
    
    - a type method .valid_header
    - a feature flag +validate_headers which would call VRT_ValidHdr
      for all SetHdr calls

diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c
index aef672e27..f88daaac1 100644
--- a/bin/varnishd/cache/cache_vrt.c
+++ b/bin/varnishd/cache/cache_vrt.c
@@ -590,6 +590,35 @@ VRT_UpperLowerStrands(VRT_CTX, VCL_STRANDS s, int up)
 	return (r);
 }
 
+// RFC7232, 3.2 without obsolete line folding:
+// ASCII VCHAR + TAB + obs-text (0x80-ff)
+static inline VCL_BOOL
+validhdr(const char *p)
+{
+	AN(p);
+	for(;*p != '\0'; p++)
+		if (vct_isctl(*p) && !vct_issp(*p))
+			return (0);
+	return (1);
+}
+
+/*--------------------------------------------------------------------*/
+VCL_BOOL
+VRT_ValidHdr(VRT_CTX, VCL_STRANDS s)
+{
+	int i;
+
+	(void) ctx;
+
+	for (i = 0; i < s->n; i++) {
+		if (s->p[i] == NULL || s->p[i][0] == '\0')
+			continue;
+		if (! validhdr(s->p[i]))
+			return (0);
+	}
+
+	return (1);
+}
 /*--------------------------------------------------------------------*/
 
 VCL_VOID
diff --git a/include/vrt.h b/include/vrt.h
index 5e5b032f9..7e31480a4 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -496,6 +496,7 @@ VCL_INT VRT_purge(VRT_CTX, VCL_DURATION, VCL_DURATION, VCL_DURATION);
 VCL_VOID VRT_synth(VRT_CTX, VCL_INT, VCL_STRING);
 VCL_VOID VRT_hit_for_pass(VRT_CTX, VCL_DURATION);
 
+VCL_BOOL VRT_ValidHdr(VRT_CTX, VCL_STRANDS);
 VCL_VOID VRT_SetHdr(VRT_CTX, VCL_HEADER, const char *, ...);
 VCL_VOID VRT_handling(VRT_CTX, unsigned hand);
 VCL_VOID VRT_fail(VRT_CTX, const char *fmt, ...) v_printflike_(2,3);


More information about the varnish-commit mailing list