From 0ab4a707fb0f5ef9deec59e8ed87645384f2af28 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 4 Nov 2019 10:54:50 +0000 Subject: [PATCH] format strings: ban %.*s as some platforms lack it The %.*s is very handy to print strings where you have a length, but there is no NUL termination. It's quite widely supported but at least one vendor RTOS toolchain doesn't have it. Since there aren't that many uses of it yet, audit all uses and convert to a new helper lws_strnncpy() which uses the smaller of two lengths. --- include/libwebsockets/lws-misc.h | 8 ++ lib/abstract/protocols/smtp/smtp.c | 11 ++- lib/jose/jwe/jwe.c | 17 ++-- lib/jose/jwk/jwk.c | 25 +++-- lib/jose/jws/jose.c | 2 +- lib/jose/jws/jws.c | 46 +++++---- lib/roles/http/client/client-handshake.c | 96 ++++++++++++------- lib/roles/http/parsers.c | 20 +++- lib/roles/ws/server-ws.c | 5 +- .../abstract/protocols/smtp-client/main.c | 8 +- .../api-tests/api-test-lws_tokenize/main.c | 37 +++++-- .../minimal-http-client/minimal-http-client.c | 10 +- 12 files changed, 189 insertions(+), 96 deletions(-) diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h index cda0ac1d3..1f6b0f167 100644 --- a/include/libwebsockets/lws-misc.h +++ b/include/libwebsockets/lws-misc.h @@ -163,6 +163,14 @@ lws_snprintf(char *str, size_t size, const char *format, ...) LWS_FORMAT(3); LWS_VISIBLE LWS_EXTERN char * lws_strncpy(char *dest, const char *src, size_t size); +/* + * Variation where we want to use the smaller of two lengths, useful when the + * source string is not NUL terminated + */ +#define lws_strnncpy(dest, src, size1, destsize) \ + lws_strncpy(dest, src, (size_t)(size1 + 1) < (size_t)(destsize) ? \ + (size_t)(size1 + 1) : (size_t)(destsize)) + /** * lws_hex_to_byte_array(): convert hex string like 0123456789ab into byte data * diff --git a/lib/abstract/protocols/smtp/smtp.c b/lib/abstract/protocols/smtp/smtp.c index 78adf1a61..542c4fa32 100644 --- a/lib/abstract/protocols/smtp/smtp.c +++ b/lib/abstract/protocols/smtp/smtp.c @@ -170,7 +170,7 @@ static int lws_smtpc_abs_rx(lws_abs_protocol_inst_t *api, const uint8_t *buf, size_t len) { lws_smtpcp_t *c = (lws_smtpcp_t *)api; - char at[5]; + char dotstar[96], at[5]; int n; c->abs->at->set_timeout(c->abs->ati, NO_PENDING_TIMEOUT, 0); @@ -186,7 +186,9 @@ lws_smtpc_abs_rx(lws_abs_protocol_inst_t *api, const uint8_t *buf, size_t len) * even get started, so fail the transport connection * (and anything queued on it) */ - lwsl_err("%s: server: %.*s\n", __func__, (int)len, buf); + + lws_strnncpy(dotstar, buf, len, sizeof(dotstar)); + lwsl_err("%s: server: %s\n", __func__, dotstar); return 1; } @@ -213,8 +215,9 @@ lws_smtpc_abs_rx(lws_abs_protocol_inst_t *api, const uint8_t *buf, size_t len) default: if (n != retcodes[c->estate]) { - lwsl_notice("%s: bad response: %d (state %d) %.*s\n", - __func__, n, c->estate, (int)len, buf); + lws_strnncpy(dotstar, buf, len, sizeof(dotstar)); + lwsl_notice("%s: bad response: %d (state %d) %s\n", + __func__, n, c->estate, dotstar); lws_smtpc_email_disposition(c, LWS_SMTP_DISPOSITION_FAILED, buf, len); diff --git a/lib/jose/jwe/jwe.c b/lib/jose/jwe/jwe.c index 5c04d950e..bf43a1908 100644 --- a/lib/jose/jwe/jwe.c +++ b/lib/jose/jwe/jwe.c @@ -323,20 +323,21 @@ LWS_VISIBLE int lws_jwe_auth_and_decrypt(struct lws_jwe *jwe, char *temp, int *temp_len) { int valid_aescbc_hmac, valid_aesgcm; + char dotstar[96]; if (lws_jwe_parse_jose(&jwe->jose, jwe->jws.map.buf[LJWS_JOSE], jwe->jws.map.len[LJWS_JOSE], temp, temp_len) < 0) { - lwsl_err("%s: JOSE parse '%.*s' failed\n", __func__, - jwe->jws.map.len[LJWS_JOSE], - jwe->jws.map.buf[LJWS_JOSE]); + lws_strnncpy(dotstar, jwe->jws.map.buf[LJWS_JOSE], + jwe->jws.map.len[LJWS_JOSE], sizeof(dotstar)); + lwsl_err("%s: JOSE parse '%s' failed\n", __func__, dotstar); return -1; } if (!jwe->jose.alg) { - lwsl_err("%s: no jose.alg: %.*s\n", __func__, - jwe->jws.map.len[LJWS_JOSE], - jwe->jws.map.buf[LJWS_JOSE]); + lws_strnncpy(dotstar, jwe->jws.map.buf[LJWS_JOSE], + jwe->jws.map.len[LJWS_JOSE], sizeof(dotstar)); + lwsl_err("%s: no jose.alg: %s\n", __func__, dotstar); return -1; } @@ -757,7 +758,9 @@ lws_jwe_render_flattened(struct lws_jwe *jwe, char *out, size_t out_len) /* unprotected not supported atm */ - p1 += lws_snprintf(p1, end1 - p1, "\",\n\"header\":%.*s", jlen, buf); + p1 += lws_snprintf(p1, end1 - p1, "\",\n\"header\":"); + lws_strnncpy(p1, buf, jlen, end1 - p1); + p1 += strlen(p1); for (m = 0; m < (int)LWS_ARRAY_SIZE(protected_en); m++) if (jwe->jws.map.buf[protected_idx[m]]) { diff --git a/lib/jose/jwk/jwk.c b/lib/jose/jwk/jwk.c index 61190a021..bbf5031b8 100644 --- a/lib/jose/jwk/jwk.c +++ b/lib/jose/jwk/jwk.c @@ -300,6 +300,7 @@ cb_jwk(struct lejp_ctx *ctx, char reason) struct lws_jwk_parse_state *jps = (struct lws_jwk_parse_state *)ctx->user; struct lws_jwk *jwk = jps->jwk; unsigned int idx, poss, n; + char dotstar[64]; if (reason == LEJPCB_VAL_STR_START) jps->pos = 0; @@ -460,8 +461,8 @@ cb_jwk(struct lejp_ctx *ctx, char reason) jps->possible = F_EC; goto cont; } - lwsl_err("%s: Unknown KTY '%.*s'\n", __func__, ctx->npos, - ctx->buf); + lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); + lwsl_err("%s: Unknown KTY '%s'\n", __func__, dotstar); return -1; default: @@ -764,9 +765,12 @@ lws_jwk_export(struct lws_jwk *jwk, int flags, char *p, int *len) if (!first) *p++ = ','; first = 0; - p += lws_snprintf(p, end - p, "\"%s\":\"%.*s\"", - l->name, jwk->meta[l->idx].len, - jwk->meta[l->idx].buf); + p += lws_snprintf(p, end - p, "\"%s\":\"", + l->name); + lws_strnncpy(p, (const char *)jwk->meta[l->idx].buf, + jwk->meta[l->idx].len, end - p); + p += strlen(p); + p += lws_snprintf(p, end - p, "\""); break; } } @@ -780,11 +784,12 @@ lws_jwk_export(struct lws_jwk *jwk, int flags, char *p, int *len) p += lws_snprintf(p, end - p, "\"%s\":\"", l->name); if (jwk->kty == LWS_GENCRYPTO_KTY_EC && - l->idx == (int)LWS_GENCRYPTO_EC_KEYEL_CRV) - m = lws_snprintf(p, end - p, "%.*s", - jwk->e[l->idx].len, - (const char *)jwk->e[l->idx].buf); - else + l->idx == (int)LWS_GENCRYPTO_EC_KEYEL_CRV) { + lws_strnncpy(p, + (const char *)jwk->e[l->idx].buf, + jwk->e[l->idx].len, end - p); + m = strlen(p); + } else m = lws_jws_base64_enc( (const char *)jwk->e[l->idx].buf, jwk->e[l->idx].len, p, end - p - 4); diff --git a/lib/jose/jws/jose.c b/lib/jose/jws/jose.c index bf0e63be8..7d9ba33a5 100644 --- a/lib/jose/jws/jose.c +++ b/lib/jose/jws/jose.c @@ -433,7 +433,7 @@ lws_jose_parse(struct lws_jose *jose, const uint8_t *buf, int n, m = (int)(signed char)lejp_parse(&jctx, (uint8_t *)buf, n); lejp_destruct(&jctx); if (m < 0) { - lwsl_notice("%s: parse %.*s returned %d\n", __func__, n, buf, m); + lwsl_notice("%s: parse returned %d\n", __func__, m); return -1; } diff --git a/lib/jose/jws/jws.c b/lib/jose/jws/jws.c index 5de4d0b2b..87b8e2eef 100644 --- a/lib/jose/jws/jws.c +++ b/lib/jose/jws/jws.c @@ -895,20 +895,29 @@ lws_jws_write_flattened_json(struct lws_jws *jws, char *flattened, size_t len) if (len < 1) return 1; - n += lws_snprintf(flattened + n, len - n , "{\"payload\": \"%.*s\",\n", - jws->map_b64.len[LJWS_PYLD], - jws->map_b64.buf[LJWS_PYLD]); + n += lws_snprintf(flattened + n, len - n , "{\"payload\": \""); + lws_strnncpy(flattened + n, jws->map_b64.buf[LJWS_PYLD], + jws->map_b64.len[LJWS_PYLD], len - n); + n += strlen(flattened + n); - n += lws_snprintf(flattened + n, len - n , " \"protected\": \"%.*s\",\n", - jws->map_b64.len[LJWS_JOSE], - jws->map_b64.buf[LJWS_JOSE]); + n += lws_snprintf(flattened + n, len - n , "\",\n \"protected\": \""); + lws_strnncpy(flattened + n, jws->map_b64.buf[LJWS_JOSE], + jws->map_b64.len[LJWS_JOSE], len - n); + n += strlen(flattened + n); - if (jws->map_b64.buf[LJWS_UHDR]) - n += lws_snprintf(flattened + n, len - n , " \"header\": %.*s,\n", - jws->map_b64.len[LJWS_UHDR], jws->map_b64.buf[LJWS_UHDR]); + if (jws->map_b64.buf[LJWS_UHDR]) { + n += lws_snprintf(flattened + n, len - n , "\",\n \"header\": "); + lws_strnncpy(flattened + n, jws->map_b64.buf[LJWS_UHDR], + jws->map_b64.len[LJWS_UHDR], len - n); + n += strlen(flattened + n); + } - n += lws_snprintf(flattened + n, len - n , " \"signature\": \"%.*s\"}\n", - jws->map_b64.len[LJWS_SIG], jws->map_b64.buf[LJWS_SIG]); + n += lws_snprintf(flattened + n, len - n , "\",\n \"signature\": \""); + lws_strnncpy(flattened + n, jws->map_b64.buf[LJWS_SIG], + jws->map_b64.len[LJWS_SIG], len - n); + n += strlen(flattened + n); + + n += lws_snprintf(flattened + n, len - n , "\"}\n"); return (n >= len - 1); } @@ -921,12 +930,15 @@ lws_jws_write_compact(struct lws_jws *jws, char *compact, size_t len) if (len < 1) return 1; - n += lws_snprintf(compact + n, len - n , "%.*s", - jws->map_b64.len[LJWS_JOSE], jws->map_b64.buf[LJWS_JOSE]); - n += lws_snprintf(compact + n, len - n , ".%.*s", - jws->map_b64.len[LJWS_PYLD], jws->map_b64.buf[LJWS_PYLD]); - n += lws_snprintf(compact + n, len - n , ".%.*s", - jws->map_b64.len[LJWS_SIG], jws->map_b64.buf[LJWS_SIG]); + lws_strnncpy(compact + n, jws->map_b64.buf[LJWS_JOSE], + jws->map_b64.len[LJWS_JOSE], len - n); + n += strlen(compact + n); + lws_strnncpy(compact + n, jws->map_b64.buf[LJWS_PYLD], + jws->map_b64.len[LJWS_PYLD], len - n); + n += strlen(compact + n); + lws_strnncpy(compact + n, jws->map_b64.buf[LJWS_SIG], + jws->map_b64.len[LJWS_SIG], len - n); + n += strlen(compact + n); return n >= len - 1; } diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index 368a0323e..278a66f21 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -1061,36 +1061,43 @@ html_parser_cb(const hubbub_token *token, void *pw) { struct lws_rewrite *r = (struct lws_rewrite *)pw; char buf[1024], *start = buf + LWS_PRE, *p = start, - *end = &buf[sizeof(buf) - 1]; + *end = &buf[sizeof(buf) - 1], dotstar[128]; size_t i; switch (token->type) { case HUBBUB_TOKEN_DOCTYPE: - p += lws_snprintf(p, end - p, "data.doctype.name.len, - token->data.doctype.name.ptr, - token->data.doctype.force_quirks ? + lws_strnncpy(dotstar, token->data.doctype.name.ptr, + token->data.doctype.name.len, sizeof(dotstar)); + + p += lws_snprintf(p, end - p, "data.doctype.force_quirks ? "(force-quirks) " : ""); if (token->data.doctype.public_missing) lwsl_debug("\tpublic: missing\n"); - else - p += lws_snprintf(p, end - p, "PUBLIC \"%.*s\"\n", - (int) token->data.doctype.public_id.len, - token->data.doctype.public_id.ptr); + else { + lws_strnncpy(dotstar, token->data.doctype.public_id.ptr, + token->data.doctype.public_id.len, + sizeof(dotstar)); + p += lws_snprintf(p, end - p, "PUBLIC \"%s\"\n", + dotstar); + } if (token->data.doctype.system_missing) lwsl_debug("\tsystem: missing\n"); - else - p += lws_snprintf(p, end - p, " \"%.*s\">\n", - (int) token->data.doctype.system_id.len, - token->data.doctype.system_id.ptr); + else { + lws_strnncpy(dotstar, token->data.doctype.system_id.ptr, + token->data.doctype.system_id.len, + sizeof(dotstar)); + p += lws_snprintf(p, end - p, " \"%s\">\n", dotstar); + } break; case HUBBUB_TOKEN_START_TAG: - p += lws_snprintf(p, end - p, "<%.*s", (int)token->data.tag.name.len, - token->data.tag.name.ptr); + lws_strnncpy(dotstar, token->data.tag.name.ptr, + token->data.tag.name.len, sizeof(dotstar)); + p += lws_snprintf(p, end - p, "<%s", dotstar); /* (token->data.tag.self_closing) ? "(self-closing) " : "", @@ -1111,25 +1118,37 @@ html_parser_cb(const hubbub_token *token, void *pw) pp += r->from_len; plen -= r->from_len; } - p += lws_snprintf(p, end - p, " %.*s=\"%s/%.*s\"", - (int) token->data.tag.attributes[i].name.len, - token->data.tag.attributes[i].name.ptr, - r->to, plen, pp); + lws_strnncpy(dotstar, + token->data.tag.attributes[i].name.ptr, + token->data.tag.attributes[i].name.len, + sizeof(dotstar)); + + p += lws_snprintf(p, end - p, " %s=\"%s", + dotstar, r->to); + lws_strnncpy(dotstar, pp, plen, sizeof(dotstar)); + p += lws_snprintf(p, end - p, " /%s\"", dotstar); continue; } } - p += lws_snprintf(p, end - p, " %.*s=\"%.*s\"", - (int) token->data.tag.attributes[i].name.len, + lws_strnncpy(dotstar, token->data.tag.attributes[i].name.ptr, - (int) token->data.tag.attributes[i].value.len, - token->data.tag.attributes[i].value.ptr); + token->data.tag.attributes[i].name.len, + sizeof(dotstar)); + + p += lws_snprintf(p, end - p, " %s=\"", dotstar); + lws_strnncpy(dotstar, + token->data.tag.attributes[i].value.ptr, + token->data.tag.attributes[i].value.len, + sizeof(dotstar)); + p += lws_snprintf(p, end - p, "%s\"", dotstar); } p += lws_snprintf(p, end - p, ">"); break; case HUBBUB_TOKEN_END_TAG: - p += lws_snprintf(p, end - p, "data.tag.name.len, - token->data.tag.name.ptr); + lws_strnncpy(dotstar, token->data.tag.name.ptr, + token->data.tag.name.len, sizeof(dotstar)); + p += lws_snprintf(p, end - p, "data.tag.self_closing) ? "(self-closing) " : "", @@ -1137,18 +1156,23 @@ html_parser_cb(const hubbub_token *token, void *pw) "attributes:" : ""); */ for (i = 0; i < token->data.tag.n_attributes; i++) { - p += lws_snprintf(p, end - p, " %.*s='%.*s'\n", - (int) token->data.tag.attributes[i].name.len, - token->data.tag.attributes[i].name.ptr, - (int) token->data.tag.attributes[i].value.len, - token->data.tag.attributes[i].value.ptr); + lws_strnncpy(dotstar, + token->data.tag.attributes[i].name.ptr, + token->data.tag.attributes[i].name.len, + sizeof(dotstar)); + p += lws_snprintf(p, end - p, " %s='", dotstar); + lws_strnncpy(dotstar, + token->data.tag.attributes[i].value.ptr, + token->data.tag.attributes[i].value.len, + sizeof(dotstar)); + p += lws_snprintf(p, end - p, "%s'\n", dotstar); } p += lws_snprintf(p, end - p, ">"); break; case HUBBUB_TOKEN_COMMENT: - p += lws_snprintf(p, end - p, "\n", - (int) token->data.comment.len, - token->data.comment.ptr); + lws_strnncpy(dotstar, token->data.comment.ptr, + token->data.comment.len, sizeof(dotstar)); + p += lws_snprintf(p, end - p, "\n", dotstar); break; case HUBBUB_TOKEN_CHARACTER: if (token->data.character.len == 1) { @@ -1165,9 +1189,9 @@ html_parser_cb(const hubbub_token *token, void *pw) break; } } - - p += lws_snprintf(p, end - p, "%.*s", (int) token->data.character.len, - token->data.character.ptr); + lws_strnncpy(dotstar, token->data.character.ptr, + token->data.character.len, sizeof(dotstar)); + p += lws_snprintf(p, end - p, "%s", dotstar); break; case HUBBUB_TOKEN_EOF: p += lws_snprintf(p, end - p, "\n"); diff --git a/lib/roles/http/parsers.c b/lib/roles/http/parsers.c index 51ff6b9bb..985e7d601 100644 --- a/lib/roles/http/parsers.c +++ b/lib/roles/http/parsers.c @@ -1108,6 +1108,11 @@ swallow: #if defined(LWS_WITH_CUSTOM_HEADERS) if (!wsi->http2_substream && pos < 0 && c == ':') { +#if defined(_DEBUG) + char dotstar[64]; + int uhlen; +#endif + /* * process unknown headers * @@ -1124,11 +1129,16 @@ swallow: ah->unk_ll_tail = ah->unk_pos; - lwsl_debug("%s: unk header %d '%.*s'\n", - __func__, - ah->pos - (ah->unk_pos + UHO_NAME), - ah->pos - (ah->unk_pos + UHO_NAME), - &ah->data[ah->unk_pos + UHO_NAME]); +#if defined(_DEBUG) + uhlen = ah->pos - (ah->unk_pos + UHO_NAME); + lws_strnncpy(dotstar, + &ah->data[ah->unk_pos + UHO_NAME], + uhlen, sizeof(dotstar)); + lwsl_debug("%s: unk header %d '%s'\n", + __func__, + ah->pos - (ah->unk_pos + UHO_NAME), + dotstar); +#endif /* set the unknown header name part length */ diff --git a/lib/roles/ws/server-ws.c b/lib/roles/ws/server-ws.c index 91d8e9fbf..db1a0159b 100644 --- a/lib/roles/ws/server-ws.c +++ b/lib/roles/ws/server-ws.c @@ -368,7 +368,7 @@ lws_process_ws_upgrade2(struct lws *wsi) #if defined(LWS_WITH_ACCESS_LOG) { - char *uptr = "unknown method", combo[128]; + char *uptr = "unknown method", combo[128], dotstar[64]; int l = 14, meth = lws_http_get_uri_and_method(wsi, &uptr, &l); if (wsi->h2_stream_carries_ws) @@ -376,7 +376,8 @@ lws_process_ws_upgrade2(struct lws *wsi) wsi->http.access_log.response = 101; - l = lws_snprintf(combo, sizeof(combo), "%.*s (%s)", l, uptr, + lws_strnncpy(dotstar, uptr, l, sizeof(dotstar)); + l = lws_snprintf(combo, sizeof(combo), "%s (%s)", dotstar, wsi->protocol->name); lws_prepare_access_log_info(wsi, combo, l, meth); diff --git a/minimal-examples/abstract/protocols/smtp-client/main.c b/minimal-examples/abstract/protocols/smtp-client/main.c index e0aca4f30..d21c4eac7 100644 --- a/minimal-examples/abstract/protocols/smtp-client/main.c +++ b/minimal-examples/abstract/protocols/smtp-client/main.c @@ -24,9 +24,11 @@ static int done_cb(struct lws_smtp_email *email, void *buf, size_t len) { /* you could examine email->data here */ - if (buf) - lwsl_notice("%s: %.*s\n", __func__, (int)len, (const char *)buf); - else + if (buf) { + char dotstar[96]; + lws_strnncpy(dotstar, (const char *)buf, len, sizeof(dotstar)); + lwsl_notice("%s: %s\n", __func__, dotstar); + } else lwsl_notice("%s:\n", __func__); /* destroy any allocations in email */ 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 7ecd4d585..4fb23dc42 100644 --- a/minimal-examples/api-tests/api-test-lws_tokenize/main.c +++ b/minimal-examples/api-tests/api-test-lws_tokenize/main.c @@ -290,6 +290,7 @@ int main(int argc, const char **argv) /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */ /* | LLL_DEBUG */; int fail = 0, ok = 0, flags = 0; + char dotstar[512]; if ((p = lws_cmdline_option(argc, argv, "-d"))) logs = atoi(p); @@ -300,6 +301,21 @@ int main(int argc, const char **argv) if ((p = lws_cmdline_option(argc, argv, "-f"))) flags = atoi(p); + /* sanity check lws_strnncpy() */ + + lws_strnncpy(dotstar, "12345678", 4, sizeof(dotstar)); + if (strcmp(dotstar, "1234")) { + lwsl_err("%s: lws_strnncpy check failed\n", __func__); + + return 1; + } + lws_strnncpy(dotstar, "12345678", 8, 6); + if (strcmp(dotstar, "12345")) { + lwsl_err("%s: lws_strnncpy check failed\n", __func__); + + return 1; + } + p = lws_cmdline_option(argc, argv, "-s"); for (n = 0; n < (int)LWS_ARRAY_SIZE(tests); n++) { @@ -314,9 +330,10 @@ int main(int argc, const char **argv) do { e = lws_tokenize(&ts); - lwsl_info("{ %s, \"%.*s\", %d }\n", - element_names[e + LWS_TOKZE_ERRS], - (int)ts.token_len, ts.token, + lws_strnncpy(dotstar, ts.token, ts.token_len, + sizeof(dotstar)); + lwsl_info("{ %s, \"%s\", %d }\n", + element_names[e + LWS_TOKZE_ERRS], dotstar, (int)ts.token_len); if (m == (int)tests[n].count) { @@ -336,8 +353,10 @@ int main(int argc, const char **argv) if (e > 0 && (ts.token_len != exp->len || memcmp(exp->value, ts.token, exp->len))) { - lwsl_notice("fail token mismatch %d %d %.*s\n", - ts.token_len, exp->len, ts.token_len, ts.token); + lws_strnncpy(dotstar, ts.token, ts.token_len, + sizeof(dotstar)); + lwsl_notice("fail token mismatch %d %d %s\n", + ts.token_len, exp->len, dotstar); fail++; break; } @@ -399,10 +418,12 @@ int main(int argc, const char **argv) do { e = lws_tokenize(&ts); - printf("\t\t{ %s, \"%.*s\", %d },\n", + lws_strnncpy(dotstar, ts.token, ts.token_len, + sizeof(dotstar)); + + printf("\t\t{ %s, \"%s\", %d },\n", element_names[e + LWS_TOKZE_ERRS], - (int)ts.token_len, - ts.token, (int)ts.token_len); + dotstar, (int)ts.token_len); } while (e > 0); diff --git a/minimal-examples/http-client/minimal-http-client/minimal-http-client.c b/minimal-examples/http-client/minimal-http-client/minimal-http-client.c index 1fa766da6..a49240fff 100644 --- a/minimal-examples/http-client/minimal-http-client/minimal-http-client.c +++ b/minimal-examples/http-client/minimal-http-client/minimal-http-client.c @@ -62,9 +62,13 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: lwsl_user("RECEIVE_CLIENT_HTTP_READ: read %d\n", (int)len); #if defined(LWS_WITH_HTTP2) - if (long_poll) - lwsl_notice("long poll rx: '%.*s'\n", - (int)len, (const char *)in); + if (long_poll) { + char dotstar[128]; + lws_strnncpy(dotstar, (const char *)in, len, + sizeof(dotstar)); + lwsl_notice("long poll rx: %d '%s'\n", (int)len, + dotstar); + } #endif #if 0 /* enable to dump the html */ {