diff --git a/ccan/README b/ccan/README index 4fab455bc..ad5b8d61f 100644 --- a/ccan/README +++ b/ccan/README @@ -1,3 +1,3 @@ CCAN imported from http://ccodearchive.net. -CCAN version: init-2545-g7b11e744 +CCAN version: init-2548-gab87e56b diff --git a/ccan/ccan/rune/coding.c b/ccan/ccan/rune/coding.c index b9255b0b5..f4d110283 100644 --- a/ccan/ccan/rune/coding.c +++ b/ccan/ccan/rune/coding.c @@ -98,7 +98,7 @@ static void rune_altern_encode(const struct rune_altern *altern, break; esc[1] = p[len]; cb(esc, 2, arg); - p++; + p += len + 1; } } @@ -184,7 +184,7 @@ static bool pull_char(const char **data, size_t *len, char *c) return true; } -static bool is_valid_cond(enum rune_condition cond) +bool rune_condition_is_valid(enum rune_condition cond) { switch (cond) { case RUNE_COND_IF_MISSING: @@ -203,31 +203,35 @@ static bool is_valid_cond(enum rune_condition cond) return false; } +size_t rune_altern_fieldname_len(const char *alternstr, size_t alternstrlen) +{ + for (size_t i = 0; i < alternstrlen; i++) { + if (cispunct(alternstr[i])) + return i; + } + return alternstrlen; +} + /* Sets *more on success: true if another altern follows */ static struct rune_altern *rune_altern_decode(const tal_t *ctx, const char **data, size_t *len, bool *more) { struct rune_altern *alt = tal(ctx, struct rune_altern); - const char *strstart = *data; char *value; - size_t strlen = 0; + size_t strlen; char c; - /* Swallow field up to conditional */ - for (;;) { - if (!pull_char(data, len, &c)) - return tal_free(alt); - if (cispunct(c)) - break; - strlen++; - } + /* Swallow field up to possible conditional */ + strlen = rune_altern_fieldname_len(*data, *len); + alt->fieldname = tal_strndup(alt, *data, strlen); + *data += strlen; + *len -= strlen; - alt->fieldname = tal_strndup(alt, strstart, strlen); - if (!is_valid_cond(c)) { - pull_invalid(data, len); + /* Grab conditional */ + if (!pull_char(data, len, &c) || !rune_condition_is_valid(c)) return tal_free(alt); - } + alt->condition = c; /* Assign worst case. */ diff --git a/ccan/ccan/rune/rune.h b/ccan/ccan/rune/rune.h index b67b78281..c373269aa 100644 --- a/ccan/ccan/rune/rune.h +++ b/ccan/ccan/rune/rune.h @@ -376,4 +376,25 @@ char *rune_to_string(const tal_t *ctx, const struct rune *rune); struct rune_restr *rune_restr_from_string(const tal_t *ctx, const char *str, size_t len); + +/** + * rune_condition_is_valid: is this a valid condition? + * @cond: potential condition character. + * + * Returns true if it's one of enum rune_condition. + */ +bool rune_condition_is_valid(enum rune_condition cond); + +/** + * rune_altern_fieldname_len: how much of this string is condition? + * @alternstr: potential alternative string + * @alternstrlen: length + * + * This helps parsing your own runes. + * + * Returns the first possible condition (check with rune_condition_is_valid) + * or alternstrlen if none found. + */ +size_t rune_altern_fieldname_len(const char *alternstr, size_t alternstrlen); + #endif /* CCAN_RUNE_RUNE_H */ diff --git a/ccan/ccan/rune/test/run-altern-escape.c b/ccan/ccan/rune/test/run-altern-escape.c new file mode 100644 index 000000000..550cafae4 --- /dev/null +++ b/ccan/ccan/rune/test/run-altern-escape.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include + +int main(void) +{ + static const u8 secret_zero[16]; + struct rune *rune; + struct rune_restr *restr; + const tal_t *ctx = tal(NULL, char); + + plan_tests(9); + restr = rune_restr_from_string(ctx, "desc=@tipjar\\|jb55@sendsats.lol", + strlen("desc=@tipjar\\|jb55@sendsats.lol")); + ok1(tal_count(restr->alterns) == 1); + ok1(restr->alterns[0]->condition == '='); + ok1(streq(restr->alterns[0]->fieldname, "desc")); + ok1(streq(restr->alterns[0]->value, "@tipjar|jb55@sendsats.lol")); + + rune = rune_new(ctx, secret_zero, sizeof(secret_zero), NULL); + rune_add_restr(rune, take(restr)); + + /* Converting via base64 should not change it! */ + rune = rune_from_base64(ctx, rune_to_base64(ctx, rune)); + ok1(tal_count(rune->restrs) == 1); + restr = rune->restrs[0]; + ok1(tal_count(restr->alterns) == 1); + ok1(restr->alterns[0]->condition == '='); + ok1(streq(restr->alterns[0]->fieldname, "desc")); + ok1(streq(restr->alterns[0]->value, "@tipjar|jb55@sendsats.lol")); + + tal_free(ctx); + /* This exits depending on whether all tests passed */ + return exit_status(); +} diff --git a/ccan/ccan/rune/test/run.c b/ccan/ccan/rune/test/run.c index 86737b86b..e53265528 100644 --- a/ccan/ccan/rune/test/run.c +++ b/ccan/ccan/rune/test/run.c @@ -83,12 +83,12 @@ int main(void) ok1(rune_is_derived_anyversion(rune1, rune2) == NULL); restr = rune_restr_new(NULL); - for (size_t i = 4; parts[i]; i+=3) { + for (size_t j = 4; parts[j]; j+=3) { struct rune_altern *alt; alt = rune_altern_new(NULL, - parts[i], - parts[i+1][0], - parts[i+2]); + parts[j], + parts[j+1][0], + parts[j+2]); rune_restr_add_altern(restr, take(alt)); } rune_add_restr(rune1, take(restr)); diff --git a/ccan/ccan/tal/tal.c b/ccan/ccan/tal/tal.c index 69270c6ff..2d05dd93f 100644 --- a/ccan/ccan/tal/tal.c +++ b/ccan/ccan/tal/tal.c @@ -777,7 +777,7 @@ void *tal_dup_(const tal_t *ctx, const void *p, size_t size, (void)taken(p); return NULL; } - + if (!adjust_size(&nbytes, n)) { if (taken(p)) tal_free(p);