diff --git a/ccan/README b/ccan/README index 926a82363872..5aee71080460 100644 --- a/ccan/README +++ b/ccan/README @@ -1,3 +1,3 @@ CCAN imported from http://ccodearchive.net. -CCAN version: init-2593-gca094039 +CCAN version: init-2595-ge43c61c4 diff --git a/ccan/ccan/json_escape/json_escape.c b/ccan/ccan/json_escape/json_escape.c index daa14abe8c89..4bbb0032d1b5 100644 --- a/ccan/ccan/json_escape/json_escape.c +++ b/ccan/ccan/json_escape/json_escape.c @@ -1,6 +1,7 @@ /* MIT (BSD) license - see LICENSE file for details */ #include #include +#include struct json_escape *json_escape_string_(const tal_t *ctx, const void *bytes, size_t len) @@ -137,19 +138,24 @@ struct json_escape *json_escape_len(const tal_t *ctx, const char *str TAKES, } /* By policy, we don't handle \u. Use UTF-8. */ -const char *json_escape_unescape(const tal_t *ctx, const struct json_escape *esc) +static const char *unescape(const tal_t *ctx, const char *esc TAKES, size_t len) { - char *unesc = tal_arr(ctx, char, strlen(esc->s) + 1); + /* Fast path: can steal, and nothing to unescape. */ + if (is_taken(esc) && !memchr(esc, '\\', len)) + return tal_strndup(ctx, esc, len); + + char *unesc = tal_arr(ctx, char, len + 1); size_t i, n; - for (i = n = 0; esc->s[i]; i++, n++) { - if (esc->s[i] != '\\') { - unesc[n] = esc->s[i]; + for (i = n = 0; i < len; i++, n++) { + if (esc[i] != '\\') { + unesc[n] = esc[i]; continue; } - i++; - switch (esc->s[i]) { + if (++i == len) + goto error; + switch (esc[i]) { case 'n': unesc[n] = '\n'; break; @@ -168,13 +174,31 @@ const char *json_escape_unescape(const tal_t *ctx, const struct json_escape *esc case '/': case '\\': case '"': - unesc[n] = esc->s[i]; + unesc[n] = esc[i]; break; default: + error: + if (taken(esc)) + tal_free(esc); return tal_free(unesc); } } unesc[n] = '\0'; + if (!tal_resize(&unesc, n + 1)) + goto error; + if (taken(esc)) + tal_free(esc); return unesc; } + +const char *json_escape_unescape(const tal_t *ctx, const struct json_escape *esc) +{ + return unescape(ctx, esc->s, strlen(esc->s)); +} + +const char *json_escape_unescape_len(const tal_t *ctx, + const char *esc TAKES, size_t len) +{ + return unescape(ctx, esc, len); +} diff --git a/ccan/ccan/json_escape/json_escape.h b/ccan/ccan/json_escape/json_escape.h index 5b33432f8fce..88d1eefc1a64 100644 --- a/ccan/ccan/json_escape/json_escape.h +++ b/ccan/ccan/json_escape/json_escape.h @@ -41,4 +41,8 @@ struct json_escape *json_escape_string_(const tal_t *ctx, /* Be very careful here! Can fail! Doesn't handle \u: use UTF-8 please. */ const char *json_escape_unescape(const tal_t *ctx, const struct json_escape *esc); + +/* Be very careful here! Can fail! Doesn't handle \u: use UTF-8 please. */ +const char *json_escape_unescape_len(const tal_t *ctx, + const char *esc TAKES, size_t len); #endif /* CCAN_JSON_ESCAPE_H */ diff --git a/ccan/tools/configurator/configurator.1 b/ccan/tools/configurator/configurator.1 index aaa92c527f9e..2fe7d5a79cbb 100644 --- a/ccan/tools/configurator/configurator.1 +++ b/ccan/tools/configurator/configurator.1 @@ -208,7 +208,7 @@ It will exit with non\-zero status if it has a problem\&. \fB1\fR means bad comm Rusty Russell wrote \fBconfigurator\fR\&. .SH "RESOURCES" .sp -Main web site: http://ccodearchive\&.net/ +Main web site: https://github\&.com/rustyrussell/ccan .sp Wiki: https://github\&.com/rustyrussell/ccan/wiki/ .SH "COPYING" diff --git a/common/json_param.c b/common/json_param.c index b95952dd48be..1a761112cc38 100644 --- a/common/json_param.c +++ b/common/json_param.c @@ -444,11 +444,9 @@ struct command_result *param_escaped_string(struct command *cmd, const char **str) { if (tok->type == JSMN_STRING) { - struct json_escape *esc; /* jsmn always gives us ~ well-formed strings. */ - esc = json_escape_string_(cmd, buffer + tok->start, - tok->end - tok->start); - *str = json_escape_unescape(cmd, esc); + *str = json_escape_unescape_len(cmd, buffer + tok->start, + tok->end - tok->start); if (*str) return NULL; } diff --git a/common/test/run-bolt12_decode.c b/common/test/run-bolt12_decode.c index ae4cd8b42888..4702d23f251c 100644 --- a/common/test/run-bolt12_decode.c +++ b/common/test/run-bolt12_decode.c @@ -190,13 +190,11 @@ int main(int argc, char *argv[]) char *fail; const char *str; size_t dlen; - struct json_escape *esc; assert(json_to_bool(json, json_get_member(json, t, "valid"), &valid)); strtok = json_get_member(json, t, "string"); - esc = json_escape_string_(tmpctx, json + strtok->start, - strtok->end - strtok->start); - str = json_escape_unescape(tmpctx, esc); + str = json_escape_unescape_len(tmpctx, json + strtok->start, + strtok->end - strtok->start); actual = (string_to_data(tmpctx, str, strlen(str), "lno", &dlen, &fail) != NULL); assert(actual == valid); diff --git a/lightningd/jsonrpc.c b/lightningd/jsonrpc.c index 4b240808c83c..43286a289097 100644 --- a/lightningd/jsonrpc.c +++ b/lightningd/jsonrpc.c @@ -1393,20 +1393,14 @@ static void setup_command_usage(struct lightningd *ld, bool jsonrpc_command_add(struct jsonrpc *rpc, struct json_command *command, const char *usage TAKES) { - struct json_escape *esc; const char *unescaped; if (!command_add(rpc, command)) return false; - esc = json_escape_string_(tmpctx, usage, strlen(usage)); - unescaped = json_escape_unescape(command, esc); + unescaped = json_escape_unescape_len(command, usage, strlen(usage)); if (!unescaped) - unescaped = tal_strdup(command, usage); - else { - if (taken(usage)) - tal_free(usage); - } + return false; strmap_add(&rpc->usagemap, command->name, unescaped); tal_add_destructor2(command, destroy_json_command, rpc); diff --git a/lightningd/plugin.c b/lightningd/plugin.c index 2032640d281d..e1588f246fce 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -516,10 +516,9 @@ static const char *plugin_log_handle(struct plugin *plugin, /* Only bother unescaping and splitting if it has \ */ if (memchr(plugin->buffer + msgtok->start, '\\', msgtok->end - msgtok->start)) { - const char *log_escaped = plugin->buffer + msgtok->start; - const size_t log_escaped_len = msgtok->end - msgtok->start; - struct json_escape *esc = json_escape_string_(tmpctx, log_escaped, log_escaped_len); - const char *log_msg = json_escape_unescape(tmpctx, esc); + const char *log_msg = json_escape_unescape_len(tmpctx, + plugin->buffer + msgtok->start, + msgtok->end - msgtok->start); char **lines; /* Weird \ escapes aren't handled by json_escape_unescape. This is for you, clboss! */ diff --git a/lightningd/runes.c b/lightningd/runes.c index 9a4c6fdef859..77be7a30a0ad 100644 --- a/lightningd/runes.c +++ b/lightningd/runes.c @@ -484,10 +484,8 @@ static struct rune_altern *rune_altern_from_json(const tal_t *ctx, /* We still need to unescape here, for \\ -> \. JSON doesn't * allow unnecessary \ */ const char *unescape; - struct json_escape *e = json_escape_string_(tmpctx, - buffer + tok->start, - tok->end - tok->start); - unescape = json_escape_unescape(tmpctx, e); + unescape = json_escape_unescape_len(tmpctx, buffer + tok->start, + tok->end - tok->start); if (!unescape) return NULL;