[Razor] State pollution in `BeginWriteTagHelperAttribute` due to uncleared `_attributeInfo` in `RazorPageBase.EndWriteAttribute`
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Describe the bug
When an HTML dynamic attribute (e.g., `dir="@Model.Direction"`) is immediately followed by a TagHelper attribute that contains the `@@` escape sequence (e.g., ``), the internal `_attributeInfo` state in `RazorPageBase` is not properly cleared.
This causes a "dirty read" during the execution of the TagHelper attribute. Because the C# Razor compiler emits a `WriteAttributeValue` call inside `BeginWriteTagHelperAttribute()` when it splits the string at `@@`, it mistakenly inherits the stale `_attributeInfo` state and leaks the prefix of the previous HTML attribute (e.g., ` dir="`) directly into the middle of the TagHelper's generated output buffer.
### Expected Behavior
The previous attribute's state should be fully cleared when `EndWriteAttribute()` is called, preventing its prefix from polluting any subsequent TagHelper attributes. The TagHelper should correctly resolve the URL without injecting garbage text.
Expected Output:
```html
```
### Steps To Reproduce
1. Create a standard ASP.NET Core MVC or Razor Pages project.
2. Add the following markup to any `.cshtml` file (e.g., `_Layout.cshtml`). Notice that the `` tag has a dynamic attribute, followed immediately by a TagHelper attribute (`~/`) that contains an escaped `@` (`@@`):
```html
```
3. Run the application and inspect the page source.
4. The output will be silently corrupted with the `dir="` prefix leaking into the `href` attribute:
```html
```
### Exceptions (if any)
No exceptions are thrown. This is a silent HTML generation corruption bug.
### .NET Version
10.0 (Also reproducible in earlier .NET Core versions)
### Anything else?
**Root cause analysis:**
This occurs because `BeginWriteTagHelperAttribute` sets up a `StringWriter` buffer, and when the Razor Chunk Generator encounters the `@@` escape sequence, it breaks the string and emits a `WriteAttributeValue` call inside this scope.
Because `RazorPageBase.EndWriteAttribute` failed to reset the `_attributeInfo` struct, `WriteAttributeValue` sees `_attributeInfo.AttributeValuesCount == 1` and blindly prepends the stale prefix to the new buffer.
**Proposed Fix:**
A PR has already been prepared and submitted to fix this by adding `_attributeInfo = default;` to the end of `RazorPageBase.EndWriteAttribute()`. This guarantees the attribute scope state is properly cleared.
Contributor guide
Research direction
Start at RazorPageBase.EndWriteAttribute and trace how _attributeInfo is read by BeginWriteTagHelperAttribute and WriteAttributeValue. Reproduce the provided .cshtml case in an ASP.NET Core MVC or Razor Pages project, then verify the generated link matches the expected output without the prior dir prefix.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- backend, web-dev
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100