1
0
mirror of https://github.com/taigrr/gopher-os synced 2025-01-18 04:43:13 -08:00

acpi: fix bugs discovered by fuzzing

This commit is contained in:
Achilleas Anagnostopoulos 2018-03-08 08:37:25 +00:00
parent ddbddd2ea2
commit f57aa9433d
4 changed files with 39 additions and 7 deletions

View File

@ -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) // 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 // In this case we need to apply relative lookup rules for FOOF.BAR0
return tree.findRelative(scopeIndex, expr) return tree.findRelative(scopeIndex, expr)
default: case exprLen == amlNameLen:
// expr is a simple name. According to the spec, we need to // expr is a simple name. According to the spec, we need to
// search for it in this scope and all its parent scopes till // search for it in this scope and all its parent scopes till
// we reach the root. // we reach the root.
@ -320,7 +320,8 @@ nextSegment:
// case skip over them. // case skip over them.
for ; segIndex < exprLen && expr[segIndex] != '_' && (expr[segIndex] < 'A' || expr[segIndex] > 'Z'); segIndex++ { for ; segIndex < exprLen && expr[segIndex] != '_' && (expr[segIndex] < 'A' || expr[segIndex] > 'Z'); segIndex++ {
} }
if segIndex >= exprLen {
if exprLen-segIndex < amlNameLen {
return InvalidIndex return InvalidIndex
} }

View File

@ -41,6 +41,7 @@ type Parser struct {
objTree *ObjectTree objTree *ObjectTree
scopeStack []uint32 scopeStack []uint32
pkgEndStack []uint32 pkgEndStack []uint32
streamEnd uint32
resolvePasses uint32 resolvePasses uint32
mergedScopes uint32 mergedScopes uint32
@ -157,6 +158,8 @@ func (p *Parser) init(tableHandle uint8, tableName string, header *table.SDTHead
uint32(unsafe.Sizeof(table.SDTHeader{})), uint32(unsafe.Sizeof(table.SDTHeader{})),
) )
// Keep track of the stream end for parsing deferred objects
p.streamEnd = header.Length
_ = p.pushPkgEnd(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) { 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)) 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() _, _ = p.nextOpcode()
@ -985,8 +989,13 @@ func (p *Parser) pushPkgEnd(pkgEnd uint32) error {
} }
func (p *Parser) popPkgEnd() { func (p *Parser) popPkgEnd() {
p.pkgEndStack = p.pkgEndStack[:len(p.pkgEndStack)-1] // Pop pkg end if one exists
if len(p.pkgEndStack) != 0 { 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]) _ = p.r.SetPkgEnd(p.pkgEndStack[len(p.pkgEndStack)-1])
} }
} }
@ -1024,8 +1033,10 @@ func (p *Parser) connectNamedObjArgs(objIndex uint32) parseResult {
return parseResultFailed return parseResultFailed
} }
// The last amlNameLen contain the name for this object // The last amlNameLen part of the namepath contains the name for this object
nameIndex = len(namepath) - amlNameLen if nameIndex = len(namepath) - amlNameLen; nameIndex < 0 {
return parseResultFailed
}
for i := 0; i < amlNameLen; i++ { for i := 0; i < amlNameLen; i++ {
argObj.name[i] = namepath[nameIndex+i] argObj.name[i] = namepath[nameIndex+i]
} }
@ -1239,6 +1250,7 @@ func (p *Parser) parseDeferredBlocks(objIndex uint32) parseResult {
p.mode = parseModeAllBlocks p.mode = parseModeAllBlocks
// Set stream offset to the first arg // Set stream offset to the first arg
p.r.SetPkgEnd(p.streamEnd)
p.r.SetOffset(obj.amlOffset + 1) p.r.SetOffset(obj.amlOffset + 1)
if obj.opcode > 0xff { // opcode length = 2 if obj.opcode > 0xff { // opcode length = 2
_, _ = p.r.ReadByte() _, _ = p.r.ReadByte()

View File

@ -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{}) p, resolver := parserForMockPayload(t, []byte{})
// Use a named object whose args contain a TermArg // 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.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) { func TestMergeScopeDirectivesErrors(t *testing.T) {

View File

@ -29,12 +29,13 @@ func (r *amlStreamReader) Init(dataAddr uintptr, dataLen, initialOffset uint32)
Data: dataAddr, Data: dataAddr,
})) }))
r.SetPkgEnd(dataLen)
r.SetOffset(initialOffset) r.SetOffset(initialOffset)
} }
// EOF returns true if the end of the pkg has been reached. // EOF returns true if the end of the pkg has been reached.
func (r *amlStreamReader) EOF() bool { func (r *amlStreamReader) EOF() bool {
return r.offset == r.pkgEnd return r.offset >= r.pkgEnd
} }
func (r *amlStreamReader) SetPkgEnd(pkgEnd uint32) error { func (r *amlStreamReader) SetPkgEnd(pkgEnd uint32) error {