From 6980c2cdf003f5963695809b3a278ff53ad51832 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 15 Oct 2018 21:44:10 -0400 Subject: [PATCH 5/6] script: fix various memory leaks coverity found a few leaks. this commit mops them up. --- src/plugins/splash/script/script-lib-image.c | 5 +- src/plugins/splash/script/script-lib-sprite.c | 4 +- src/plugins/splash/script/script-parse.c | 61 +++++++++++++++++-- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/src/plugins/splash/script/script-lib-image.c b/src/plugins/splash/script/script-lib-image.c index a202702..748e6d1 100644 --- a/src/plugins/splash/script/script-lib-image.c +++ b/src/plugins/splash/script/script-lib-image.c @@ -173,61 +173,64 @@ static script_return_t image_text (script_state_t *state, script_obj_unref (alpha_obj); font_obj = script_obj_hash_peek_element (state->local, "font"); if (script_obj_is_string (font_obj)) font = script_obj_as_string (font_obj); else font = NULL; script_obj_unref (font_obj); align_obj = script_obj_hash_peek_element (state->local, "align"); if (script_obj_is_string (align_obj)) { char *align_str = script_obj_as_string (align_obj); if (!strcmp ("left", align_str)) align = PLY_LABEL_ALIGN_LEFT; else if (!strcmp ("center", align_str)) align = PLY_LABEL_ALIGN_CENTER; else if (!strcmp ("right", align_str)) align = PLY_LABEL_ALIGN_RIGHT; else ply_error ("Unrecognized Image.Text alignment string '%s'. " "Expecting 'left', 'center', or 'right'\n", align_str); free (align_str); } script_obj_unref (align_obj); - if (!text) return script_return_obj_null (); + if (!text) { + free (font); + return script_return_obj_null (); + } label = ply_label_new (); ply_label_set_text (label, text); if (font) ply_label_set_font (label, font); ply_label_set_alignment (label, align); ply_label_set_color (label, red, green, blue, alpha); ply_label_show (label, NULL, 0, 0); width = ply_label_get_width (label); height = ply_label_get_height (label); image = ply_pixel_buffer_new (width, height); ply_label_draw_area (label, image, 0, 0, width, height); free (text); free (font); ply_label_free (label); return script_return_obj (script_obj_new_native (image, data->class)); } script_lib_image_data_t *script_lib_image_setup (script_state_t *state, char *image_dir) { script_lib_image_data_t *data = malloc (sizeof(script_lib_image_data_t)); data->class = script_obj_native_class_new (image_free, "image", data); data->image_dir = strdup (image_dir); diff --git a/src/plugins/splash/script/script-lib-sprite.c b/src/plugins/splash/script/script-lib-sprite.c index c49297d..b119f05 100644 --- a/src/plugins/splash/script/script-lib-sprite.c +++ b/src/plugins/splash/script/script-lib-sprite.c @@ -714,66 +714,68 @@ region_add_area (ply_region_t *region, ply_region_add_rectangle (region, &rectangle); } void script_lib_sprite_pixel_display_removed (script_lib_sprite_data_t *data, ply_pixel_display_t *pixel_display) { ply_list_node_t *node; ply_list_node_t *next_node; script_lib_display_t* display; if (!data) return; node = ply_list_get_first_node (data->displays); while (node) { next_node = ply_list_get_next_node (data->displays, node); display = ply_list_node_get_data (node); if (display->pixel_display == pixel_display) { ply_list_remove_node (data->displays, node); } node = next_node; } } void script_lib_sprite_refresh (script_lib_sprite_data_t *data) { ply_list_node_t *node; - ply_region_t *region = ply_region_new (); + ply_region_t *region; ply_list_t *rectable_list; if (!data) return; + region = ply_region_new (); + ply_list_sort_stable (data->sprite_list, &sprite_compare_z); node = ply_list_get_first_node (data->sprite_list); if (data->full_refresh) { for (node = ply_list_get_first_node (data->displays); node; node = ply_list_get_next_node (data->displays, node)) { script_lib_display_t *display = ply_list_node_get_data (node); region_add_area (region, display->x, display->y, ply_pixel_display_get_width (display->pixel_display), ply_pixel_display_get_height (display->pixel_display)); } data->full_refresh = false; } while (node) { sprite_t *sprite = ply_list_node_get_data (node); ply_list_node_t *next_node = ply_list_get_next_node (data->sprite_list, node); if (sprite->remove_me) { if (sprite->image) { region_add_area (region, sprite->old_x, sprite->old_y, sprite->old_width, diff --git a/src/plugins/splash/script/script-parse.c b/src/plugins/splash/script/script-parse.c index a4c7656..ea5fdd2 100644 --- a/src/plugins/splash/script/script-parse.c +++ b/src/plugins/splash/script/script-parse.c @@ -27,60 +27,61 @@ #include "ply-hashtable.h" #include "ply-list.h" #include "ply-bitarray.h" #include "ply-logger.h" #include #include #include #include #include #include #include #include #include "script-debug.h" #include "script-scan.h" #include "script-parse.h" #define WITH_SEMIES typedef struct { const char *symbol; script_exp_type_t exp_type; int presedence; }script_parse_operator_table_entry_t; static script_op_t *script_parse_op (script_scan_t *scan); static script_exp_t *script_parse_exp (script_scan_t *scan); static ply_list_t *script_parse_op_list (script_scan_t *scan); static void script_parse_op_list_free (ply_list_t *op_list); +static void script_parse_exp_free (script_exp_t *exp); static script_exp_t *script_parse_new_exp (script_exp_type_t type, script_debug_location_t *location) { script_exp_t *exp = malloc (sizeof(script_exp_t)); exp->type = type; script_debug_add_element (exp, location); return exp; } static script_exp_t *script_parse_new_exp_single (script_exp_type_t type, script_exp_t *sub, script_debug_location_t *location) { script_exp_t *exp = script_parse_new_exp (type, location); exp->data.sub = sub; return exp; } static script_exp_t *script_parse_new_exp_dual (script_exp_type_t type, script_exp_t *sub_a, script_exp_t *sub_b, script_debug_location_t *location) { script_exp_t *exp = script_parse_new_exp (type, location); exp->data.dual.sub_a = sub_a; exp->data.dual.sub_b = sub_b; @@ -198,101 +199,127 @@ static void script_parse_error (script_debug_location_t *location, static const script_parse_operator_table_entry_t * /* Only allows 1 or 2 character symbols */ script_parse_operator_table_entry_lookup (script_scan_t *scan, const script_parse_operator_table_entry_t *table) { int entry_index; script_scan_token_t *curtoken = script_scan_get_current_token (scan); script_scan_token_t *peektoken = script_scan_peek_next_token (scan); for (entry_index = 0; table[entry_index].symbol; entry_index++) { if (!script_scan_token_is_symbol (curtoken)) continue; if (curtoken->data.symbol != table[entry_index].symbol[0]) continue; if (table[entry_index].symbol[1]) { if (!script_scan_token_is_symbol (peektoken)) continue; if (peektoken->data.symbol != table[entry_index].symbol[1]) continue; if (peektoken->whitespace) continue; } break; } return &table[entry_index]; } static void script_parse_advance_scan_by_string (script_scan_t *scan, const char *string) { while (*string) { script_scan_get_next_token (scan); string++; } } +static void +free_parameter_list (script_scan_t *scan, + ply_list_t *parameter_list) +{ + if (parameter_list != NULL) { + ply_list_node_t *node; + + node = ply_list_get_first_node (parameter_list); + while (node != NULL) { + ply_list_node_t *next_node; + char *parameter; + + parameter = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (parameter_list, node); + free (parameter); + ply_list_remove_node (parameter_list, node); + + node = next_node; + } + } +} + static script_function_t *script_parse_function_def (script_scan_t *scan) { script_scan_token_t *curtoken = script_scan_get_current_token (scan); - ply_list_t *parameter_list; + script_function_t *function = NULL; + ply_list_t *parameter_list = NULL; if (!script_scan_token_is_symbol_of_value (curtoken, '(')) { script_parse_error (&curtoken->location, "Function declaration requires parameters to be declared within '(' brackets"); return NULL; } curtoken = script_scan_get_next_token (scan); parameter_list = ply_list_new (); while (true) { if (script_scan_token_is_symbol_of_value (curtoken, ')')) break; if (!script_scan_token_is_identifier (curtoken)) { script_parse_error (&curtoken->location, "Function declaration parameters must be valid identifiers"); - return NULL; + goto out; } char *parameter = strdup (curtoken->data.string); ply_list_append_data (parameter_list, parameter); curtoken = script_scan_get_next_token (scan); if (script_scan_token_is_symbol_of_value (curtoken, ')')) break; if (!script_scan_token_is_symbol_of_value (curtoken, ',')) { script_parse_error (&curtoken->location, "Function declaration parameters must separated with ',' and terminated with a ')'"); - return NULL; + goto out; } curtoken = script_scan_get_next_token (scan); } curtoken = script_scan_get_next_token (scan); script_op_t *func_op = script_parse_op (scan); - script_function_t *function = script_function_script_new (func_op, - NULL, - parameter_list); + function = script_function_script_new (func_op, + NULL, + parameter_list); + parameter_list = NULL; +out: + free_parameter_list (scan, parameter_list); return function; } static script_exp_t *script_parse_exp_tm (script_scan_t *scan) { script_scan_token_t *curtoken = script_scan_get_current_token (scan); script_exp_t *exp = NULL; if (script_scan_token_is_integer (curtoken)) { exp = script_parse_new_exp_number (curtoken->data.integer, &curtoken->location); script_scan_get_next_token (scan); return exp; } if (script_scan_token_is_float (curtoken)) { exp = script_parse_new_exp_number (curtoken->data.floatpoint, &curtoken->location); script_scan_get_next_token (scan); return exp; } if (script_scan_token_is_identifier (curtoken)) { if (script_scan_token_is_identifier_of_value (curtoken, "NULL")) { exp = script_parse_new_exp (SCRIPT_EXP_TYPE_TERM_NULL, &curtoken->location); } else if (script_scan_token_is_identifier_of_value (curtoken, "INFINITY")) { exp = script_parse_new_exp_number (INFINITY, &curtoken->location); } else if (script_scan_token_is_identifier_of_value (curtoken, "NAN")) { exp = script_parse_new_exp_number (NAN, &curtoken->location); } else if (script_scan_token_is_identifier_of_value (curtoken, "global")) { exp = script_parse_new_exp (SCRIPT_EXP_TYPE_TERM_GLOBAL, &curtoken->location); } else if (script_scan_token_is_identifier_of_value (curtoken, "local")) { exp = script_parse_new_exp (SCRIPT_EXP_TYPE_TERM_LOCAL, &curtoken->location); } else if (script_scan_token_is_identifier_of_value (curtoken, "this")) { @@ -300,112 +327,132 @@ static script_exp_t *script_parse_exp_tm (script_scan_t *scan) } else if (script_scan_token_is_identifier_of_value (curtoken, "fun")) { script_debug_location_t location = curtoken->location; script_scan_get_next_token (scan); exp = script_parse_new_exp_function_def (script_parse_function_def (scan), &location); return exp; } else { exp = script_parse_new_exp_var (curtoken->data.string, &curtoken->location); } curtoken = script_scan_get_next_token (scan); return exp; } if (script_scan_token_is_string (curtoken)) { exp = script_parse_new_exp_string (curtoken->data.string, &curtoken->location); script_scan_get_next_token (scan); return exp; } if (script_scan_token_is_symbol_of_value (curtoken, '[')) { ply_list_t *parameters = ply_list_new (); script_debug_location_t location = curtoken->location; script_scan_get_next_token (scan); while (true) { if (script_scan_token_is_symbol_of_value (curtoken, ']')) break; script_exp_t *parameter = script_parse_exp (scan); ply_list_append_data (parameters, parameter); curtoken = script_scan_get_current_token (scan); if (script_scan_token_is_symbol_of_value (curtoken, ']')) break; if (!script_scan_token_is_symbol_of_value (curtoken, ',')) { + ply_list_node_t *node; script_parse_error (&curtoken->location, "Set parameters should be separated with a ',' and terminated with a ']'"); + + + for (node = ply_list_get_first_node (parameters); + node; + node = ply_list_get_next_node (parameters, node)) { + script_exp_t *sub = ply_list_node_get_data (node); + script_parse_exp_free (sub); + } + ply_list_free (parameters); return NULL; } curtoken = script_scan_get_next_token (scan); } script_scan_get_next_token (scan); exp = script_parse_new_exp_set (parameters, &location); return exp; } if (script_scan_token_is_symbol_of_value (curtoken, '(')) { script_scan_get_next_token (scan); exp = script_parse_exp (scan); curtoken = script_scan_get_current_token (scan); if (!exp) { script_parse_error (&curtoken->location, "Expected valid contents of bracketed expression"); return NULL; } if (!script_scan_token_is_symbol_of_value (curtoken, ')')) { script_parse_error (&curtoken->location, "Expected bracketed block to be terminated with a ')'"); return NULL; } script_scan_get_next_token (scan); return exp; } return NULL; } static script_exp_t *script_parse_exp_pi (script_scan_t *scan) { script_exp_t *exp = script_parse_exp_tm (scan); script_scan_token_t *curtoken = script_scan_get_current_token (scan); while (true) { script_debug_location_t location = curtoken->location; if (!script_scan_token_is_symbol (curtoken)) break; if (script_scan_token_is_symbol_of_value (curtoken, '(')) { ply_list_t *parameters = ply_list_new (); script_scan_get_next_token (scan); while (true) { if (script_scan_token_is_symbol_of_value (curtoken, ')')) break; script_exp_t *parameter = script_parse_exp (scan); ply_list_append_data (parameters, parameter); curtoken = script_scan_get_current_token (scan); if (script_scan_token_is_symbol_of_value (curtoken, ')')) break; if (!script_scan_token_is_symbol_of_value (curtoken, ',')) { + ply_list_node_t *node; + script_parse_error (&curtoken->location, "Function parameters should be separated with a ',' and terminated with a ')'"); + + for (node = ply_list_get_first_node (parameters); + node; + node = ply_list_get_next_node (parameters, node)) { + script_exp_t *sub = ply_list_node_get_data (node); + script_parse_exp_free (sub); + } + ply_list_free (parameters); return NULL; } curtoken = script_scan_get_next_token (scan); } script_scan_get_next_token (scan); exp = script_parse_new_exp_function_exe (exp, parameters, &location); continue; } script_exp_t *key; if (script_scan_token_is_symbol_of_value (curtoken, '.')) { script_scan_get_next_token (scan); if (script_scan_token_is_identifier (curtoken)) { key = script_parse_new_exp_string (curtoken->data.string, &curtoken->location); } else { script_parse_error (&curtoken->location, "A dot based hash index must be an identifier"); return NULL; } curtoken = script_scan_get_next_token (scan); } else if (script_scan_token_is_symbol_of_value (curtoken, '[')) { script_scan_get_next_token (scan); key = script_parse_exp (scan); if (!key) { script_parse_error (&curtoken->location, "Expected a valid index expression"); return NULL; } curtoken = script_scan_get_current_token (scan); if (!script_scan_token_is_symbol_of_value (curtoken, ']')) { @@ -965,59 +1012,61 @@ void script_parse_op_free (script_op_t *op) static void script_parse_op_list_free (ply_list_t *op_list) { ply_list_node_t *node; for (node = ply_list_get_first_node (op_list); node; node = ply_list_get_next_node (op_list, node)) { script_op_t *op = ply_list_node_get_data (node); script_parse_op_free (op); } ply_list_free (op_list); return; } script_op_t *script_parse_file (const char *filename) { script_scan_t *scan = script_scan_file (filename); if (!scan) { ply_error ("Parser error : Error opening file %s\n", filename); return NULL; } script_scan_token_t *curtoken = script_scan_get_current_token (scan); script_debug_location_t location = curtoken->location; ply_list_t *list = script_parse_op_list (scan); curtoken = script_scan_get_current_token (scan); if (curtoken->type != SCRIPT_SCAN_TOKEN_TYPE_EOF) { script_parse_error (&curtoken->location, "Unparsed characters at end of file"); + script_parse_op_list_free (list); return NULL; } script_op_t *op = script_parse_new_op_block (list, &location); script_scan_free (scan); return op; } script_op_t *script_parse_string (const char *string, const char *name) { script_scan_t *scan = script_scan_string (string, name); if (!scan) { ply_error ("Parser error : Error creating a parser with a string"); return NULL; } script_scan_token_t *curtoken = script_scan_get_current_token (scan); script_debug_location_t location = curtoken->location; ply_list_t *list = script_parse_op_list (scan); curtoken = script_scan_get_current_token (scan); if (curtoken->type != SCRIPT_SCAN_TOKEN_TYPE_EOF) { script_parse_error (&curtoken->location, "Unparsed characters at end of file"); + script_parse_op_list_free (list); return NULL; } script_op_t *op = script_parse_new_op_block (list, &location); script_scan_free (scan); return op; } -- 2.17.1