Fix null pointer dereference printing an expression.

Parser.parseVariable method should always set the value of the variable
it creates. Failure to do so may end up in the following:

```
$ androidmk  <(printf "FOO:=(X)\nFOO:=bar\n")
parse error:
<input>:3:1: variable already set, previous assignment: FOO@<input>:1:5 = %!s(PANIC=String method: runtime error: invalid memory address or nil pointer dereference) (%!s(PANIC=String method: runtime error: invalid memory address or nil pointer dereference)) false
```

The cause is that calling Parser.Parse to parse `FOO=abc` created
a Variable instance with nil value, causing panic on print attempt.

Test: m androidmk && androidmk  <(printf "FOO:=(X)\nFOO:=bar\n")
(should print:
ERROR:  parse error:
<input>:3:1: variable already set, previous assignment: FOO@<input>:1:5 = X = Not Evaluated (X = Not Evaluated) false)

Change-Id: I296d7984df6d8796e0075f9eb692b234f8c94f08
This commit is contained in:
Sasha Smundak 2020-01-21 13:31:06 -08:00
parent 0c4d1db0a0
commit 77418b70b4
3 changed files with 49 additions and 0 deletions

View file

@ -164,6 +164,7 @@ const (
Int64Type Int64Type
ListType ListType
MapType MapType
NotEvaluatedType
) )
func (t Type) String() string { func (t Type) String() string {
@ -178,6 +179,8 @@ func (t Type) String() string {
return "list" return "list"
case MapType: case MapType:
return "map" return "map"
case NotEvaluatedType:
return "notevaluated"
default: default:
panic(fmt.Errorf("Unknown type %d", t)) panic(fmt.Errorf("Unknown type %d", t))
} }
@ -476,6 +479,29 @@ func (c Comment) Text() string {
return string(buf) return string(buf)
} }
type NotEvaluated struct {
Position scanner.Position
}
func (n NotEvaluated) Copy() Expression {
return NotEvaluated{Position: n.Position}
}
func (n NotEvaluated) String() string {
return "Not Evaluated"
}
func (n NotEvaluated) Type() Type {
return NotEvaluatedType
}
func (n NotEvaluated) Eval() Expression {
return NotEvaluated{Position: n.Position}
}
func (n NotEvaluated) Pos() scanner.Position { return n.Position }
func (n NotEvaluated) End() scanner.Position { return n.Position }
func endPos(pos scanner.Position, n int) scanner.Position { func endPos(pos scanner.Position, n int) scanner.Position {
pos.Offset += n pos.Offset += n
pos.Column += n pos.Column += n

View file

@ -484,6 +484,8 @@ func (p *parser) parseVariable() Expression {
} }
value = assignment.Value value = assignment.Value
} }
} else {
value = &NotEvaluated{}
} }
value = &Variable{ value = &Variable{
Name: text, Name: text,

View file

@ -1122,3 +1122,24 @@ func TestParserEndPos(t *testing.T) {
} }
} }
} }
func TestParserNotEvaluated(t *testing.T) {
// When parsing without evaluation, create variables correctly
scope := NewScope(nil)
input := "FOO=abc\n"
_, errs := Parse("", bytes.NewBufferString(input), scope)
if errs != nil {
t.Errorf("unexpected errors:")
for _, err := range errs {
t.Errorf(" %s", err)
}
t.FailNow()
}
assignment, found := scope.Get("FOO")
if !found {
t.Fatalf("Expected to find FOO after parsing %s", input)
}
if s := assignment.String(); strings.Contains(s, "PANIC") {
t.Errorf("Attempt to print FOO returned %s", s)
}
}