-
Notifications
You must be signed in to change notification settings - Fork 1k
lightningd: accept options array in plugin start #9391
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
daywalker90
wants to merge
1
commit into
ElementsProject:master
Choose a base branch
from
daywalker90:plugin-options-obj
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+228
−13
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| #include "config.h" | ||
| #include <ccan/json_escape/json_escape.h> | ||
| #include <ccan/tal/path/path.h> | ||
| #include <ccan/tal/str/str.h> | ||
| #include <common/json_command.h> | ||
|
|
@@ -86,6 +87,59 @@ plugin_dynamic_start(struct plugin_command *pcmd, const char *plugin_path, | |
| return command_still_pending(pcmd->cmd); | ||
| } | ||
|
|
||
| /* Returns true if params is an object with keys other than the fixed | ||
| * subcommand/plugin/options. */ | ||
| static bool plugin_has_extra_params(const char *buffer, | ||
| const jsmntok_t *params) | ||
| { | ||
| size_t i; | ||
| const jsmntok_t *t; | ||
|
|
||
| json_for_each_obj(i, t, params) | ||
| if (!json_tok_streq(buffer, t, "subcommand") | ||
| && !json_tok_streq(buffer, t, "plugin") | ||
| && !json_tok_streq(buffer, t, "options")) | ||
| return true; | ||
| return false; | ||
| } | ||
|
|
||
| /* Build an object of name/value pairs from an "options" array of | ||
| * "keyword=value" strings, suitable for plugin_add_params(). An element | ||
| * without an '=' is treated as a boolean flag. */ | ||
| static jsmntok_t *plugin_start_params(const tal_t *ctx, const char *buffer, | ||
| const jsmntok_t *options, char **parambuf) | ||
| { | ||
| size_t i; | ||
| const jsmntok_t *t; | ||
| char *newbuf = tal_strdup(ctx, "{"); | ||
| bool first = true; | ||
|
|
||
| json_for_each_arr(i, t, options) { | ||
| const char *opt = json_strdup(tmpctx, buffer, t); | ||
| const char *eq = strchr(opt, '='); | ||
| struct json_escape *esc; | ||
|
|
||
| if (!first) | ||
| tal_append_fmt(&newbuf, ","); | ||
| first = false; | ||
| if (eq) { | ||
| esc = json_escape(tmpctx, | ||
| take(tal_strndup(tmpctx, opt, eq - opt))); | ||
| tal_append_fmt(&newbuf, "\"%s\":", esc->s); | ||
| esc = json_escape(tmpctx, eq + 1); | ||
| tal_append_fmt(&newbuf, "\"%s\"", esc->s); | ||
| } else { | ||
| /* Boolean flags are given without a value. */ | ||
| esc = json_escape(tmpctx, opt); | ||
| tal_append_fmt(&newbuf, "\"%s\":true", esc->s); | ||
| } | ||
| } | ||
|
|
||
| tal_append_fmt(&newbuf, "}"); | ||
| *parambuf = newbuf; | ||
| return json_parse_simple(ctx, newbuf, strlen(newbuf)); | ||
| } | ||
|
|
||
| /** | ||
| * Called when trying to start a plugin directory through RPC, it registers | ||
| * all contained plugins recursively and then starts them. | ||
|
|
@@ -235,23 +289,54 @@ static struct command_result *json_plugin_control(struct command *cmd, | |
| return plugin_dynamic_stop(cmd, plugin_name); | ||
| } else if (streq(subcmd, "start")) { | ||
| const char *plugin_path; | ||
| const jsmntok_t *options = NULL; | ||
| char *mod_buffer; | ||
| jsmntok_t *mod_params; | ||
|
|
||
| if (!param_check(cmd, buffer, params, | ||
| p_req("subcommand", param_ignore, cmd), | ||
| p_req("plugin", param_string, &plugin_path), | ||
| p_opt("options", param_array, &options), | ||
| p_opt_any(), | ||
| NULL)) | ||
| return command_param_failed(); | ||
|
|
||
| /* The "options" array is documented as containing keyword=value | ||
| * strings: reject anything else before we mangle it. */ | ||
| if (options) { | ||
| size_t i; | ||
| const jsmntok_t *t; | ||
|
|
||
| json_for_each_arr(i, t, options) | ||
| if (t->type != JSMN_STRING) | ||
| return command_fail(cmd, JSONRPC2_INVALID_PARAMS, | ||
| "options array entries must be strings"); | ||
| } | ||
|
|
||
| /* Manually parse any remaining options (only for objects, | ||
| * since plugin options must be explicitly named!). */ | ||
| if (params->type == JSMN_ARRAY) { | ||
| if (params->size != 2) | ||
| if (params->size > (options ? 3 : 2)) | ||
| return command_fail(cmd, JSONRPC2_INVALID_PARAMS, | ||
| "Extra parameters must be in object"); | ||
| mod_params = NULL; | ||
| if (options) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, per the schema, fixed. |
||
| mod_params = plugin_start_params(cmd, buffer, | ||
| options, &mod_buffer); | ||
| } else { | ||
| mod_buffer = NULL; | ||
| mod_params = NULL; | ||
| } | ||
| } else if (options) { | ||
| /* Either flattened keyword options or an explicit | ||
| * "options" array, never both. */ | ||
| if (plugin_has_extra_params(buffer, params)) | ||
| return command_fail(cmd, JSONRPC2_INVALID_PARAMS, | ||
| "Cannot mix 'options' array " | ||
| "with keyword options"); | ||
| mod_params = plugin_start_params(cmd, buffer, | ||
| options, &mod_buffer); | ||
| } else { | ||
| mod_buffer = NULL; | ||
| mod_params = json_tok_copy(cmd, params); | ||
|
|
||
| json_tok_remove(&mod_params, mod_params, | ||
|
|
@@ -271,7 +356,9 @@ static struct command_result *json_plugin_control(struct command *cmd, | |
| if (command_check_only(cmd)) | ||
| return command_check_done(cmd); | ||
|
|
||
| return plugin_dynamic_start(pcmd, plugin_path, buffer, mod_params); | ||
| return plugin_dynamic_start(pcmd, plugin_path, | ||
| mod_buffer ? mod_buffer : buffer, | ||
| mod_params); | ||
| } else if (streq(subcmd, "startdir")) { | ||
| const char *dir_path; | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!! As i understood when
plugin_start_params()builds a new json string (mod_buffer), the code always threadsmod_bufferthrough toplugin_dynamic_start()instead of the originalbuffer. Using the original buffer with fresh synthesized token offsets would have caused out-of-bounds reads