diff --git a/include/libwebsockets/lws-tokenize.h b/include/libwebsockets/lws-tokenize.h index e9e6851fc..70379de0b 100644 --- a/include/libwebsockets/lws-tokenize.h +++ b/include/libwebsockets/lws-tokenize.h @@ -192,10 +192,15 @@ enum { * \p exp: the exp object to init * \p priv: the user's object pointer to pass to callback * \p cb: the callback to expand named objects - * \p out: the start of the output buffer + * \p out: the start of the output buffer, or NULL just to get the length * \p olen: the length of the output buffer in bytes * * Prepares an lws_strexp_t for use and sets the initial output buffer + * + * If \p out is NULL, substitution proceeds normally, but no output is produced, + * only the length is returned. olen should be set to the largest feasible + * overall length. To use this mode, the substitution callback must also check + * for NULL \p out and avoid producing the output. */ LWS_VISIBLE LWS_EXTERN void lws_strexp_init(lws_strexp_t *exp, void *priv, lws_strexp_expand_cb cb, @@ -205,12 +210,17 @@ lws_strexp_init(lws_strexp_t *exp, void *priv, lws_strexp_expand_cb cb, * lws_strexp_reset_out() - reset the output buffer on an existing strexp * * \p exp: the exp object to init - * \p out: the start of the output buffer + * \p out: the start of the output buffer, or NULL to just get length * \p olen: the length of the output buffer in bytes * * Provides a new output buffer for lws_strexp_expand() to continue to write * into. It can be the same as the old one if it has been copied out or used. * The position of the next write will be reset to the start of the given buf. + * + * If \p out is NULL, substitution proceeds normally, but no output is produced, + * only the length is returned. \p olen should be set to the largest feasible + * overall length. To use this mode, the substitution callback must also check + * for NULL \p out and avoid producing the output. */ LWS_VISIBLE LWS_EXTERN void lws_strexp_reset_out(lws_strexp_t *exp, char *out, size_t olen); diff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c index 4688b3e23..0ad9330d6 100644 --- a/lib/core/libwebsockets.c +++ b/lib/core/libwebsockets.c @@ -936,7 +936,9 @@ lws_strexp_expand(lws_strexp_t *exp, const char *in, size_t len, break; } - exp->out[exp->pos++] = *in; + if (exp->out) + exp->out[exp->pos] = *in; + exp->pos++; if (exp->olen - exp->pos < 1) { *pused_in = used + 1; *pused_out = exp->pos; @@ -955,8 +957,11 @@ lws_strexp_expand(lws_strexp_t *exp, const char *in, size_t len, if (exp->olen - exp->pos < 3) return -1; - exp->out[exp->pos++] = '$'; - exp->out[exp->pos++] = *in; + if (exp->out) { + exp->out[exp->pos++] = '$'; + exp->out[exp->pos++] = *in; + } else + exp->pos += 2; if (*in != '$') exp->state = LWS_EXPS_LITERAL; break; @@ -991,7 +996,8 @@ drain: in++; } - exp->out[exp->pos] = '\0'; + if (exp->out) + exp->out[exp->pos] = '\0'; *pused_in = used; *pused_out = exp->pos; diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 7318b4f17..a8f4ed84f 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -167,7 +167,8 @@ lws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos, if (total < budget) budget = total; - memcpy(out + *pos, replace + (*exp_ofs), budget); + if (out) + memcpy(out + *pos, replace + (*exp_ofs), budget); *exp_ofs += budget; *pos += budget; diff --git a/minimal-examples/api-tests/api-test-lws_tokenize/main.c b/minimal-examples/api-tests/api-test-lws_tokenize/main.c index 9cbc2e3ce..7682ede1f 100644 --- a/minimal-examples/api-tests/api-test-lws_tokenize/main.c +++ b/minimal-examples/api-tests/api-test-lws_tokenize/main.c @@ -299,7 +299,8 @@ expand: if (total < budget) budget = total; - memcpy(out + *pos, replace + (*exp_ofs), budget); + if (out) + memcpy(out + *pos, replace + (*exp_ofs), budget); *exp_ofs += budget; *pos += budget; @@ -354,6 +355,17 @@ int main(int argc, const char **argv) return 1; } + /* as above, but don't generate output, just find the length */ + + lws_strexp_init(&exp, NULL, exp_cb1, NULL, (size_t)-1); + n = lws_strexp_expand(&exp, exp_inp1, 28, &used_in, &used_out); + if (n != LSTRX_DONE || used_in != 28 || used_out != 39) { + lwsl_err("%s: lws_strexp test 2 failed: %d, used_out: %d\n", + __func__, n, (int)used_out); + + return 1; + } + p = exp_inp1; in_len = strlen(p); memset(obuf, 0, sizeof(obuf));