From 284eb635b9b8ad0063e1c091b8d7cf3c47e855ef Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Tue, 30 May 2017 18:54:38 -0700 Subject: [PATCH] zclsyntax: fix parser infinite loops on certain EOF cases The recovery functions in particular were not all properly handling EOF, so they would spin forever looking for the right place to stop. --- zcl/zclsyntax/parser.go | 47 ++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/zcl/zclsyntax/parser.go b/zcl/zclsyntax/parser.go index f8100dc..9b78ccd 100644 --- a/zcl/zclsyntax/parser.go +++ b/zcl/zclsyntax/parser.go @@ -71,20 +71,22 @@ Token: } default: bad := p.Read() - if bad.Type == TokenOQuote { - diags = append(diags, &zcl.Diagnostic{ - Severity: zcl.DiagError, - Summary: "Invalid attribute name", - Detail: "Attribute names must not be quoted.", - Subject: &bad.Range, - }) - } else { - diags = append(diags, &zcl.Diagnostic{ - Severity: zcl.DiagError, - Summary: "Attribute or block definition required", - Detail: "An attribute or block definition is required here.", - Subject: &bad.Range, - }) + if !p.recovery { + if bad.Type == TokenOQuote { + diags = append(diags, &zcl.Diagnostic{ + Severity: zcl.DiagError, + Summary: "Invalid attribute name", + Detail: "Attribute names must not be quoted.", + Subject: &bad.Range, + }) + } else { + diags = append(diags, &zcl.Diagnostic{ + Severity: zcl.DiagError, + Summary: "Attribute or block definition required", + Detail: "An attribute or block definition is required here.", + Subject: &bad.Range, + }) + } } endRange = p.PrevRange() // arbitrary, but somewhere inside the body means better diagnostics @@ -169,6 +171,19 @@ Token: diags = append(diags, labelDiags...) labels = append(labels, label) labelRanges = append(labelRanges, labelRange) + if labelDiags.HasErrors() { + p.recoverAfterBodyItem() + return &Block{ + Type: blockType, + Labels: labels, + Body: nil, + + TypeRange: ident.Range, + LabelRanges: labelRanges, + OpenBraceRange: ident.Range, // placeholder + CloseBraceRange: ident.Range, // placeholder + }, diags + } default: switch tok.Type { @@ -346,6 +361,8 @@ func (p *parser) recover(end TokenType) { } nest-- + case TokenEOF: + return } } } @@ -366,7 +383,7 @@ Token: for { tok := p.Read() switch tok.Type { - case start: + case start, TokenEOF: break Token } }