ACPICA: Improve argument parsing in acpi_ps_get_next_simple_arg()

Improve argument parsing in acpi_ps_get_next_simple_arg() to handle
remaining AML data safely.

Link: https://github.com/acpica/acpica/commit/ecbb8bcfe301
Signed-off-by: ikaros <void0red@gmail.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://patch.msgid.link/2008043.taCxCBeP46@rafael.j.wysocki
This commit is contained in:
ikaros 2026-05-27 20:02:49 +02:00 committed by Rafael J. Wysocki
parent 0e2021f49e
commit 27d27e75ec

View File

@ -384,6 +384,8 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
u32 length;
u16 opcode;
u8 *aml = parser_state->aml;
u32 remaining = (u32)ACPI_PTR_DIFF(parser_state->aml_end, aml);
u64 partial_value;
ACPI_FUNCTION_TRACE_U32(ps_get_next_simple_arg, arg_type);
@ -393,8 +395,13 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
/* Get 1 byte from the AML stream */
opcode = AML_BYTE_OP;
arg->common.value.integer = (u64) *aml;
length = 1;
if (remaining >= 1) {
arg->common.value.integer = (u64)*aml;
length = 1;
} else {
arg->common.value.integer = 0;
length = 0;
}
break;
case ARGP_WORDDATA:
@ -402,8 +409,19 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
/* Get 2 bytes from the AML stream */
opcode = AML_WORD_OP;
ACPI_MOVE_16_TO_64(&arg->common.value.integer, aml);
length = 2;
if (remaining >= 2) {
ACPI_MOVE_16_TO_64(&arg->common.value.integer, aml);
length = 2;
} else {
arg->common.value.integer = 0;
length = 0;
if (remaining > 0) {
partial_value = 0;
memcpy(&partial_value, aml, remaining);
arg->common.value.integer = partial_value;
length = remaining;
}
}
break;
case ARGP_DWORDDATA:
@ -411,8 +429,19 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
/* Get 4 bytes from the AML stream */
opcode = AML_DWORD_OP;
ACPI_MOVE_32_TO_64(&arg->common.value.integer, aml);
length = 4;
if (remaining >= 4) {
ACPI_MOVE_32_TO_64(&arg->common.value.integer, aml);
length = 4;
} else {
arg->common.value.integer = 0;
length = 0;
if (remaining > 0) {
partial_value = 0;
memcpy(&partial_value, aml, remaining);
arg->common.value.integer = partial_value;
length = remaining;
}
}
break;
case ARGP_QWORDDATA:
@ -420,8 +449,19 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
/* Get 8 bytes from the AML stream */
opcode = AML_QWORD_OP;
ACPI_MOVE_64_TO_64(&arg->common.value.integer, aml);
length = 8;
if (remaining >= 8) {
ACPI_MOVE_64_TO_64(&arg->common.value.integer, aml);
length = 8;
} else {
arg->common.value.integer = 0;
length = 0;
if (remaining > 0) {
partial_value = 0;
memcpy(&partial_value, aml, remaining);
arg->common.value.integer = partial_value;
length = remaining;
}
}
break;
case ARGP_CHARLIST:
@ -434,10 +474,28 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
/* Find the null terminator */
length = 0;
while (aml[length]) {
while ((length < remaining) && aml[length]) {
length++;
}
length++;
if (length < remaining) {
/* Account for the terminating null */
length++;
} else {
/*
* No terminator found - add null at buffer boundary
* and report a warning
*/
ACPI_WARNING((AE_INFO,
"Invalid AML string: no null terminator, truncating at offset %u",
(u32)(aml - parser_state->aml)));
/* Add null terminator at the boundary */
if (remaining > 0) {
aml[remaining - 1] = 0;
length = remaining;
}
}
break;
case ARGP_NAME: