Skip to content
This repository was archived by the owner on Feb 16, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions bin/varnishd/cache/cache_vrt.c
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,32 @@ VRT_SetHdr(VRT_CTX, VCL_HEADER hs, const char *pfx, VCL_STRANDS s)
http_SetHeader(hp, b);
}

VCL_VOID
VRT_SetHeader(VRT_CTX, VCL_HEADER hs, const char *hdr)
{
VCL_HTTP hp;
unsigned wl, hl;

CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(hs);
AN(hs->what);
AN(hdr);

hl = strlen(hdr);
wl = hs->what[0];
assert(hl > wl);
AZ(strncasecmp(hs->what + 1, hdr, wl));
hp = VRT_selecthttp(ctx, hs->where);
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);

if (FEATURE(FEATURE_VALIDATE_HEADERS) && !validhdr(hdr + wl)) {
VRT_fail(ctx, "Bad static header %s", hdr);
return;
}
http_Unset(hp, hs->what);
http_SetHeader(hp, hdr);
}

/*--------------------------------------------------------------------*/

VCL_VOID
Expand Down
2 changes: 1 addition & 1 deletion bin/varnishtest/tests/b00040.vtc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ logexpect l1 -v v1 -g raw {
expect * 1012 BogoHeader {Header has ctrl char 0x0d}
expect * 1014 BogoHeader {Header has ctrl char 0x0d}
expect * 1016 BogoHeader {Missing header name:.*}
expect * 1018 VCL_Error {Bad header foo:}
expect * 1018 VCL_Error {Bad static header foo:}
} -start

client c1 {
Expand Down
2 changes: 2 additions & 0 deletions include/vrt.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
* BODY can either be a BLOB or a STRANDS, but only a STRANDS
* can take a non-NULL const char * prefix. The changes to BODY
* assignments doesn't break the ABI or the API.
* VRT_SetHeader() added
*
* 14.0 (2021-09-15)
* VIN_n_Arg() no directly returns the directory name.
Expand Down Expand Up @@ -646,6 +647,7 @@ VCL_VOID VRT_hit_for_pass(VRT_CTX, VCL_DURATION);
VCL_BOOL VRT_ValidHdr(VRT_CTX, VCL_STRANDS);
VCL_VOID VRT_UnsetHdr(VRT_CTX, VCL_HEADER);
VCL_VOID VRT_SetHdr(VRT_CTX, VCL_HEADER, const char *pfx, VCL_STRANDS);
VCL_VOID VRT_SetHeader(VRT_CTX, VCL_HEADER, const char *);
VCL_VOID VRT_handling(VRT_CTX, unsigned hand);
unsigned VRT_handled(VRT_CTX);
VCL_VOID VRT_fail(VRT_CTX, const char *fmt, ...) v_printflike_(2,3);
Expand Down
86 changes: 43 additions & 43 deletions lib/libvcc/vcc_action.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,67 +91,69 @@ vcc_act_call(struct vcc *tl, struct token *t, struct symbol *sym)
Fb(tl, 1, "}\n");
}

/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------
* We borrow the edit string syntax from vcc_expr.c and use the \v2
* sequence to refer to the symbol as itself on the RHS.
*/

static const struct assign {
vcc_type_t type;
unsigned oper;
vcc_type_t want;
const char *expr;
const char *edit;
} assign[] = {
{ INT, T_INCR, INT, "\v + " },
{ INT, T_DECR, INT, "\v - " },
{ INT, T_MUL, INT, "\v * " },
{ INT, T_DIV, INT, "\v / " },
{ INT, T_INCR, INT, "\v2 + " },
{ INT, T_DECR, INT, "\v2 - " },
{ INT, T_MUL, INT, "\v2 * " },
{ INT, T_DIV, INT, "\v2 / " },
{ INT, '=', INT },
{ INT, 0, INT },
{ TIME, T_INCR, DURATION, "\v + " },
{ TIME, T_DECR, DURATION, "\v - " },
{ TIME, T_MUL, REAL, "\v * " },
{ TIME, T_DIV, REAL, "\v / " },
{ TIME, T_INCR, DURATION, "\v2 + " },
{ TIME, T_DECR, DURATION, "\v2 - " },
{ TIME, T_MUL, REAL, "\v2 * " },
{ TIME, T_DIV, REAL, "\v2 / " },
{ TIME, '=', TIME },
{ TIME, 0, TIME },
{ DURATION, T_INCR, DURATION, "\v + " },
{ DURATION, T_DECR, DURATION, "\v - " },
{ DURATION, T_MUL, REAL, "\v * " },
{ DURATION, T_DIV, REAL, "\v / " },
{ DURATION, T_INCR, DURATION, "\v2 + " },
{ DURATION, T_DECR, DURATION, "\v2 - " },
{ DURATION, T_MUL, REAL, "\v2 * " },
{ DURATION, T_DIV, REAL, "\v2 / " },
{ DURATION, '=', DURATION },
{ DURATION, 0, DURATION },
{ STRING, T_INCR, STRANDS, "\v,\n" },
{ STRING, T_INCR, STRANDS, "\v2,\n" },
{ STRING, '=', STRANDS, "0,\n" },
{ HEADER, T_INCR, STRANDS, "VRT_GetHdr(ctx, \v),\n" },
{ HEADER, T_INCR, STRANDS, "VRT_GetHdr(ctx, \v2),\n" },
{ HEADER, '=', STRANDS, "0,\n" },
{ BODY, '=', BODY, "LBODY_SET_" },
{ BODY, T_INCR, BODY, "LBODY_ADD_" },
{ VOID, '=', VOID }
};

static void
vcc_assign_expr(struct vcc *tl, struct symbol *sym, const struct assign *ap)
vcc_assign_edit(struct vsb *vsb, struct symbol *sym, const struct assign *ap)
{
const char *e;
unsigned indent = 1;

e = ap->expr;
if (e == NULL)
return;

while (*e != '\0') {
if (*e == '\v')
Fb(tl, indent, "%s", sym->rname);
else
Fb(tl, indent, "%c", *e);
indent = 0;
e++;
VSB_printf(vsb, "%s\n\v+", sym->lname);
for (e = ap->edit; e != NULL && *e != '\0'; e++) {
if (*e == '\v' && e[1] == '2') {
VSB_cat(vsb, sym->rname);
e++;
continue;
}
VSB_putc(vsb, *e);
}
VSB_cat(vsb, "\v1\v-);\n");
}

/*--------------------------------------------------------------------*/

static void v_matchproto_(sym_act_f)
vcc_act_set(struct vcc *tl, struct token *t, struct symbol *sym)
{
const char *const_assign = NULL;
const struct assign *ap;
struct vsb *vsb;
vcc_type_t type;

(void)t;
Expand All @@ -176,13 +178,16 @@ vcc_act_set(struct vcc *tl, struct token *t, struct symbol *sym)
if (ap->type == VOID)
SkipToken(tl, ap->oper);

Fb(tl, 1, "%s\n", sym->lname);
tl->indent += INDENT;
vcc_assign_expr(tl, sym, ap);
vcc_Expr(tl, type);
ERRCHK(tl);
tl->indent -= INDENT;
Fb(tl, 1, ");\n");
vsb = VSB_new_auto();
AN(vsb);
vcc_assign_edit(vsb, sym, ap);
AZ(VSB_finish(vsb));

if (ap->oper == '=')
const_assign = sym->const_assign;

vcc_ExprEdit(tl, type, VSB_data(vsb), const_assign);
VSB_destroy(&vsb);
SkipToken(tl, ';');
}

Expand Down Expand Up @@ -218,14 +223,9 @@ vcc_act_ban(struct vcc *tl, struct token *t, struct symbol *sym)
(void)sym;

SkipToken(tl, '(');

Fb(tl, 1, "(void) VRT_ban_string(ctx, \n");
tl->indent += INDENT;
vcc_Expr(tl, STRING);
tl->indent -= INDENT;
vcc_ExprEdit(tl, STRING,
"(void) VRT_ban_string(ctx,\v+\n\v1\v-);\n", NULL);
ERRCHK(tl);
Fb(tl, 1, ");\n");

SkipToken(tl, ')');
SkipToken(tl, ';');
}
Expand Down
3 changes: 2 additions & 1 deletion lib/libvcc/vcc_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ struct type {
vcc_type_t multype;
int stringform;
int bodyform;
int noindent;
};

#define VCC_TYPE(UC, lc) extern const struct type UC[1];
Expand Down Expand Up @@ -201,6 +200,7 @@ struct symbol {
unsigned w_methods;
const char *uname;
unsigned u_methods;
const char *const_assign;
};

VTAILQ_HEAD(tokenhead, token);
Expand Down Expand Up @@ -348,6 +348,7 @@ char *TlDup(struct vcc *tl, const char *s);

/* vcc_expr.c */
void vcc_Expr(struct vcc *tl, vcc_type_t typ);
void vcc_ExprEdit(struct vcc *tl, vcc_type_t typ, const char *, const char *);
sym_act_f vcc_Act_Call;
sym_act_f vcc_Act_Obj;
void vcc_Expr_Init(struct vcc *tl);
Expand Down
64 changes: 56 additions & 8 deletions lib/libvcc/vcc_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ struct expr {
vcc_type_t fmt;
struct vsb *vsb;
uint8_t constant;
struct expr *constant_expr;
#define EXPR_VAR (1<<0)
#define EXPR_CONST (1<<1)
#define EXPR_STR_CONST (1<<2) // Last string elem is "..."
Expand Down Expand Up @@ -95,7 +96,6 @@ vcc_new_expr(vcc_type_t fmt)
AN(e);
e->vsb = VSB_new_auto();
e->fmt = fmt;
e->constant = EXPR_VAR;
return (e);
}

Expand All @@ -106,6 +106,7 @@ vcc_mk_expr(vcc_type_t fmt, const char *str, ...)
struct expr *e;

e = vcc_new_expr(fmt);
e->constant = EXPR_VAR;
va_start(ap, str);
VSB_vprintf(e->vsb, str, ap);
va_end(ap);
Expand All @@ -119,6 +120,7 @@ vcc_delete_expr(struct expr *e)
if (e == NULL)
return;
CHECK_OBJ(e, EXPR_MAGIC);
vcc_delete_expr(e->constant_expr);
VSB_destroy(&e->vsb);
FREE_OBJ(e);
}
Expand Down Expand Up @@ -149,9 +151,10 @@ vcc_delete_expr(struct expr *e)
*/

static void
vcc_strands_edit(const struct expr *e1, const struct expr *e2)
vcc_strands_edit(struct expr *e1, const struct expr *e2)
{

e1->constant = EXPR_VAR;
if (e2->nstr == 1) {
VSB_printf(e1->vsb, "TOSTRAND(%s)", VSB_data(e2->vsb));
return;
Expand All @@ -172,6 +175,15 @@ vcc_expr_edit(struct vcc *tl, vcc_type_t fmt, const char *p, struct expr *e1,

AN(e1);
e = vcc_new_expr(fmt);

/* NB: An expression with two operands is enough to be considered
* variable, even if both operands are constant.
*/
if ((e1->constant & EXPR_VAR) || e2 != NULL)
e->constant = EXPR_VAR;
else
e->constant = e1->constant;

while (*p != '\0') {
if (*p != '\v') {
if (*p != '\n' || !nl)
Expand Down Expand Up @@ -222,7 +234,10 @@ vcc_expr_edit(struct vcc *tl, vcc_type_t fmt, const char *p, struct expr *e1,
e->t2 = e1->t2;
if (e2 != NULL)
e->t2 = e2->t2;
vcc_delete_expr(e1);
if (!(e1->constant & EXPR_VAR) && e2 == NULL)
e->constant_expr = e1;
else
vcc_delete_expr(e1);
vcc_delete_expr(e2);
return (e);
}
Expand All @@ -237,10 +252,8 @@ vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1)
char *p;
int i;

if (!e1->fmt->noindent) {
for (i = 0; i < ind; i++)
VSB_putc(d, ' ');
}
for (i = 0; i < ind; i++)
VSB_putc(d, ' ');
p = VSB_data(e1->vsb);
while (*p != '\0') {
if (*p == '\n') {
Expand Down Expand Up @@ -271,6 +284,7 @@ vcc_expr_tobool(struct vcc *tl, struct expr **e)

if ((*e)->fmt == BOOL)
return;
(*e)->constant = EXPR_VAR;
if ((*e)->fmt == BACKEND || (*e)->fmt == INT)
*e = vcc_expr_edit(tl, BOOL, "(\v1 != 0)", *e, NULL);
else if ((*e)->fmt == DURATION)
Expand Down Expand Up @@ -948,6 +962,11 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
return;
}

/* NB: we have no idea what method calls do, at this point all
* bets are off.
*/
(*e)->constant = EXPR_VAR;

AN(sym->eval);
sym->eval(tl, e, tl->t, sym, sym->type);
ERRCHK(tl);
Expand Down Expand Up @@ -1489,13 +1508,42 @@ vcc_expr_typecheck(struct vcc *tl, struct expr **e, vcc_type_t fmt,
void
vcc_Expr(struct vcc *tl, vcc_type_t fmt)
{
struct expr *e = NULL;

vcc_ExprEdit(tl, fmt, NULL, NULL);
}

void
vcc_ExprEdit(struct vcc *tl, vcc_type_t fmt, const char *var_edit,
const char *const_edit)
{
struct expr *e = NULL, *e1 = NULL;
const char *edit = NULL;

assert(fmt != VOID);
assert(fmt != STRINGS);
vcc_expr0(tl, &e, fmt);
ERRCHK(tl);
assert(e->fmt == fmt);
if (const_edit != NULL)
AN(var_edit);

if (e->constant & EXPR_VAR) {
if (e->constant_expr != NULL) {
edit = const_edit;
e1 = e->constant_expr;
}
} else {
edit = const_edit;
e1 = e;
}

if (edit == NULL) {
edit = var_edit;
e1 = e;
}

if (edit != NULL)
e = vcc_expr_edit(tl, e1->fmt, edit, e1, NULL);

vcc_expr_fmt(tl->fb, tl->indent, e);
VSB_cat(tl->fb, "\n");
Expand Down
1 change: 0 additions & 1 deletion lib/libvcc/vcc_types.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ const struct type BLOB[1] = {{
const struct type BODY[1] = {{
.magic = TYPE_MAGIC,
.name = "BODY",
.noindent = 1,
}};

const struct type BOOL[1] = {{
Expand Down
5 changes: 5 additions & 0 deletions lib/libvcc/vcc_var.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,10 @@ vcc_Var_Wildcard(struct vcc *tl, struct symbol *parent, struct symbol *sym)
VSB_printf(vsb, "VRT_UnsetHdr(ctx, %s)", sym->rname);
AZ(VSB_finish(vsb));
sym->uname = TlDup(tl, VSB_data(vsb));
VSB_clear(vsb);
VSB_printf(vsb, "VRT_SetHeader(ctx, %s, \"%s: \" \v1);",
sym->rname, sym->name);
AZ(VSB_finish(vsb));
sym->const_assign = TlDup(tl, VSB_data(vsb));
VSB_destroy(&vsb);
}