diff --git a/src/gopheros/device/acpi/aml/obj_tree.go b/src/gopheros/device/acpi/aml/obj_tree.go index c8dd353..12e79fd 100644 --- a/src/gopheros/device/acpi/aml/obj_tree.go +++ b/src/gopheros/device/acpi/aml/obj_tree.go @@ -284,7 +284,7 @@ func (tree *ObjectTree) Find(scopeIndex uint32, expr []byte) uint32 { // The expression consists of multiple name segments joined together (e.g. FOOFBAR0) // In this case we need to apply relative lookup rules for FOOF.BAR0 return tree.findRelative(scopeIndex, expr) - default: + case exprLen == amlNameLen: // expr is a simple name. According to the spec, we need to // search for it in this scope and all its parent scopes till // we reach the root. @@ -320,7 +320,8 @@ nextSegment: // case skip over them. for ; segIndex < exprLen && expr[segIndex] != '_' && (expr[segIndex] < 'A' || expr[segIndex] > 'Z'); segIndex++ { } - if segIndex >= exprLen { + + if exprLen-segIndex < amlNameLen { return InvalidIndex } diff --git a/src/gopheros/device/acpi/aml/parser.go b/src/gopheros/device/acpi/aml/parser.go index 810edd6..9051cd1 100644 --- a/src/gopheros/device/acpi/aml/parser.go +++ b/src/gopheros/device/acpi/aml/parser.go @@ -41,6 +41,7 @@ type Parser struct { objTree *ObjectTree scopeStack []uint32 pkgEndStack []uint32 + streamEnd uint32 resolvePasses uint32 mergedScopes uint32 @@ -157,6 +158,8 @@ func (p *Parser) init(tableHandle uint8, tableName string, header *table.SDTHead uint32(unsafe.Sizeof(table.SDTHeader{})), ) + // Keep track of the stream end for parsing deferred objects + p.streamEnd = header.Length _ = p.pushPkgEnd(header.Length) } @@ -431,6 +434,7 @@ func (p *Parser) parseStrictTermArg(curObj *Object) (*Object, parseResult) { if !pOpIsType2(nextOp) && !pOpIsDataObject(nextOp) && !pOpIsArg(nextOp) { kfmt.Fprintf(p.errWriter, "[table: %s, offset: 0x%x] encountered unexpected opcode %s while parsing termArg\n", p.tableName, p.r.Offset(), pOpcodeName(nextOp)) + return nil, parseResultFailed } _, _ = p.nextOpcode() @@ -985,8 +989,13 @@ func (p *Parser) pushPkgEnd(pkgEnd uint32) error { } func (p *Parser) popPkgEnd() { - p.pkgEndStack = p.pkgEndStack[:len(p.pkgEndStack)-1] + // Pop pkg end if one exists if len(p.pkgEndStack) != 0 { + p.pkgEndStack = p.pkgEndStack[:len(p.pkgEndStack)-1] + } + + // If the stack is not empty restore the last pushed pkgEnd + if len(p.pkgEndStack) != 0 && len(p.pkgEndStack) != 0 { _ = p.r.SetPkgEnd(p.pkgEndStack[len(p.pkgEndStack)-1]) } } @@ -1024,8 +1033,10 @@ func (p *Parser) connectNamedObjArgs(objIndex uint32) parseResult { return parseResultFailed } - // The last amlNameLen contain the name for this object - nameIndex = len(namepath) - amlNameLen + // The last amlNameLen part of the namepath contains the name for this object + if nameIndex = len(namepath) - amlNameLen; nameIndex < 0 { + return parseResultFailed + } for i := 0; i < amlNameLen; i++ { argObj.name[i] = namepath[nameIndex+i] } @@ -1239,6 +1250,7 @@ func (p *Parser) parseDeferredBlocks(objIndex uint32) parseResult { p.mode = parseModeAllBlocks // Set stream offset to the first arg + p.r.SetPkgEnd(p.streamEnd) p.r.SetOffset(obj.amlOffset + 1) if obj.opcode > 0xff { // opcode length = 2 _, _ = p.r.ReadByte() diff --git a/src/gopheros/device/acpi/aml/parser_test.go b/src/gopheros/device/acpi/aml/parser_test.go index 9fab368..2f514c9 100644 --- a/src/gopheros/device/acpi/aml/parser_test.go +++ b/src/gopheros/device/acpi/aml/parser_test.go @@ -200,7 +200,7 @@ func TestParseAMLErrors(t *testing.T) { } }) - t.Run("connectNonNamedObjArgs failed", func(t *testing.T) { + t.Run("connectNonNamedObjArgs failed", func(t *testing.T) { p, resolver := parserForMockPayload(t, []byte{}) // Use a named object whose args contain a TermArg @@ -727,6 +727,24 @@ func TestConnectNamedObjectsErrors(t *testing.T) { t.Fatalf("expected to get parseResultFailed(%d); got %d", parseResultFailed, res) } }) + + t.Run("incomplete namepath", func(t *testing.T) { + tree := NewObjectTree() + tree.CreateDefaultScopes(0) + + // Use a named object whose args contain a TermArg + namedObj := tree.newNamedObject(pOpBankField, 0, [amlNameLen]byte{'F', 'O', 'O', 'F'}) + namepathObj := tree.newObject(pOpIntNamePath, 0) + namepathObj.value = []byte{'F', 'O'} // namepath len < amlNameLen + tree.append(namedObj, namepathObj) + tree.append(tree.ObjectAt(0), namedObj) + + p := NewParser(ioutil.Discard, tree) + if res := p.connectNamedObjArgs(0); res != parseResultFailed { + t.Fatalf("expected to get parseResultFailed(%d); got %d", parseResultFailed, res) + } + }) + } func TestMergeScopeDirectivesErrors(t *testing.T) { diff --git a/src/gopheros/device/acpi/aml/stream_reader.go b/src/gopheros/device/acpi/aml/stream_reader.go index 850059c..a0a70f8 100644 --- a/src/gopheros/device/acpi/aml/stream_reader.go +++ b/src/gopheros/device/acpi/aml/stream_reader.go @@ -29,12 +29,13 @@ func (r *amlStreamReader) Init(dataAddr uintptr, dataLen, initialOffset uint32) Data: dataAddr, })) + r.SetPkgEnd(dataLen) r.SetOffset(initialOffset) } // EOF returns true if the end of the pkg has been reached. func (r *amlStreamReader) EOF() bool { - return r.offset == r.pkgEnd + return r.offset >= r.pkgEnd } func (r *amlStreamReader) SetPkgEnd(pkgEnd uint32) error {