Commit d5bbb1a9 authored by Dridi Boukelmoune's avatar Dridi Boukelmoune

vsl: Tolerate float LHS with int RHS in queries

Only if strtoll(3) stumbled upon a VNUM special character.

Fixes #3463
parent 306b43a5
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
......@@ -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
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment