[4.1] 8e5c7a0 Add fallback on std conversion functions.

Lasse Karstensen lkarsten at varnish-software.com
Thu Sep 10 14:37:29 CEST 2015


commit 8e5c7a0a610200089d7aca5edbde6e25de5e804d
Author: Lasse Karstensen <lkarsten at varnish-software.com>
Date:   Thu Sep 10 14:21:04 2015 +0200

    Add fallback on std conversion functions.
    
    Handle that conversion between VCL data type can fail,
    and return a user-specificed fallback in those cases.
    
    Mostly identical to patch from Arianna Aondio.

diff --git a/bin/varnishtest/tests/m00016.vtc b/bin/varnishtest/tests/m00016.vtc
index ef51f93..261f840 100644
--- a/bin/varnishtest/tests/m00016.vtc
+++ b/bin/varnishtest/tests/m00016.vtc
@@ -1,4 +1,4 @@
-varnishtest "Test std.real2time, std.time2integer and std.time2real"
+varnishtest "Test real2integer, real2time, time2integer and time2real in std"
 
 server s1 {
 	rxreq
@@ -10,8 +10,18 @@ varnish v1 -vcl+backend {
 
 	sub vcl_deliver {
 		set resp.http.x-foo = std.integer(req.http.foo, 0);
-		set resp.http.x-bar = std.time2integer(std.real2time(std.real(resp.http.x-foo, 0.0)));
-		set resp.http.x-baz = std.time2real(std.real2time(std.real(resp.http.x-foo, 0.0)));
+		set resp.http.x-bar = std.time2integer(std.real2time(
+		    std.real(resp.http.x-foo, 0.0), now), 1);
+
+		set resp.http.x-baz = std.time2real(std.real2time(
+		    std.real(resp.http.x-foo, 0.0), now), 1.0);
+
+		set resp.http.x-qux = std.real2integer(
+		    std.real(req.http.foo, 2.0), 2);
+
+		# Representation of 9e99, which is larger than what fits in the
+		# 128bit integers on $exotic_platform.
+		set resp.http.x-int-fallback = std.real2integer(9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000, 2);
 	}
 } -start
 
@@ -20,4 +30,15 @@ client c1 {
 	rxresp
 	expect resp.http.x-foo == resp.http.x-bar
 	expect resp.http.x-baz == 1140618699.000
+	expect resp.http.x-qux == 1140618699
+	expect resp.http.x-int-fallback == 2
+} -run
+
+# check we get the fallback if the conversion fails
+client c2 {
+	txreq -hdr "foo: -9e99+1"
+	rxresp
+	expect resp.http.x-bar == 0
+	expect resp.http.x-baz == 0.000
+	expect resp.http.x-qux == 2
 } -run
diff --git a/bin/varnishtest/tests/r01532.vtc b/bin/varnishtest/tests/r01532.vtc
index c189f55..b1ff007 100644
--- a/bin/varnishtest/tests/r01532.vtc
+++ b/bin/varnishtest/tests/r01532.vtc
@@ -9,7 +9,7 @@ varnish v1 -vcl+backend {
 	import ${vmod_std};
 
 	sub vcl_deliver {
-		set resp.http.x-foo = std.real2time(1140618699.00);
+		set resp.http.x-foo = std.real2time(1140618699.00, now);
 	}
 } -start
 
diff --git a/lib/libvmod_std/vmod.vcc b/lib/libvmod_std/vmod.vcc
index 0ad385f..b082da3 100644
--- a/lib/libvmod_std/vmod.vcc
+++ b/lib/libvmod_std/vmod.vcc
@@ -128,7 +128,7 @@ Example
 $Function INT integer(STRING s, INT fallback)
 
 Description
-	Converts the string *s* to an integer.	If conversion fails,
+	Converts the string *s* to an integer. If conversion fails,
 	*fallback* will be returned.
 Example
 	| if (std.integer(req.http.foo, 0) > 5) {
@@ -139,7 +139,7 @@ $Function IP ip(STRING s, IP fallback)
 
 Description
 	Converts the string *s* to the first IP number returned by
-	the system library function getaddrinfo(3).  If conversion
+	the system library function getaddrinfo(3). If conversion
 	fails, *fallback* will be returned.
 Example
 	| if (std.ip(req.http.X-forwarded-for, "0.0.0.0") ~ my_acl) {
@@ -149,33 +149,44 @@ Example
 $Function REAL real(STRING s, REAL fallback)
 
 Description
-	Converts the string *s* to a real.  If conversion fails,
+	Converts the string *s* to a real. If conversion fails,
 	*fallback* will be returned.
 Example
 	| if (std.real(req.http.foo, 0.0) > 5.5) {
 	|	...
 	| }
 
-$Function TIME real2time(REAL r)
+$Function INT real2integer(REAL r, INT fallback)
 
 Description
-	Converts the real *r* to a time.
+	Converts the real *r* to an integer. If conversion fails,
+	*fallback* will be returned.
+Example
+	set req.http.integer = std.real2integer(1140618699.00, 0);
+
+$Function TIME real2time(REAL r, TIME fallback)
+
+Description
+	Converts the real *r* to a time. If conversion fails,
+	*fallback* will be returned.
 Example
-	set req.http.time = std.real2time(1140618699.00);
+	set req.http.time = std.real2time(1140618699.00, now);
 
-$Function INT time2integer(TIME t)
+$Function INT time2integer(TIME t, INT fallback)
 
 Description
-	Converts the time *t* to a integer.
+	Converts the time *t* to a integer. If conversion fails,
+	*fallback* will be returned.
 Example
-	set req.http.int = std.time2integer(now);
+	set req.http.int = std.time2integer(now, 0);
 
-$Function REAL time2real(TIME t)
+$Function REAL time2real(TIME t, REAL fallback)
 
 Description
-	Converts the time *t* to a real.
+	Converts the time *t* to a real. If conversion fails,
+	*fallback* will be returned.
 Example
-	set req.http.real = std.time2real(now);
+	set req.http.real = std.time2real(now, 1.0);
 
 $Function BOOL healthy(BACKEND be)
 
@@ -241,7 +252,7 @@ Example
 $Function TIME time(STRING s, TIME fallback)
 
 Description
-	Converts the string *s* to a time.  If conversion fails,
+	Converts the string *s* to a time. If conversion fails,
 	*fallback* will be returned.
 
 	Supported formats:
diff --git a/lib/libvmod_std/vmod_std_conversions.c b/lib/libvmod_std/vmod_std_conversions.c
index 95bb003..131c3c1 100644
--- a/lib/libvmod_std/vmod_std_conversions.c
+++ b/lib/libvmod_std/vmod_std_conversions.c
@@ -187,27 +187,51 @@ vmod_real(VRT_CTX, VCL_STRING p, VCL_REAL d)
 	return (r);
 }
 
+VCL_INT __match_proto__(td_std_real2integer)
+vmod_real2integer(VRT_CTX, VCL_REAL r, VCL_INT i)
+{
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+
+	if (!isfinite(r))
+		return (i);
+	r = round(r);
+	if (r > LONG_MAX || r < LONG_MIN)
+		return(i);
+	return ((long)r);
+}
+
 VCL_TIME __match_proto__(td_std_real2time)
-vmod_real2time(VRT_CTX, VCL_REAL r)
+vmod_real2time(VRT_CTX, VCL_REAL r, VCL_TIME t)
 {
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
 
+	if (!isfinite(r))
+		return (t);
+
 	return (r);
 }
 
 VCL_INT __match_proto__(td_std_time2integer)
-vmod_time2integer(VRT_CTX, VCL_TIME t)
+vmod_time2integer(VRT_CTX, VCL_TIME t, VCL_INT i)
 {
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
 
-	return ((long)floor(t));
+	if (!isfinite(t))
+		return (i);
+	t = round(t);
+	if (t > LONG_MAX || t < LONG_MIN)
+		return(i);
+	return ((long)t);
 }
 
 VCL_REAL __match_proto__(td_std_time2real)
-vmod_time2real(VRT_CTX, VCL_TIME t)
+vmod_time2real(VRT_CTX, VCL_TIME t, VCL_REAL r)
 {
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
 
+	if (!isfinite(t))
+		return (r);
+
 	return (t);
 }
 



More information about the varnish-commit mailing list