From 93cb57b551c2d65b930c1151d0789fa23c0a398a Mon Sep 17 00:00:00 2001 From: Marie Helene Kvello-Aune Date: Sat, 2 Jan 2016 04:38:58 +0100 Subject: [PATCH 1/3] asprintf memory checking Check if asprintf calls failed due to not enough memory, and if so, print a message to stderr and abort() --- uclcmd.h | 2 +- uclcmd_common.c | 33 ++++++++++++++++++++++++--------- uclcmd_get.c | 43 +++++++++++++++++++++---------------------- uclcmd_output.c | 2 +- uclcmd_parse.c | 2 +- 5 files changed, 48 insertions(+), 34 deletions(-) diff --git a/uclcmd.h b/uclcmd.h index dc89e48..fd51a14 100755 --- a/uclcmd.h +++ b/uclcmd.h @@ -104,6 +104,6 @@ int get_cmd_type(const ucl_object_t *obj, char *nodepath, const char *command_str, char *remaining_commands, int recurse); int get_cmd_values(const ucl_object_t *obj, char *nodepath, const char *command_str, char *remaining_commands, int recurse); - +void asprintf_check_enomem(int retcode); #endif /* UCLCMD_H_ */ diff --git a/uclcmd_common.c b/uclcmd_common.c index 1cad602..2334602 100755 --- a/uclcmd_common.c +++ b/uclcmd_common.c @@ -26,8 +26,23 @@ * $FreeBSD$ */ +#include + #include "uclcmd.h" +void +asprintf_check_enomem(int retcode) { + /* + * This method is called with the return code of asprintf() as parameter. + * asprintf returns -1 when it cannot allocate memory. + * See printf(3) for details. + */ + if (retcode != -1) + return; + fprintf(stderr, "ENOMEM(%d): Could not allocate memory.\n", ENOMEM); + abort(); +} + char* expand_subkeys(const ucl_object_t *obj, char *nodepath) { @@ -170,31 +185,31 @@ type_as_string (const ucl_object_t *obj) if (obj == NULL) { return NULL; } else if (ucl_object_type(obj) == UCL_OBJECT) { - asprintf(&ret, "UCL_OBJECT"); + asprintf_check_enomem(asprintf(&ret, "UCL_OBJECT")); } else if (ucl_object_type(obj) == UCL_ARRAY) { - asprintf(&ret, "UCL_ARRAY"); + asprintf_check_enomem(asprintf(&ret, "UCL_ARRAY")); } else if (ucl_object_type(obj) == UCL_INT) { - asprintf(&ret, "UCL_INT"); + asprintf_check_enomem(asprintf(&ret, "UCL_INT")); } else if (ucl_object_type(obj) == UCL_FLOAT) { - asprintf(&ret, "UCL_FLOAT"); + asprintf_check_enomem(asprintf(&ret, "UCL_FLOAT")); } else if (ucl_object_type(obj) == UCL_STRING) { - asprintf(&ret, "UCL_STRING"); + asprintf_check_enomem(asprintf(&ret, "UCL_STRING")); } else if (ucl_object_type(obj) == UCL_BOOLEAN) { - asprintf(&ret, "UCL_BOOLEAN"); + asprintf_check_enomem(asprintf(&ret, "UCL_BOOLEAN")); } else if (ucl_object_type(obj) == UCL_TIME) { - asprintf(&ret, "UCL_TIME"); + asprintf_check_enomem(asprintf(&ret, "UCL_TIME")); } else if (ucl_object_type(obj) == UCL_USERDATA) { - asprintf(&ret, "UCL_USERDATA"); + asprintf_check_enomem(asprintf(&ret, "UCL_USERDATA")); } else if (ucl_object_type(obj) == UCL_NULL) { - asprintf(&ret, "UCL_NULL"); + asprintf_check_enomem(asprintf(&ret, "UCL_NULL")); } return ret; diff --git a/uclcmd_get.c b/uclcmd_get.c index cd6594a..ca2a10f 100755 --- a/uclcmd_get.c +++ b/uclcmd_get.c @@ -152,10 +152,9 @@ get_mode(char *requested_node) char *cmd = requested_node; char *node_name = strsep(&cmd, "|"); char *command_str = strsep(&cmd, "|"); - char *nodepath = NULL; + char *nodepath = ""; int command_count = 0, i; - asprintf(&nodepath, ""); found_object = root_obj; if (strlen(node_name) == 0) { @@ -180,7 +179,7 @@ get_mode(char *requested_node) } found_object = ucl_lookup_path_char(found_object, node_name, input_sepchar); free(nodepath); - asprintf(&nodepath, "%s", node_name); + asprintf_check_enomem(asprintf(&nodepath, "%s", node_name)); } while (command_str != NULL) { @@ -403,12 +402,12 @@ get_cmd_values(const ucl_object_t *obj, char *nodepath, continue; } if (ucl_object_type(obj) == UCL_ARRAY) { - asprintf(&newkey, "%c%i", output_sepchar, arrindex); + asprintf_check_enomem(asprintf(&newkey, "%c%i", output_sepchar, arrindex)); arrindex++; } else { newkey = __DECONST(char *, ucl_object_key(cur)); if (newkey != NULL) { - asprintf(&newkey, "%c%s", output_sepchar, ucl_object_key(cur)); + asprintf_check_enomem(asprintf(&newkey, "%c%s", output_sepchar, ucl_object_key(cur))); } } output_key(cur, nodepath, newkey); @@ -482,7 +481,7 @@ get_cmd_recurse(const ucl_object_t *obj, char *nodepath, ucl_object_t *arrlen = NULL; arrlen = ucl_object_fromint(obj->len); - asprintf(&tmpkeyname, "%c%s", output_sepchar, "_length"); + asprintf_check_enomem(asprintf(&tmpkeyname, "%c%s", output_sepchar, "_length")); output_chunk(arrlen, nodepath, tmpkeyname); free(tmpkeyname); } @@ -494,7 +493,7 @@ get_cmd_recurse(const ucl_object_t *obj, char *nodepath, keylist = expand_subkeys(obj, nodepath); if (keylist != NULL) { keystr = ucl_object_fromstring(keylist); - asprintf(&tmpkeyname, "%c%s", output_sepchar, "_keys"); + asprintf_check_enomem(asprintf(&tmpkeyname, "%c%s", output_sepchar, "_keys")); output_chunk(keystr, nodepath, tmpkeyname); free(tmpkeyname); free(keylist); @@ -505,24 +504,24 @@ get_cmd_recurse(const ucl_object_t *obj, char *nodepath, char *newkey = NULL; char *newnodepath = NULL; if (ucl_object_type(obj) == UCL_ARRAY) { - asprintf(&newkey, "%c%i", output_sepchar, arrindex); + asprintf_check_enomem(asprintf(&newkey, "%c%i", output_sepchar, arrindex)); arrindex++; } else if (strlen(nodepath) == 0) { asprintf(&newkey, "%s", ucl_object_key(cur)); } else { - asprintf(&newkey, "%c%s", output_sepchar, ucl_object_key(cur)); + asprintf_check_enomem(asprintf(&newkey, "%c%s", output_sepchar, ucl_object_key(cur))); } if (ucl_object_type(cur) == UCL_OBJECT || ucl_object_type(cur) == UCL_ARRAY) { it2 = NULL; while ((cur2 = ucl_iterate_object(cur, &it2, false))) { if (nodepath != NULL && strlen(nodepath) > 0) { - asprintf(&newnodepath, "%s%s", nodepath, newkey); + asprintf_check_enomem(asprintf(&newnodepath, "%s%s", nodepath, newkey)); } else { if (ucl_object_type(obj) == UCL_ARRAY) { - asprintf(&newnodepath, "%i", arrindex); + asprintf_check_enomem(asprintf(&newnodepath, "%i", arrindex)); } else { - asprintf(&newnodepath, "%s", ucl_object_key(cur2)); + asprintf_check_enomem(asprintf(&newnodepath, "%s", ucl_object_key(cur2))); } } recurse_level = process_get_command(cur2, @@ -560,10 +559,10 @@ get_cmd_each(const ucl_object_t *obj, char *nodepath, while ((cur = ucl_iterate_object(obj, &it, true))) { char *newkey = NULL; if (ucl_object_type(obj) == UCL_ARRAY) { - asprintf(&newkey, "%c%i", output_sepchar, arrindex); + asprintf_check_enomem(asprintf(&newkey, "%c%i", output_sepchar, arrindex)); arrindex++; } else { - asprintf(&newkey, "%c%s", output_sepchar, ucl_object_key(cur)); + asprintf_check_enomem(asprintf(&newkey, "%c%s", output_sepchar, ucl_object_key(cur))); } if (cur->next != 0 && cur->type != UCL_ARRAY) { /* Implicit array */ @@ -586,12 +585,12 @@ get_cmd_each(const ucl_object_t *obj, char *nodepath, while ((cur = ucl_iterate_object(obj, &it, true))) { char *newnodepath = NULL; if (ucl_object_type(obj) == UCL_ARRAY) { - asprintf(&newnodepath, "%s%c%i", nodepath, output_sepchar, - arrindex); + asprintf_check_enomem(asprintf(&newnodepath, "%s%c%i", nodepath, output_sepchar, + arrindex)); arrindex++; } else { - asprintf(&newnodepath, "%s%c%s", nodepath, output_sepchar, - ucl_object_key(cur)); + asprintf_check_enomem(asprintf(&newnodepath, "%s%c%s", nodepath, output_sepchar, + ucl_object_key(cur))); } if (cur->next != 0 && cur->type != UCL_ARRAY) { /* Implicit array */ @@ -648,12 +647,12 @@ get_cmd_none(const ucl_object_t *obj, char *nodepath, if (next_command != NULL) { char *newnodepath = NULL; if (ucl_object_type(obj) == UCL_ARRAY) { - asprintf(&newnodepath, "%s%c%i", nodepath, output_sepchar, - arrindex); + asprintf_check_enomem(asprintf(&newnodepath, "%s%c%i", nodepath, output_sepchar, + arrindex)); arrindex++; } else { - asprintf(&newnodepath, "%s%c%s", nodepath, output_sepchar, - ucl_object_key(cur)); + asprintf_check_enomem(asprintf(&newnodepath, "%s%c%s", nodepath, output_sepchar, + ucl_object_key(cur))); } if (debug > 2) { fprintf(stderr, "DEBUG: Calling recurse with %s.%s on %s\n", diff --git a/uclcmd_output.c b/uclcmd_output.c index 6e75d0a..3f96efe 100755 --- a/uclcmd_output.c +++ b/uclcmd_output.c @@ -173,7 +173,7 @@ output_key(const ucl_object_t *obj, char *nodepath, const char *inkey) char *key; if (inkey == NULL) { - asprintf(&key, ""); + key = ""; } else { key = strdup(inkey); } diff --git a/uclcmd_parse.c b/uclcmd_parse.c index 910d902..71e8968 100755 --- a/uclcmd_parse.c +++ b/uclcmd_parse.c @@ -72,7 +72,7 @@ parse_input(struct ucl_parser *parser, FILE *source) /* There must be a better way to detect a string */ ucl_parser_clear_error(parser); success = true; - asprintf(&data, "%s", inbuf); + asprintf_check_enomem(asprintf(&data, "%s", inbuf)); obj = ucl_object_fromstring_common(data, 0, UCL_STRING_PARSE); } else { obj = ucl_parser_get_object(parser); From d097216c2e1a238f55c2eebcbb41fcd09837dc78 Mon Sep 17 00:00:00 2001 From: Marie Helene Kvello-Aune Date: Sat, 2 Jan 2016 06:10:11 +0100 Subject: [PATCH 2/3] Updated readme with instructions for which libucl to use --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2e2da91..9f930c2 100644 --- a/README.md +++ b/README.md @@ -10,3 +10,4 @@ instead of jq's .object.object[arrayindex]|command Although uclcmd commands are not actually 'piped' and only the 'each' command can be stacked. Running other commands just runs them sequentially +uclcmd currently targets the master branch of [vstakhov/libucl](https://github.com/vstakhov/libucl), as some used features are not available in an existing release. \ No newline at end of file From e52356521f2ddc4adf76a372bd5e5908e9ea9d42 Mon Sep 17 00:00:00 2001 From: Marie Helene Kvello-Aune Date: Sat, 2 Jan 2016 07:43:42 +0100 Subject: [PATCH 3/3] Using atexit() to call cleanup. Fixed asprintf_check_enomem() to call cleanup and set errno global variable. --- uclcmd.c | 2 +- uclcmd_common.c | 20 +++++++++++--------- uclcmd_get.c | 2 -- uclcmd_merge.c | 2 -- uclcmd_output.c | 2 -- uclcmd_parse.c | 4 ---- uclcmd_remove.c | 2 -- uclcmd_set.c | 2 -- 8 files changed, 12 insertions(+), 24 deletions(-) diff --git a/uclcmd.c b/uclcmd.c index 227351c..cff4654 100755 --- a/uclcmd.c +++ b/uclcmd.c @@ -55,6 +55,7 @@ char *include_file = NULL; int main(int argc, char *argv[]) { + atexit(cleanup); int ret = 0, i = 0; bool verbfound = false; verbmap_t cmdmap[] = @@ -163,4 +164,3 @@ cleanup() ucl_object_unref(set_obj); } } - diff --git a/uclcmd_common.c b/uclcmd_common.c index 2334602..ab4e792 100755 --- a/uclcmd_common.c +++ b/uclcmd_common.c @@ -32,15 +32,17 @@ void asprintf_check_enomem(int retcode) { - /* - * This method is called with the return code of asprintf() as parameter. - * asprintf returns -1 when it cannot allocate memory. - * See printf(3) for details. - */ - if (retcode != -1) - return; - fprintf(stderr, "ENOMEM(%d): Could not allocate memory.\n", ENOMEM); - abort(); + /* + * This method is called with the return code of asprintf() as parameter. + * asprintf returns -1 when it cannot allocate memory. + * See printf(3) for details. + */ + if (retcode != -1) + return; + errno = ENOMEM; + fprintf(stderr, "ENOMEM(%d): Could not allocate memory.\n", ENOMEM); + cleanup(); + abort(); } char* diff --git a/uclcmd_get.c b/uclcmd_get.c index ca2a10f..6e3db6e 100755 --- a/uclcmd_get.c +++ b/uclcmd_get.c @@ -136,8 +136,6 @@ get_main(int argc, char *argv[]) get_mode(argv[k]); } - cleanup(); - if (nonewline) { printf("\n"); } diff --git a/uclcmd_merge.c b/uclcmd_merge.c index 6b6e6d8..b0c2811 100755 --- a/uclcmd_merge.c +++ b/uclcmd_merge.c @@ -144,8 +144,6 @@ merge_main(int argc, char *argv[]) ret = 1; } - cleanup(); - if (nonewline) { printf("\n"); } diff --git a/uclcmd_output.c b/uclcmd_output.c index 3f96efe..d51655b 100755 --- a/uclcmd_output.c +++ b/uclcmd_output.c @@ -75,8 +75,6 @@ output_main(int argc, char *argv[]) ucl_obj_dump(root_obj, 0); - cleanup(); - if (nonewline) { printf("\n"); } diff --git a/uclcmd_parse.c b/uclcmd_parse.c index 71e8968..905c86e 100755 --- a/uclcmd_parse.c +++ b/uclcmd_parse.c @@ -38,7 +38,6 @@ parse_file(struct ucl_parser *parser, const char *filename) if (ucl_parser_get_error(parser)) { fprintf(stderr, "Error occured: %s\n", ucl_parser_get_error(parser)); - cleanup(); exit(2); } @@ -46,7 +45,6 @@ parse_file(struct ucl_parser *parser, const char *filename) if (ucl_parser_get_error(parser)) { fprintf(stderr, "Error: Parse Error occured: %s\n", ucl_parser_get_error(parser)); - cleanup(); exit(3); } @@ -81,7 +79,6 @@ parse_input(struct ucl_parser *parser, FILE *source) if (ucl_parser_get_error(parser)) { fprintf(stderr, "Error: Parse Error occured: %s\n", ucl_parser_get_error(parser)); - cleanup(); exit(3); } @@ -107,7 +104,6 @@ parse_string(struct ucl_parser *parser, char *data) if (ucl_parser_get_error(parser)) { fprintf(stderr, "Error: Parse Error occured: %s\n", ucl_parser_get_error(parser)); - cleanup(); exit(3); } diff --git a/uclcmd_remove.c b/uclcmd_remove.c index 3acc52b..28952a2 100755 --- a/uclcmd_remove.c +++ b/uclcmd_remove.c @@ -178,8 +178,6 @@ remove_main(int argc, char *argv[]) } get_mode(""); - cleanup(); - if (nonewline) { printf("\n"); } diff --git a/uclcmd_set.c b/uclcmd_set.c index d92319f..14ed8c0 100755 --- a/uclcmd_set.c +++ b/uclcmd_set.c @@ -144,8 +144,6 @@ set_main(int argc, char *argv[]) ret = 1; } - cleanup(); - if (nonewline) { printf("\n"); }