From ccd8e5b57d75de07aa4026de0a985beb8aaedd8e Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 4 Aug 2026 11:04:06 +0200 Subject: [PATCH] MINOR: sample: make the param converter support control characters Sometimes it can be convenient to support delimiting of the param() converter using control characters that can be found in some request bodies. Since the converter only supports a single character, we can easily make an exception for "0xHH". That's what this patch does. The reg-test was updated to include one 0x26. --- doc/configuration.txt | 7 ++++++- reg-tests/converter/param.vtc | 2 +- src/sample.c | 16 +++++++++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 7fa73bede..545907a6a 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -22587,7 +22587,12 @@ param([,]) where parameters are delimited by , which defaults to "&", and the name and value of the parameter are separated by a "=". If there is no "=" and value before the end of the parameter segment, it is treated as equivalent to - a value of an empty string. + a value of an empty string. The delimiter must be either a single character, + or it can be the hexadecimal encoding of the delimiter's ASCII code in the + form "0xHH" (either upper or lower case). The hex form may sometimes be + needed to represent a NUL character or more generally control characters that + cannot be expressed in the configuration, and that can be found in request + bodies (see req.body). This can be useful for extracting parameters from a query string, or possibly a x-www-form-urlencoded body. In particular, `query,param()` can be used diff --git a/reg-tests/converter/param.vtc b/reg-tests/converter/param.vtc index c33dc64ea..d549b5baa 100644 --- a/reg-tests/converter/param.vtc +++ b/reg-tests/converter/param.vtc @@ -24,7 +24,7 @@ haproxy h1 -conf { ### requests http-request set-var(txn.query) query - http-response set-header Found %[var(txn.query),param(test)] if { var(txn.query),param(test) -m found } + http-response set-header Found %[var(txn.query),param(test)] if { var(txn.query),param(test,0x26) -m found } default_backend be diff --git a/src/sample.c b/src/sample.c index 5230db4a2..d24225fe1 100644 --- a/src/sample.c +++ b/src/sample.c @@ -3213,8 +3213,22 @@ found: static int sample_conv_param_check(struct arg *arg, struct sample_conv *conv, const char *file, int line, char **err) { + if (arg[1].type == ARGT_STR && arg[1].data.str.data == 4 && + strncmp(arg[1].data.str.area, "0x", 2) == 0) { + /* 0x can be decoded */ + char *err = NULL; + int i = strtol(arg[1].data.str.area, &err, 0); + + if (!err || !*err) { + arg[1].data.str.area[0] = i; + arg[1].data.str.data = 1; + return 1; + } + /* otherwise fall back to the error message */ + } + if (arg[1].type == ARGT_STR && arg[1].data.str.data != 1) { - memprintf(err, "Delimiter must be exactly 1 character."); + memprintf(err, "Delimiter must be either exactly 1 character, or 0xHH for an ASCII code ."); return 0; } -- 2.47.3