From b31b286425b7f80f0f078dc00a567bb53be170f3 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 10 Nov 2026 08:26:37 +0000 Subject: [PATCH] aml: A store into a buffer keeps the buffer's length Storing a buffer into a buffer replaced it, length included. As in ACPICA, the source is now copied into the buffer, which keeps its length: the rest is zeroed, or the source cut. An empty buffer takes the source's length. Found on a Dell XPS 13 7390, whose _BIF stores each text into a buffer one byte longer, then sets that last byte for its null: it failed with IndexOutOfBounds, and the battery read nothing. --- src/aml/object.rs | 9 +++++++-- tests/store.asl | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/aml/object.rs b/src/aml/object.rs index cc96af52..d1510b34 100644 --- a/src/aml/object.rs +++ b/src/aml/object.rs @@ -381,7 +381,7 @@ impl Object { /// Replace this object's contents with that of a `new` object, applying implicit casting rules /// as needed. This follows the NT interpreter's creative interpretation of implicit casts, which is - /// effectively a byte-wise transmutation. + /// effectively a byte-wise transmutation. A buffer keeps its length, unless it's empty. pub fn replace_with_implicit_casting(&mut self, new: Object) -> Result<(), AmlError> { let new_bytes = match new { Object::Integer(value) => &value.to_le_bytes(), @@ -401,7 +401,12 @@ impl Object { *value = String::from_utf8_lossy(new_bytes).split('\0').next().unwrap().to_string(); } Object::Buffer(value) => { - *value = new_bytes.to_vec(); + if value.is_empty() { + value.resize(new_bytes.len(), 0); + } + let n = usize::min(new_bytes.len(), value.len()); + value[..n].copy_from_slice(&new_bytes[..n]); + value[n..].fill(0); } _ => return Err(AmlError::InvalidImplicitCast { from: self.typ(), to: new.typ() }), } diff --git a/tests/store.asl b/tests/store.asl index 5feca531..f52c07da 100644 --- a/tests/store.asl +++ b/tests/store.asl @@ -177,6 +177,20 @@ DefinitionBlock ("", "DSDT", 2, "RSACPI", "TESTTABL", 0xF0F0F0F0) } } + Method (T10) { + Name(BUF, Buffer (4) { 0xff, 0xff, 0xff, 0xff }) + BUF = Buffer () { 1, 2 } + CHEK(BUF, Buffer () { 1, 2, 0, 0 }) + BUF = Buffer () { 1, 2, 3, 4, 5, 6 } + CHEK(BUF, Buffer () { 1, 2, 3, 4 }) + } + + Method (T11) { + Name(BUF, Buffer (0) {}) + BUF = Buffer () { 1, 2 } + CHEK(BUF, Buffer () { 1, 2 }) + } + Method (MAIN, 0, NotSerialized) { T1() T2() @@ -196,6 +210,8 @@ DefinitionBlock ("", "DSDT", 2, "RSACPI", "TESTTABL", 0xF0F0F0F0) U4() // references-8 U5() // references-9 U6() // references-10 + T10() + T11() Return (FCNT) }