From 687b3f691167ac29361db161fd7e0427652e0a0d Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Thu, 4 Aug 2016 14:48:25 -0700 Subject: [PATCH] [Fixes #815] Fix Debug.Assert failure for malformed tags in expression --- .../Internal/TagHelperParseTreeRewriter.cs | 20 ++++++++------ .../TagHelperParseTreeRewriterTest.cs | 27 +++++++++++++++++++ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/Internal/TagHelperParseTreeRewriter.cs b/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/Internal/TagHelperParseTreeRewriter.cs index ee17ca334c..925d4d146c 100644 --- a/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/Internal/TagHelperParseTreeRewriter.cs +++ b/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/Internal/TagHelperParseTreeRewriter.cs @@ -60,12 +60,12 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal public void Rewrite(RewritingContext context) { - RewriteTags(context.SyntaxTree, context); + RewriteTags(context.SyntaxTree, context, depth: 0); context.SyntaxTree = _currentBlock.Build(); } - private void RewriteTags(Block input, RewritingContext context) + private void RewriteTags(Block input, RewritingContext context, int depth) { // We want to start a new block without the children from existing (we rebuild them). TrackBlock(new BlockBuilder @@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal // Non-TagHelper tag. ValidateParentAllowsPlainTag(childBlock, context.ErrorSink); - TrackTagBlock(childBlock); + TrackTagBlock(childBlock, depth); } // If we get to here it means that we're a normal html tag. No need to iterate any deeper into @@ -102,7 +102,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal else { // We're not an Html tag so iterate through children recursively. - RewriteTags(childBlock, context); + RewriteTags(childBlock, context, depth + 1); continue; } } @@ -133,7 +133,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal BuildCurrentlyTrackedBlock(); } - private void TrackTagBlock(Block childBlock) + private void TrackTagBlock(Block childBlock, int depth) { var tagName = GetTagName(childBlock); @@ -148,6 +148,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal var parentTracker = _trackerStack.Count > 0 ? _trackerStack.Peek() : null; if (parentTracker != null && !parentTracker.IsTagHelper && + depth == parentTracker.Depth && string.Equals(parentTracker.TagName, tagName, StringComparison.OrdinalIgnoreCase)) { PopTrackerStack(); @@ -157,7 +158,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal { // If it's not a void element and it's not self-closing then we need to create a tag // tracker for it. - var tracker = new TagBlockTracker(tagName, isTagHelper: false); + var tracker = new TagBlockTracker(tagName, isTagHelper: false, depth: depth); PushTrackerStack(tracker); } } @@ -802,15 +803,18 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal private class TagBlockTracker { - public TagBlockTracker(string tagName, bool isTagHelper) + public TagBlockTracker(string tagName, bool isTagHelper, int depth) { TagName = tagName; IsTagHelper = isTagHelper; + Depth = depth; } public string TagName { get; } public bool IsTagHelper { get; } + + public int Depth { get; } } private class TagHelperBlockTracker : TagBlockTracker @@ -818,7 +822,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal private IEnumerable _prefixedAllowedChildren; public TagHelperBlockTracker(TagHelperBlockBuilder builder) - : base(builder.TagName, isTagHelper: true) + : base(builder.TagName, isTagHelper: true, depth: 0) { Builder = builder; diff --git a/test/Microsoft.AspNetCore.Razor.Test/Parser/TagHelpers/Internal/TagHelperParseTreeRewriterTest.cs b/test/Microsoft.AspNetCore.Razor.Test/Parser/TagHelpers/Internal/TagHelperParseTreeRewriterTest.cs index 34e0135a1e..6b0bf074fb 100644 --- a/test/Microsoft.AspNetCore.Razor.Test/Parser/TagHelpers/Internal/TagHelperParseTreeRewriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Test/Parser/TagHelpers/Internal/TagHelperParseTreeRewriterTest.cs @@ -4486,5 +4486,32 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal { RunParseTreeRewriterTest(documentContent, expectedOutput, "p", "div"); } + + [Fact] + public void Rewrite_HandlesMalformedNestedNonTagHelperTags_Correctly() + { + var documentContent = "
@{
}"; + var expectedOutput = new MarkupBlock( + new MarkupTagBlock( + Factory.Markup("
")), + new StatementBlock( + Factory.CodeTransition(), + Factory.MetaCode("{").Accepts(AcceptedCharacters.None), + new MarkupBlock( + new MarkupTagBlock( + Factory.Markup("
").Accepts(AcceptedCharacters.None))), + Factory.EmptyCSharp().AsStatement(), + Factory.MetaCode("}").Accepts(AcceptedCharacters.None)), + Factory.EmptyHtml()); + var expectedErrors = new[] + { + new RazorError( + "Encountered end tag \"div\" with no matching start tag. Are your start/end tags properly balanced?", + new SourceLocation(9, 0, 9), + 3), + }; + + RunParseTreeRewriterTest(documentContent, expectedOutput, expectedErrors); + } } } \ No newline at end of file