Browse Source

lightning-cli: use tal_arr for toks again.

We moved to raw malloc to detect OOM, but json_tok_remove wants a tal
array.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
pull/2938/head
Rusty Russell 6 years ago
parent
commit
7e97119117
  1. 46
      cli/lightning-cli.c
  2. 22
      cli/test/run-large-input.c

46
cli/lightning-cli.c

@ -369,7 +369,7 @@ static size_t read_nofail(int fd, void *buf, size_t len)
/* We rely on the fact that lightningd terminates all JSON RPC responses with /* We rely on the fact that lightningd terminates all JSON RPC responses with
* "\n\n", so we can stream even if we can't parse. */ * "\n\n", so we can stream even if we can't parse. */
static void oom_dump(int fd, char *resp, size_t resp_len, size_t off) static void oom_dump(int fd, char *resp, size_t off)
{ {
warnx("Out of memory: sending raw output"); warnx("Out of memory: sending raw output");
@ -378,13 +378,21 @@ static void oom_dump(int fd, char *resp, size_t resp_len, size_t off)
/* Keep last char, to avoid splitting \n\n */ /* Keep last char, to avoid splitting \n\n */
write_all(STDOUT_FILENO, resp, off-1); write_all(STDOUT_FILENO, resp, off-1);
resp[0] = resp[off-1]; resp[0] = resp[off-1];
off = 1 + read_nofail(fd, resp + 1, resp_len - 1); off = 1 + read_nofail(fd, resp + 1, tal_bytelen(resp) - 1);
} while (resp[off-2] != '\n' || resp[off-1] != '\n'); } while (resp[off-2] != '\n' || resp[off-1] != '\n');
write_all(STDOUT_FILENO, resp, off-1); write_all(STDOUT_FILENO, resp, off-1);
/* We assume giant answer means "success" */ /* We assume giant answer means "success" */
exit(0); exit(0);
} }
/* We want to return failure if tal_resize fails */
static void tal_error(const char *msg)
{
if (streq(msg, "Reallocation failure"))
return;
abort();
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
setup_locale(); setup_locale();
@ -404,11 +412,11 @@ int main(int argc, char *argv[])
enum format format = DEFAULT_FORMAT; enum format format = DEFAULT_FORMAT;
enum input input = DEFAULT_INPUT; enum input input = DEFAULT_INPUT;
char *command = NULL; char *command = NULL;
size_t resp_len, num_toks;
err_set_progname(argv[0]); err_set_progname(argv[0]);
jsmn_init(&parser); jsmn_init(&parser);
tal_set_backend(NULL, NULL, NULL, tal_error);
opt_set_alloc(opt_allocfn, tal_reallocfn, tal_freefn); opt_set_alloc(opt_allocfn, tal_reallocfn, tal_freefn);
opt_register_arg("--lightning-dir=<dir>", opt_set_talstr, opt_show_charp, opt_register_arg("--lightning-dir=<dir>", opt_set_talstr, opt_show_charp,
@ -522,17 +530,15 @@ int main(int argc, char *argv[])
err(ERROR_TALKING_TO_LIGHTNINGD, "Writing command"); err(ERROR_TALKING_TO_LIGHTNINGD, "Writing command");
/* Start with 1000 characters, 100 tokens. */ /* Start with 1000 characters, 100 tokens. */
resp_len = 1000; resp = tal_arr(ctx, char, 1000);
resp = malloc(resp_len); toks = tal_arr(ctx, jsmntok_t, 100);
num_toks = 100;
toks = malloc(sizeof(jsmntok_t) * num_toks);
off = 0; off = 0;
parserr = 0; parserr = 0;
while (parserr <= 0) { while (parserr <= 0) {
/* Read more if parser says, or we have 0 tokens. */ /* Read more if parser says, or we have 0 tokens. */
if (parserr == 0 || parserr == JSMN_ERROR_PART) { if (parserr == 0 || parserr == JSMN_ERROR_PART) {
ssize_t i = read(fd, resp + off, resp_len - 1 - off); ssize_t i = read(fd, resp + off, tal_bytelen(resp) - 1 - off);
if (i == 0) if (i == 0)
errx(ERROR_TALKING_TO_LIGHTNINGD, errx(ERROR_TALKING_TO_LIGHTNINGD,
"reading response: socket closed"); "reading response: socket closed");
@ -545,7 +551,7 @@ int main(int argc, char *argv[])
} }
/* (Continue) parsing */ /* (Continue) parsing */
parserr = jsmn_parse(&parser, resp, off, toks, num_toks); parserr = jsmn_parse(&parser, resp, off, toks, tal_count(toks));
switch (parserr) { switch (parserr) {
case JSMN_ERROR_INVAL: case JSMN_ERROR_INVAL:
@ -553,23 +559,15 @@ int main(int argc, char *argv[])
"Malformed response '%s'", resp); "Malformed response '%s'", resp);
case JSMN_ERROR_NOMEM: { case JSMN_ERROR_NOMEM: {
/* Need more tokens, double it */ /* Need more tokens, double it */
jsmntok_t *newtoks = realloc(toks, if (!tal_resize(&toks, tal_count(toks) * 2))
sizeof(jsmntok_t) oom_dump(fd, resp, off);
* num_toks * 2);
if (!newtoks)
oom_dump(fd, resp, resp_len, off);
toks = newtoks;
num_toks *= 2;
break; break;
} }
case JSMN_ERROR_PART: case JSMN_ERROR_PART:
/* Need more data: make room if necessary */ /* Need more data: make room if necessary */
if (off == resp_len - 1) { if (off == tal_bytelen(resp) - 1) {
char *newresp = realloc(resp, resp_len * 2); if (!tal_resize(&resp, tal_count(resp) * 2))
if (!newresp) oom_dump(fd, resp, off);
oom_dump(fd, resp, resp_len, off);
resp = newresp;
resp_len *= 2;
} }
break; break;
} }
@ -612,8 +610,6 @@ int main(int argc, char *argv[])
tal_free(rpc_filename); tal_free(rpc_filename);
tal_free(ctx); tal_free(ctx);
opt_free_table(); opt_free_table();
free(resp);
free(toks);
return 0; return 0;
} }
@ -628,7 +624,5 @@ int main(int argc, char *argv[])
tal_free(rpc_filename); tal_free(rpc_filename);
tal_free(ctx); tal_free(ctx);
opt_free_table(); opt_free_table();
free(resp);
free(toks);
return 1; return 1;
} }

22
cli/test/run-large-input.c

@ -14,9 +14,6 @@ int test_connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen); socklen_t addrlen);
int test_getpid(void); int test_getpid(void);
int test_printf(const char *format, ...); int test_printf(const char *format, ...);
void *test_malloc(size_t n);
void *test_realloc(void *p, size_t n);
void test_free(void *p);
#define main test_main #define main test_main
#define read test_read #define read test_read
@ -24,9 +21,6 @@ void test_free(void *p);
#define connect test_connect #define connect test_connect
#define getpid test_getpid #define getpid test_getpid
#define printf test_printf #define printf test_printf
#define malloc test_malloc
#define realloc test_realloc
#define free test_free
#include "../lightning-cli.c" #include "../lightning-cli.c"
#undef main #undef main
@ -62,22 +56,6 @@ int test_printf(const char *fmt UNUSED, ...)
static char *response; static char *response;
static size_t response_off, max_read_return; static size_t response_off, max_read_return;
void *test_malloc(size_t n)
{
return tal_arr(response, u8, n);
}
void *test_realloc(void *p, size_t n)
{
tal_resize(&p, n);
return p;
}
void test_free(void *p)
{
tal_free(p);
}
ssize_t test_read(int fd UNUSED, void *buf, size_t len) ssize_t test_read(int fd UNUSED, void *buf, size_t len)
{ {
if (len > max_read_return) if (len > max_read_return)

Loading…
Cancel
Save