Skip to content

Commit

Permalink
Bugfix: CSS error loop when encountering } in inline style
Browse files Browse the repository at this point in the history
  • Loading branch information
tdewolff committed Jun 5, 2019
1 parent b8d8be7 commit c7ade08
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 19 deletions.
36 changes: 20 additions & 16 deletions css/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,14 @@ func (p *Parser) parseDeclarationList() GrammarType {
p.l.r.Move(-len(p.data))
p.err = parse.NewErrorLexer("unexpected token in declaration", p.l.r)
p.l.r.Move(len(p.data))
return p.parseDeclarationError(p.tt, p.data, true)

if p.tt == RightBraceToken {
// right brace token will occur when we've had a decl error that ended in a right brace token
// as these are not handled by decl error, we handle it here explictly. Normally its used to end eg. the qual rule.
p.pushBuf(p.tt, p.data)
return ErrorGrammar
}
return p.parseDeclarationError(p.tt, p.data)
}

////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -362,12 +369,14 @@ func (p *Parser) parseDeclaration() GrammarType {
p.initBuf()
parse.ToLower(p.data)

ttName, dataName := p.tt, p.data
tt, data := p.popToken(false)
if tt != ColonToken {
p.l.r.Move(-len(data))
p.err = parse.NewErrorLexer("expected colon in declaration", p.l.r)
p.l.r.Move(len(data))
return p.parseDeclarationError(tt, data, false)
p.pushBuf(ttName, dataName)
return p.parseDeclarationError(tt, data)
}

skipWS := true
Expand All @@ -392,14 +401,10 @@ func (p *Parser) parseDeclaration() GrammarType {
}
}

func (p *Parser) parseDeclarationError(tt TokenType, data []byte, skipFirstPush bool) GrammarType {
first := true
func (p *Parser) parseDeclarationError(tt TokenType, data []byte) GrammarType {
// we're on the offending (tt,data), keep popping tokens till we reach ;, }, or EOF
p.tt, p.data = tt, data
for {
if first {
first = false
} else {
tt, data = p.popToken(false)
}
if (tt == SemicolonToken || tt == RightBraceToken) && p.level == 0 || tt == ErrorToken {
p.prevEnd = (tt == RightBraceToken)
if tt == SemicolonToken {
Expand All @@ -411,14 +416,13 @@ func (p *Parser) parseDeclarationError(tt TokenType, data []byte, skipFirstPush
} else if tt == RightParenthesisToken || tt == RightBraceToken || tt == RightBracketToken {
p.level--
}
if skipFirstPush {
skipFirstPush = false
} else {
if p.prevWS {
p.pushBuf(WhitespaceToken, wsBytes)
}
p.pushBuf(tt, data)

if p.prevWS {
p.pushBuf(WhitespaceToken, wsBytes)
}
p.pushBuf(tt, data)

tt, data = p.popToken(false)
}
}

Expand Down
6 changes: 5 additions & 1 deletion css/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ func TestParse(t *testing.T) {
{false, "@media{selector{", "@media{selector{"},

// bad grammar
{false, "}", "ERROR(})"},
{true, "}", "ERROR(})"},
{true, "~color:red", "ERROR(~color:red)"},
{true, "(color;red)", "ERROR((color;red))"},
{true, "color(;red)", "ERROR(color(;red))"},
Expand Down Expand Up @@ -118,7 +120,7 @@ func TestParse(t *testing.T) {
data = parse.Copy(data)
if grammar == ErrorGrammar {
if err := p.Err(); err != io.EOF {
data = append([]byte("ERROR("), data...)
data = []byte("ERROR(")
for _, val := range p.Values() {
data = append(data, val.Data...)
}
Expand Down Expand Up @@ -162,6 +164,8 @@ func TestParseError(t *testing.T) {
css string
col int
}{
{false, "}", 2},
{true, "}", 1},
{false, "selector", 9},
{true, "color 0", 7},
{true, "--color 0", 9},
Expand Down
4 changes: 2 additions & 2 deletions error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func TestError(t *testing.T) {
line, column, context := err.Position()
test.T(t, line, 1, "line")
test.T(t, column, 4, "column")
test.T(t, context, " 1: buffer\n ^", "context")
test.T(t, "\n"+context, "\n 1: buffer\n ^", "context")

test.T(t, err.Error(), "parse error:1:4: message\n 1: buffer\n ^", "error")
}
Expand All @@ -27,7 +27,7 @@ func TestErrorLexer(t *testing.T) {
line, column, context := err.Position()
test.T(t, line, 1, "line")
test.T(t, column, 4, "column")
test.T(t, context, " 1: buffer\n ^", "context")
test.T(t, "\n"+context, "\n 1: buffer\n ^", "context")

test.T(t, err.Error(), "parse error:1:4: message\n 1: buffer\n ^", "error")
}

0 comments on commit c7ade08

Please sign in to comment.