]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ACPICA: Fix memory leak if acpi_ps_get_next_field() fails
authorArmin Wolf <W_Armin@gmx.de>
Sun, 14 Apr 2024 19:50:33 +0000 (21:50 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 29 Aug 2024 17:03:14 +0000 (19:03 +0200)
ACPICA commit 1280045754264841b119a5ede96cd005bc09b5a7

If acpi_ps_get_next_field() fails, the previously created field list
needs to be properly disposed before returning the status code.

Link: https://github.com/acpica/acpica/commit/12800457
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
[ rjw: Rename local variable to avoid compiler confusion ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/acpica/psargs.c

index 7debfd5ce0d866d7ba5f0851dc5e1b031e777bac..28582adfc0acafbd83f534a5ead68f439e7e4d3a 100644 (file)
@@ -25,6 +25,8 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state);
 static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
                                                       *parser_state);
 
+static void acpi_ps_free_field_list(union acpi_parse_object *start);
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ps_get_next_package_length
@@ -683,6 +685,39 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
        return_PTR(field);
 }
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ps_free_field_list
+ *
+ * PARAMETERS:  start               - First Op in field list
+ *
+ * RETURN:      None.
+ *
+ * DESCRIPTION: Free all Op objects inside a field list.
+ *
+ ******************************************************************************/
+
+static void acpi_ps_free_field_list(union acpi_parse_object *start)
+{
+       union acpi_parse_object *cur = start;
+       union acpi_parse_object *next;
+       union acpi_parse_object *arg;
+
+       while (cur) {
+               next = cur->common.next;
+
+               /* AML_INT_CONNECTION_OP can have a single argument */
+
+               arg = acpi_ps_get_arg(cur, 0);
+               if (arg) {
+                       acpi_ps_free_op(arg);
+               }
+
+               acpi_ps_free_op(cur);
+               cur = next;
+       }
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ps_get_next_arg
@@ -751,6 +786,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
                        while (parser_state->aml < parser_state->pkg_end) {
                                field = acpi_ps_get_next_field(parser_state);
                                if (!field) {
+                                       if (arg) {
+                                               acpi_ps_free_field_list(arg);
+                                       }
+
                                        return_ACPI_STATUS(AE_NO_MEMORY);
                                }