Browse Source

bolt11: undo json encoding for description bytes.

We don't handle \u, since we assume everyone sane is using UTF-8.  We'd
still have to reject '\u0000' and maybe other weird cases if we did.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
parent
commit
9f7d4312ff
  1. 44
      common/json_escaped.c
  2. 3
      common/json_escaped.h
  3. 2
      devtools/bolt11-cli.c
  4. 35
      lightningd/invoice.c

44
common/json_escaped.c

@ -84,3 +84,47 @@ struct json_escaped *json_escape(const tal_t *ctx, const char *str TAKES)
tal_free(str); tal_free(str);
return esc; return esc;
} }
/* By policy, we don't handle \u. Use UTF-8. */
const char *json_escaped_unescape(const tal_t *ctx,
const struct json_escaped *esc)
{
char *unesc = tal_arr(ctx, char, strlen(esc->s) + 1);
size_t i, n;
for (i = n = 0; esc->s[i]; i++, n++) {
if (esc->s[i] != '\\') {
unesc[n] = esc->s[i];
continue;
}
i++;
switch (esc->s[i]) {
case 'n':
unesc[n] = '\n';
break;
case 'b':
unesc[n] = '\b';
break;
case 'f':
unesc[n] = '\f';
break;
case 't':
unesc[n] = '\t';
break;
case 'r':
unesc[n] = '\r';
break;
case '/':
case '\\':
case '"':
unesc[n] = esc->s[i];
break;
default:
return tal_free(unesc);
}
}
unesc[n] = '\0';
return unesc;
}

3
common/json_escaped.h

@ -33,4 +33,7 @@ void json_add_escaped_string(struct json_result *result,
struct json_escaped *json_escaped_string_(const tal_t *ctx, struct json_escaped *json_escaped_string_(const tal_t *ctx,
const void *bytes, size_t len); const void *bytes, size_t len);
/* Be very careful here! Can fail! Doesn't handle \u: use UTF-8 please. */
const char *json_escaped_unescape(const tal_t *ctx,
const struct json_escaped *esc);
#endif /* LIGHTNING_COMMON_JSON_ESCAPED_H */ #endif /* LIGHTNING_COMMON_JSON_ESCAPED_H */

2
devtools/bolt11-cli.c

@ -105,7 +105,7 @@ int main(int argc, char *argv[])
if (b11->msatoshi) if (b11->msatoshi)
printf("msatoshi: %"PRIu64"\n", *b11->msatoshi); printf("msatoshi: %"PRIu64"\n", *b11->msatoshi);
if (b11->description) if (b11->description)
printf("description: %s\n", b11->description); printf("description: '%s'\n", b11->description);
if (b11->description_hash) if (b11->description_hash)
printf("description_hash: %s\n", printf("description_hash: %s\n",
tal_hexstr(ctx, b11->description_hash, tal_hexstr(ctx, b11->description_hash,

35
lightningd/invoice.c

@ -109,9 +109,9 @@ static void json_invoice(struct command *cmd,
{ {
struct invoice invoice; struct invoice invoice;
struct invoice_details details; struct invoice_details details;
jsmntok_t *msatoshi, *label, *desc, *exp, *fallback; jsmntok_t *msatoshi, *label, *desctok, *exp, *fallback;
u64 *msatoshi_val; u64 *msatoshi_val;
const struct json_escaped *label_val; const struct json_escaped *label_val, *desc;
const char *desc_val; const char *desc_val;
enum address_parse_result fallback_parse; enum address_parse_result fallback_parse;
struct json_result *response = new_json_result(cmd); struct json_result *response = new_json_result(cmd);
@ -125,7 +125,7 @@ static void json_invoice(struct command *cmd,
if (!json_get_params(cmd, buffer, params, if (!json_get_params(cmd, buffer, params,
"msatoshi", &msatoshi, "msatoshi", &msatoshi,
"label", &label, "label", &label,
"description", &desc, "description", &desctok,
"?expiry", &exp, "?expiry", &exp,
"?fallback", &fallback, "?fallback", &fallback,
NULL)) { NULL)) {
@ -163,18 +163,31 @@ static void json_invoice(struct command *cmd,
INVOICE_MAX_LABEL_LEN); INVOICE_MAX_LABEL_LEN);
return; return;
} }
desc = json_tok_escaped_string(cmd, buffer, desctok);
if (!desc) {
command_fail(cmd, "description '%.*s' not a string",
desctok->end - desctok->start,
buffer + desctok->start);
return;
}
desc_val = json_escaped_unescape(cmd, desc);
if (!desc_val) {
command_fail(cmd, "description '%s' is invalid"
" (note: we don't allow \\u)",
desc->s);
return;
}
/* description */ /* description */
if (desc->end - desc->start >= BOLT11_FIELD_BYTE_LIMIT) { if (strlen(desc_val) >= BOLT11_FIELD_BYTE_LIMIT) {
command_fail(cmd, command_fail(cmd,
"Descriptions greater than %d bytes " "Descriptions greater than %d bytes "
"not yet supported " "not yet supported "
"(description length %d)", "(description length %zu)",
BOLT11_FIELD_BYTE_LIMIT, BOLT11_FIELD_BYTE_LIMIT,
desc->end - desc->start); strlen(desc_val));
return; return;
} }
desc_val = tal_strndup(cmd, buffer + desc->start,
desc->end - desc->start);
/* expiry */ /* expiry */
if (exp && !json_tok_u64(buffer, exp, &expiry)) { if (exp && !json_tok_u64(buffer, exp, &expiry)) {
command_fail(cmd, "Expiry '%.*s' invalid seconds", command_fail(cmd, "Expiry '%.*s' invalid seconds",
@ -629,8 +642,10 @@ static void json_decodepay(struct command *cmd,
json_add_pubkey(response, "payee", &b11->receiver_id); json_add_pubkey(response, "payee", &b11->receiver_id);
if (b11->msatoshi) if (b11->msatoshi)
json_add_u64(response, "msatoshi", *b11->msatoshi); json_add_u64(response, "msatoshi", *b11->msatoshi);
if (b11->description) if (b11->description) {
json_add_string(response, "description", b11->description); struct json_escaped *esc = json_escape(NULL, b11->description);
json_add_escaped_string(response, "description", take(esc));
}
if (b11->description_hash) if (b11->description_hash)
json_add_hex(response, "description_hash", json_add_hex(response, "description_hash",
b11->description_hash, b11->description_hash,

Loading…
Cancel
Save