You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
HtmlAttributeCollection: ICollection<HtmlAttribute>.Clear() and ICollection<HtmlAttribute>.Remove(HtmlAttribute) methods forget to update Hashitems
#463
Closed
elgonzo opened this issue
Jan 14, 2022
· 4 comments
When taking a look at the fix for #461 out of curiosity, i noticed another two issues with HtmlAttributeCollection's ICollection<HtmlAttribute>.Clear() and ICollection<HtmlAttribute>.Remove(HtmlAttribute) implementations.
Both method implementations forget to update the Hashitems dictionary after directly altering the items collection.
The issue manifests and becomes easily observable when working with an HtmlAttributeCollection referenced by a ICollection<HtmlAttribute> variable without repeatedly re-obtaining the collection from the owning node's HtmlNode.Attributes property. (Emptying the internal items list by either clearing or removing the last element from it will cause the getter of the HtmlNode.Attributes property to create and provide a new HtmlAttributeCollection, thus masking the issue.)
usingHtmlAgilityPack;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;namespaceHtmlAttributeCollection_RemoveAndClearNotUpdatingHashItems{classProgram{staticvoidMain(string[]args){Remove_Issue_Demo();Console.WriteLine();Console.WriteLine();Clear_Issue_Demo();}staticvoidRemove_Issue_Demo(){Console.WriteLine("Demo of AttributeCollection item removal issue");Console.WriteLine("----------------------------------------------");var(doc,attributes)=CreateHtmlDocument();Console.WriteLine($"Number of attributes in collection before removal: {attributes.Count}");varattrBeforeRemoval=attributes["class"];Console.WriteLine($"Attribute obtained through this[\"class\"] indexer before removal: {attrBeforeRemoval.Name}={attrBeforeRemoval.Value}");RemoveAnAttribute(attributes);Console.WriteLine($"Number of attributes in collection after removal: {attributes.Count}");varattrAfterRemoval=attributes["class"];Console.WriteLine($"Attribute obtained through this[\"class\"] indexer after removal: {attrAfterRemoval.Name}={attrAfterRemoval.Value}");staticvoidRemoveAnAttribute(ICollection<HtmlAttribute>attributes){varattr=attributes.First();attributes.Remove(attr);}}staticvoidClear_Issue_Demo(){Console.WriteLine("Demo of AttributeCollection clearing issue");Console.WriteLine("------------------------------------------");var(doc,attributes)=CreateHtmlDocument();Console.WriteLine($"Number of attributes in collection before clearing: {attributes.Count}");varattrBeforeClearing=attributes["class"];Console.WriteLine($"Attribute obtained through this[\"class\"] indexer before clearing: {attrBeforeClearing.Name}={attrBeforeClearing.Value}");Clear(attributes);Console.WriteLine($"Number of attributes in collection after clearing: {attributes.Count}");varattrAfterClearing=attributes["class"];Console.WriteLine($"Attribute obtained through this[\"class\"] indexer after clearing: {attrAfterClearing.Name}={attrAfterClearing.Value}");staticvoidClear(ICollection<HtmlAttribute>attributes){attributes.Clear();}}static(HtmlDocumentdoc,HtmlAttributeCollectionattributes)CreateHtmlDocument(){varhtml=@"<div class=""foobar"">Hello world!</div>";varhtmlDoc=newHtmlDocument();htmlDoc.LoadHtml(html);return(htmlDoc,htmlDoc.DocumentNode.SelectSingleNode("//div").Attributes);}}}
Note how after the attribute removal or clearing of the attribute collection the item count of the collection is being reported as 0, yet the removed attribute can still be accessed through the this[string name] indexer.
3. Any further technical details
HAP version: 1.11.40
NET 5.0
The text was updated successfully, but these errors were encountered:
1. Description
When taking a look at the fix for #461 out of curiosity, i noticed another two issues with HtmlAttributeCollection's
ICollection<HtmlAttribute>.Clear()
andICollection<HtmlAttribute>.Remove(HtmlAttribute)
implementations.Both method implementations forget to update the Hashitems dictionary after directly altering the items collection.
html-agility-pack/src/HtmlAgilityPack.Shared/HtmlAttributeCollection.cs
Lines 154 to 157 in 127fe37
html-agility-pack/src/HtmlAgilityPack.Shared/HtmlAttributeCollection.cs
Lines 231 to 234 in 127fe37
The issue manifests and becomes easily observable when working with an HtmlAttributeCollection referenced by a
ICollection<HtmlAttribute>
variable without repeatedly re-obtaining the collection from the owning node'sHtmlNode.Attributes
property. (Emptying the internal items list by either clearing or removing the last element from it will cause the getter of the HtmlNode.Attributes property to create and provide a new HtmlAttributeCollection, thus masking the issue.)2. Fiddle or Project
https://dotnetfiddle.net/D735Ot
Click to expand the source code
Note how after the attribute removal or clearing of the attribute collection the item count of the collection is being reported as
0
, yet the removed attribute can still be accessed through thethis[string name]
indexer.3. Any further technical details
The text was updated successfully, but these errors were encountered: