lib: fix static analysis issues, use regfree()

* Fix potential NULL dereference
* Fix use of uninitialized value
* Fix leaking memory by not freeing regex_t
* Fix extra \n when using empty regex filter
* Clean up still-reachable hook memory
* Handle nonexistent pager

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
Quentin Young 2018-05-29 17:13:51 +00:00
parent 62bece4449
commit 5d806ec6e0
4 changed files with 39 additions and 6 deletions

View File

@ -1198,16 +1198,22 @@ static int handle_pipe_action(struct vty *vty, const char *cmd_in,
if (strmatch(token, "include")) { if (strmatch(token, "include")) {
/* the remaining text should be a regexp */ /* the remaining text should be a regexp */
char *regexp = working; char *regexp = working;
if (!regexp) {
vty_out(vty, "%% Need a regexp to filter with\n");
goto fail;
}
bool succ = vty_set_include(vty, regexp); bool succ = vty_set_include(vty, regexp);
if (!succ) { if (!succ) {
vty_out(vty, "%% Bad regexp '%s'", regexp); vty_out(vty, "%% Bad regexp '%s'\n", regexp);
goto fail; goto fail;
} }
*cmd_out = XSTRDUP(MTYPE_TMP, cmd_in); *cmd_out = XSTRDUP(MTYPE_TMP, cmd_in);
*(strstr(*cmd_out, "|")) = '\0'; *(strstr(*cmd_out, "|")) = '\0';
} else { } else {
vty_out(vty, "%% Unknown action '%s'", token); vty_out(vty, "%% Unknown action '%s'\n", token);
goto fail; goto fail;
} }
@ -2892,6 +2898,9 @@ void cmd_terminate()
{ {
struct cmd_node *cmd_node; struct cmd_node *cmd_node;
hook_unregister(cmd_execute, handle_pipe_action);
hook_unregister(cmd_execute_done, handle_pipe_action_done);
if (cmdvec) { if (cmdvec) {
for (unsigned int i = 0; i < vector_active(cmdvec); i++) for (unsigned int i = 0; i < vector_active(cmdvec); i++)
if ((cmd_node = vector_slot(cmdvec, i)) != NULL) { if ((cmd_node = vector_slot(cmdvec, i)) != NULL) {

View File

@ -58,6 +58,9 @@ vector frrstr_split_vec(const char *string, const char *delimiter)
char **result; char **result;
int argc; int argc;
if (!string)
return NULL;
frrstr_split(string, delimiter, &result, &argc); frrstr_split(string, delimiter, &result, &argc);
vector v = array_to_vector((void **)result, argc); vector v = array_to_vector((void **)result, argc);
@ -89,7 +92,7 @@ char *frrstr_join(const char **parts, int argc, const char *join)
memcpy(p, parts[i], arglen); memcpy(p, parts[i], arglen);
p += arglen; p += arglen;
if (i + 1 != argc) { if (i + 1 != argc && join) {
memcpy(p, join, joinlen); memcpy(p, join, joinlen);
p += joinlen; p += joinlen;
} }

View File

@ -119,8 +119,8 @@ bool vty_set_include(struct vty *vty, const char *regexp)
bool ret = true; bool ret = true;
char errbuf[256]; char errbuf[256];
if (!regexp) { if (!regexp && vty->filter) {
memset(&vty->include, 0x00, sizeof(vty->include)); regfree(&vty->include);
vty->filter = false; vty->filter = false;
return true; return true;
} }
@ -188,8 +188,26 @@ int vty_out(struct vty *vty, const char *format, ...)
vector lines = frrstr_split_vec(buf, "\n"); vector lines = frrstr_split_vec(buf, "\n");
frrstr_filter_vec(lines, &vty->include); frrstr_filter_vec(lines, &vty->include);
if (buf[strlen(buf) - 1] == '\n' && vector_active(lines) > 0)
/*
* Consider the string "foo\n". If the regex is an empty string
* and the line ended with a newline, then the vector will look
* like:
*
* [0]: 'foo'
* [1]: ''
*
* If the regex isn't empty, the vector will look like:
*
* [0]: 'foo'
*
* In this case we'd like to preserve the newline, so we add
* the empty string [1] as in the first example.
*/
if (buf[strlen(buf) - 1] == '\n' && vector_active(lines) > 0
&& strlen(vector_slot(lines, vector_active(lines) - 1)))
vector_set(lines, XSTRDUP(MTYPE_TMP, "")); vector_set(lines, XSTRDUP(MTYPE_TMP, ""));
filtered = frrstr_join_vec(lines, "\n"); filtered = frrstr_join_vec(lines, "\n");
frrstr_strvec_free(lines); frrstr_strvec_free(lines);
} else { } else {

View File

@ -70,6 +70,9 @@ static FILE *vty_open_pager(struct vty *vty)
if (vty->is_paged) if (vty->is_paged)
return vty->of; return vty->of;
if (!vtysh_pager_name)
return NULL;
vty->of_saved = vty->of; vty->of_saved = vty->of;
vty->of = popen(vtysh_pager_name, "w"); vty->of = popen(vtysh_pager_name, "w");
if (vty->of == NULL) { if (vty->of == NULL) {