[master] 2d39b0790 Collect VCL_DURATION type conversion in a single function and restrict acceptable whitespace to SP and TAB.

Poul-Henning Kamp phk at FreeBSD.org
Tue Jan 29 09:43:08 UTC 2019


commit 2d39b0790f523ef7e894bea38e26f0406b269a1b
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Jan 29 08:56:34 2019 +0000

    Collect VCL_DURATION type conversion in a single function and restrict
    acceptable whitespace to SP and TAB.
    
    Part of fix for #2882

diff --git a/bin/varnishtest/tests/v00016.vtc b/bin/varnishtest/tests/v00016.vtc
index 1d1637f8c..a53bcc579 100644
--- a/bin/varnishtest/tests/v00016.vtc
+++ b/bin/varnishtest/tests/v00016.vtc
@@ -30,7 +30,7 @@ varnish v1 -errvcl {include not followed by string constant.} {
 	{ } ( ) * + - / % > < = ; ! & . | ~ ,
 }
 
-varnish v1 -errvcl {Unknown time unit 'k'.  Legal are 'ms', 's', 'm', 'h', 'd', 'w' and 'y'} {
+varnish v1 -errvcl {Unknown duration unit 'k'} {
 	backend b { .host = "127.0.0.1"; }
 	sub vcl_backend_response { set beresp.ttl = 1. k; }
 }
diff --git a/include/vnum.h b/include/vnum.h
index 266f156f5..ae8a8e1f2 100644
--- a/include/vnum.h
+++ b/include/vnum.h
@@ -31,5 +31,9 @@
 /* from libvarnish/vnum.c */
 double VNUM(const char *p);
 double VNUMpfx(const char *p, const char **e);
+vtim_dur VNUM_duration_unit(vtim_dur r, const char *b, const char *e);
 vtim_dur VNUM_duration(const char *p);
 const char *VNUM_2bytes(const char *p, uintmax_t *r, uintmax_t rel);
+
+#define VNUM_LEGAL_DURATION \
+	"Legal duration units are 'ms', 's', 'm', 'h', 'd', 'w' and 'y'"
diff --git a/lib/libvarnish/Makefile.am b/lib/libvarnish/Makefile.am
index 271b13c43..026955a5e 100644
--- a/lib/libvarnish/Makefile.am
+++ b/lib/libvarnish/Makefile.am
@@ -51,7 +51,7 @@ binheap_CFLAGS = -DTEST_DRIVER
 
 vnum_c_test_SOURCES = vnum.c vas.c
 vnum_c_test_CFLAGS = -DNUM_C_TEST -include config.h
-vnum_c_test_LDADD = ${LIBM}
+vnum_c_test_LDADD = ${LIBM} libvarnish.a
 
 vjsn_test_SOURCES = vjsn.c
 vjsn_test_CFLAGS = -DVJSN_TEST @SAN_CFLAGS@
diff --git a/lib/libvarnish/vnum.c b/lib/libvarnish/vnum.c
index 59e804ec8..99a81a8f5 100644
--- a/lib/libvarnish/vnum.c
+++ b/lib/libvarnish/vnum.c
@@ -30,14 +30,15 @@
 
 #include "config.h"
 
-#include <ctype.h>
 #include <math.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "vdef.h"
 
+#include "vct.h"
 #include "vnum.h"
 #include "vas.h"
 
@@ -61,14 +62,14 @@ VNUMpfx(const char *p, const char **t)
 	AN(p);
 	AN(t);
 	*t = NULL;
-	while (isspace(*p))
+	while (vct_issp(*p))
 		p++;
 
 	if (*p == '-' || *p == '+')
 		ms = (*p++ == '-' ? -1.0 : 1.0);
 
 	for (; *p != '\0'; p++) {
-		if (isdigit(*p)) {
+		if (vct_isdigit(*p)) {
 			m = m * 10. + *p - '0';
 			e = ne;
 			if (e)
@@ -84,12 +85,12 @@ VNUMpfx(const char *p, const char **t)
 		p++;
 		if (*p == '-' || *p == '+')
 			es = (*p++ == '-' ? -1.0 : 1.0);
-		if (!isdigit(*p))
+		if (!vct_isdigit(*p))
 			return (nan(""));
-		for (; isdigit(*p); p++)
+		for (; vct_isdigit(*p); p++)
 			ee = ee * 10. + *p - '0';
 	}
-	while (isspace(*p))
+	while (vct_issp(*p))
 		p++;
 	if (*p != '\0')
 		*t = p;
@@ -111,31 +112,25 @@ VNUM(const char *p)
 /**********************************************************************/
 
 vtim_dur
-VNUM_duration(const char *p)
+VNUM_duration_unit(vtim_dur r, const char *b, const char *e)
 {
-	const char *t;
-	vtim_dur r;
 	double sc = 1.0;
 
-	if (p == NULL)
-		return (nan(""));
-
-	r = VNUMpfx(p, &t);
+	if (e == NULL)
+		e = strchr(b, '\0');
 
-	if (isnan(r) || t == NULL)
+	while (b < e && vct_issp(*b))
+		b++;
+	if (b == e)
 		return (nan(""));
 
-	while (isspace(*t))
-		t++;
-
-	// keep in sync with vcc_expr.c vcc_TimeUnit()
-	switch (*t++) {
+	switch (*b++) {
 	case 's':
 		break;
 	case 'm':
-		if (*t == 's') {
+		if (b < e && *b == 's') {
 			sc = 1e-3;
-			t++;
+			b++;
 		} else
 			sc = 60.0;
 		break;
@@ -155,15 +150,32 @@ VNUM_duration(const char *p)
 		return (nan(""));
 	}
 
-	while (isspace(*t))
-		t++;
+	while (b < e && vct_issp(*b))
+		b++;
 
-	if (*t != '\0')
+	if (b < e)
 		return (nan(""));
 
 	return (r * sc);
 }
 
+vtim_dur
+VNUM_duration(const char *p)
+{
+	const char *t;
+	vtim_dur r;
+
+	if (p == NULL)
+		return (nan(""));
+
+	r = VNUMpfx(p, &t);
+
+	if (isnan(r) || t == NULL)
+		return (nan(""));
+
+	return (VNUM_duration_unit(r, t, NULL));
+}
+
 /**********************************************************************/
 
 const char *
diff --git a/lib/libvarnishapi/Makefile.am b/lib/libvarnishapi/Makefile.am
index a2dd76bbc..a94efee04 100644
--- a/lib/libvarnishapi/Makefile.am
+++ b/lib/libvarnishapi/Makefile.am
@@ -20,6 +20,7 @@ libvarnishapi_la_SOURCES = \
 	../../include/vcs_version.h \
 	../libvarnish/version.c \
 	../libvarnish/vcli_proto.c \
+	../libvarnish/vct.c \
 	../libvarnish/vfil.c \
 	../libvarnish/vfl.c \
 	../libvarnish/vin.c \
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index 3a98c76e0..4e7e94c05 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -334,7 +334,7 @@ void Resolve_Sockaddr(struct vcc *tl, const char *host, const char *defport,
     const struct token *t_err, const char *errid);
 void Emit_UDS_Path(struct vcc *tl, const struct token *t_path,
     const char *errid);
-double vcc_TimeUnit(struct vcc *);
+double vcc_DurationUnit(struct vcc *);
 void vcc_ByteVal(struct vcc *, double *);
 void vcc_Duration(struct vcc *tl, double *);
 unsigned vcc_UintVal(struct vcc *tl);
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index 00b6ca700..1c1f659ad 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -838,7 +838,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
 			vcc_NextToken(tl);
 			if (tl->t->tok == ID) {
 				e1 = vcc_mk_expr(DURATION, "(%s%.*s) * %g",
-				    sign, PF(t), vcc_TimeUnit(tl));
+				    sign, PF(t), vcc_DurationUnit(tl));
 				ERRCHK(tl);
 			} else if (fmt == REAL || t->tok == FNUM) {
 				e1 = vcc_mk_expr(REAL, "%s%.*s", sign, PF(t));
diff --git a/lib/libvcc/vcc_utils.c b/lib/libvcc/vcc_utils.c
index f03762b34..abe4f69b5 100644
--- a/lib/libvcc/vcc_utils.c
+++ b/lib/libvcc/vcc_utils.c
@@ -40,6 +40,7 @@
 #include "vcc_compile.h"
 
 #include "vre.h"
+#include "vnum.h"
 #include "vsa.h"
 #include "vss.h"
 #include "vtcp.h"
@@ -296,39 +297,25 @@ Emit_UDS_Path(struct vcc *tl, const struct token *t_path, const char *errid)
 }
 
 /*--------------------------------------------------------------------
- * Recognize and convert units of time, return seconds.
+ * Recognize and convert units of duration, return seconds.
  */
 
 double
-vcc_TimeUnit(struct vcc *tl)
+vcc_DurationUnit(struct vcc *tl)
 {
-	double sc = 1.0;
+	double sc;
 
 	assert(tl->t->tok == ID);
-	if (vcc_IdIs(tl->t, "ms"))
-		sc = 1e-3;
-	else if (vcc_IdIs(tl->t, "s"))
-		sc = 1.0;
-	else if (vcc_IdIs(tl->t, "m"))
-		sc = 60.0;
-	else if (vcc_IdIs(tl->t, "h"))
-		sc = 60.0 * 60.0;
-	else if (vcc_IdIs(tl->t, "d"))
-		sc = 60.0 * 60.0 * 24.0;
-	else if (vcc_IdIs(tl->t, "w"))
-		sc = 60.0 * 60.0 * 24.0 * 7.0;
-	else if (vcc_IdIs(tl->t, "y"))
-		sc = 60.0 * 60.0 * 24.0 * 365.0;
-	else {
-		VSB_printf(tl->sb, "Unknown time unit ");
-		vcc_ErrToken(tl, tl->t);
-		VSB_printf(tl->sb,
-		    ".  Legal are 'ms', 's', 'm', 'h', 'd', 'w' and 'y'\n");
-		vcc_ErrWhere(tl, tl->t);
-		return (1.0);
+	sc = VNUM_duration_unit(1.0, tl->t->b, tl->t->e);
+	if (!isnan(sc)) {
+		vcc_NextToken(tl);
+		return (sc);
 	}
-	vcc_NextToken(tl);
-	return (sc);
+	VSB_printf(tl->sb, "Unknown duration unit ");
+	vcc_ErrToken(tl, tl->t);
+	VSB_printf(tl->sb, "\n%s\n", VNUM_LEGAL_DURATION);
+	vcc_ErrWhere(tl, tl->t);
+	return (1.0);
 }
 
 /*--------------------------------------------------------------------
@@ -374,7 +361,7 @@ vcc_Duration(struct vcc *tl, double *d)
 	v = vcc_DoubleVal(tl);
 	ERRCHK(tl);
 	ExpectErr(tl, ID);
-	sc = vcc_TimeUnit(tl);
+	sc = vcc_DurationUnit(tl);
 	*d = v * sc;
 }
 
diff --git a/lib/libvmod_std/vmod_std_conversions.c b/lib/libvmod_std/vmod_std_conversions.c
index ba10fa513..05c17495b 100644
--- a/lib/libvmod_std/vmod_std_conversions.c
+++ b/lib/libvmod_std/vmod_std_conversions.c
@@ -47,10 +47,10 @@
 VCL_DURATION v_matchproto_(td_std_duration)
 vmod_duration(VRT_CTX, VCL_STRING p, VCL_DURATION d)
 {
-	double r = VNUM_duration(p);
-
-	(void) ctx;
+	double r;
 
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	r = VNUM_duration(p);
 	return (isnan(r) ? d : r);
 }
 


More information about the varnish-commit mailing list