在 .NET Framework 2.0 中,當自訂配置節 (ConfigurationSection) 使用樹狀結構 (即 ConfigurationElement 巢狀參考自身類型) 時,存取該屬性會拋出 System.StackOverflowException,導致程序崩潰。
public class NodeElement : ConfigurationElement
{
[ConfigurationProperty("text", IsRequired = true)]
public string Text => (string)this["text"];
[ConfigurationProperty("child")]
public NodeElement ChildElement => (NodeElement)this["child"];
}
static class Program
{
[STAThread]
static void Main()
{
NodeElement node = new NodeElement();
object o = node.ChildElement; // 此處拋出 StackOverflowException
}
}
使用 .NET Reflector 反編譯 System.Configuration.ConfigurationElement 原始碼發現,其內部方法 CreateConfigurationPropertyFromAttributes 在建立 ConfigurationProperty 時,缺少對「屬性類型是否為當前類型」的判斷。當屬性型別為 ConfigurationElement 衍生類且指向自身時,PropertiesFromType 會陷入無限遞迴。
private static ConfigurationProperty CreateConfigurationPropertyFromAttributes(PropertyInfo propertyInformation)
{
ConfigurationProperty property = null;
if (Attribute.GetCustomAttribute(propertyInformation, typeof(ConfigurationPropertyAttribute)) is ConfigurationPropertyAttribute)
{
property = new ConfigurationProperty(propertyInformation);
}
// 缺少 property.Type 與當前類型的比較判斷
if ((property != null) && typeof(ConfigurationElement).IsAssignableFrom(property.Type))
{
ConfigurationPropertyCollection result = null;
PropertiesFromType(property.Type, out result); // 無限遞迴入口
}
return property;
}
ConfigurationElement 直接或間接參考自身型別。ConfigurationElementCollection 管理子節點集合,而非單一巢狀屬性。此為 .NET Framework 2.0 基礎類別庫的已知缺陷。開發自訂配置節時,務必注意型別參考關係,避免觸發內部遞迴邏輯導致堆疊溢位。