[master] d5bbb1a92 vsl: Tolerate float LHS with int RHS in queries

Dridi Boukelmoune dridi.boukelmoune at gmail.com
Mon Jan 18 17:57:06 UTC 2021


commit d5bbb1a92322232591f48cc491dc7d266cdcfa11
Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
Date:   Wed Jan 13 12:00:48 2021 +0100

    vsl: Tolerate float LHS with int RHS in queries
    
    Only if strtoll(3) stumbled upon a VNUM special character.
    
    Fixes #3463

diff --git a/bin/varnishtest/tests/r03463.vtc b/bin/varnishtest/tests/r03463.vtc
new file mode 100644
index 000000000..9d0818e7f
--- /dev/null
+++ b/bin/varnishtest/tests/r03463.vtc
@@ -0,0 +1,52 @@
+varnishtest "VSL query lenient int comparisons"
+
+varnish v1 -vcl {
+	import std;
+	backend be none;
+	sub vcl_recv {
+		if (req.http.skip != "log") {
+			std.log("float1: 123.456");
+			std.log("float2: 123.");
+			std.log("float3: .456");
+			std.log("float4: 12.3e1");
+			std.log("float5: e1");
+		}
+		return (synth(200));
+	}
+} -start
+
+logexpect l1 -v v1 -q "VCL_Log:float1 >= 123" {
+	expect 0 1001 Begin rxreq
+} -start
+
+logexpect l2 -v v1 -q "VCL_Log:float2 <= 123" {
+	expect 0 1001 Begin rxreq
+} -start
+
+logexpect l3 -v v1 -q "VCL_Log:float3 == 0" {
+	expect 0 1001 Begin rxreq
+} -start
+
+logexpect l4 -v v1 -q "VCL_Log:float4 == 123" {
+	expect 0 1001 Begin rxreq
+} -start
+
+logexpect l5 -v v1 -q "VCL_Log:float5 != 42 or ReqHeader:skip eq log" {
+	fail add 1001 Begin rxreq
+	expect * 1002 Begin rxreq
+	fail clear
+} -start
+
+client c1 {
+	txreq
+	rxresp
+
+	txreq -hdr "skip: log"
+	rxresp
+} -run
+
+logexpect l1 -wait
+logexpect l2 -wait
+logexpect l3 -wait
+logexpect l4 -wait
+logexpect l5 -wait
diff --git a/doc/sphinx/reference/vsl-query.rst b/doc/sphinx/reference/vsl-query.rst
index 71534a4b0..6cfff6100 100644
--- a/doc/sphinx/reference/vsl-query.rst
+++ b/doc/sphinx/reference/vsl-query.rst
@@ -246,13 +246,15 @@ The following types of operands are available:
 
   A number without any fractional part, valid for the numerical
   comparison operators. The integer type is used when the operand does
-  not contain any period (.) characters.
+  not contain any period (.) nor exponent (e) characters. However if
+  the record evaluates as a float, only its integral part is used for
+  the comparison.
 
 * Float
 
   A number with a fractional part, valid for the numerical comparison
   operators. The float type is used when the operand does contain a
-  period (.) character.
+  period (.) or exponent (e) character.
 
 * String
 
@@ -329,7 +331,8 @@ QUERY EXPRESSION EXAMPLES
 HISTORY
 =======
 
-This document was written by Martin Blix Grydeland.
+This document was initially written by Martin Blix Grydeland and amended
+by others.
 
 
 COPYRIGHT
diff --git a/lib/libvarnishapi/vsl_query.c b/lib/libvarnishapi/vsl_query.c
index eb08bf18a..b214a38da 100644
--- a/lib/libvarnishapi/vsl_query.c
+++ b/lib/libvarnishapi/vsl_query.c
@@ -122,7 +122,7 @@ vslq_test_rec(const struct vex *vex, const struct VSLC_ptr *rec)
 	const struct vex_rhs *rhs;
 	long long lhs_int = 0;
 	double lhs_float = 0.;
-	const char *b, *e, *q;
+	const char *b, *e, *q, *t;
 	char *p;
 	int i, dq;
 
@@ -209,6 +209,16 @@ vslq_test_rec(const struct vex *vex, const struct VSLC_ptr *rec)
 		switch (rhs->type) {
 		case VEX_INT:
 			lhs_int = strtoll(b, &p, 0);
+			if (*p == '.' || *p == 'e') {
+				t = ""; /* assume valid float */
+				lhs_float = VNUMpfx(b, &q);
+				if (isnan(lhs_float))
+					return (0);
+				if (q != NULL)
+					t = (q > p) ? q - 1 : q;
+				p = TRUST_ME(t);
+				lhs_int = trunc(lhs_float);
+			}
 			if (*p != '\0' && !isspace(*p))
 				return (0); /* Can't parse - no match */
 			break;


More information about the varnish-commit mailing list