Blame SOURCES/0005-script-fix-various-memory-leaks.patch

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