• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zorbathut / dec / 10786980837

10 Sep 2024 06:26AM UTC coverage: 90.657% (+0.04%) from 90.614%
10786980837

push

github

zorbathut
Fix: Security issue: XML documents could cause arbitrary HTTP requests.

4473 of 4934 relevant lines covered (90.66%)

195267.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.51
/src/ReaderXmlDec.cs
1
namespace Dec
2
{
3
    using System;
4
    using System.Collections.Generic;
5
    using System.IO;
6
    using System.Linq;
7
    using System.Xml;
8
    using System.Xml.Linq;
9

10
    internal class ReaderFileDecXml : ReaderFileDec
11
    {
12
        private XDocument doc;
13
        private string fileIdentifier;
14
        private Recorder.IUserSettings userSettings;
15

16
        public static ReaderFileDecXml Create(TextReader input, string identifier, Recorder.IUserSettings userSettings)
17
        {
12,535✔
18
            XDocument doc = UtilXml.ParseSafely(input);
12,535✔
19
            if (doc == null)
12,535✔
20
            {
60✔
21
                return null;
60✔
22
            }
23

24
            var result = new ReaderFileDecXml();
12,475✔
25
            result.doc = doc;
12,475✔
26
            result.fileIdentifier = identifier;
12,475✔
27
            result.userSettings = userSettings;
12,475✔
28
            return result;
12,475✔
29
        }
12,535✔
30

31
        public override List<ReaderDec> ParseDecs()
32
        {
12,470✔
33
            if (doc.Elements().Count() > 1)
12,470✔
34
            {
×
35
                // This isn't testable, unfortunately; XDocument doesn't even support multiple root elements.
36
                Dbg.Err($"{fileIdentifier}: Found {doc.Elements().Count()} root elements instead of the expected 1");
×
37
            }
×
38

39
            var result = new List<ReaderDec>();
12,470✔
40

41
            foreach (var rootElement in doc.Elements())
62,350✔
42
            {
12,470✔
43
                var rootContext = new InputContext(fileIdentifier, rootElement);
12,470✔
44
                if (rootElement.Name.LocalName != "Decs")
12,470✔
45
                {
20✔
46
                    Dbg.Wrn($"{rootContext}: Found root element with name `{rootElement.Name.LocalName}` when it should be `Decs`");
20✔
47
                }
20✔
48

49
                foreach (var decElement in rootElement.Elements())
130,230✔
50
                {
46,410✔
51
                    var readerDec = new ReaderDec();
46,410✔
52

53
                    readerDec.inputContext = new InputContext(fileIdentifier, decElement);
46,410✔
54
                    string typeName = decElement.Name.LocalName;
46,410✔
55

56
                    readerDec.type = UtilType.ParseDecFormatted(typeName, readerDec.inputContext);
46,410✔
57
                    if (readerDec.type == null || !typeof(Dec).IsAssignableFrom(readerDec.type))
46,410✔
58
                    {
40✔
59
                        Dbg.Err($"{readerDec.inputContext}: {typeName} is being used as a Dec but does not inherit from Dec.Dec");
40✔
60
                        continue;
40✔
61
                    }
62

63
                    var decNameAttribute = decElement.Attribute("decName");
46,370✔
64
                    if (decNameAttribute == null)
46,370✔
65
                    {
20✔
66
                        Dbg.Err($"{readerDec.inputContext}: No dec name provided, add a `decName=` attribute to the {typeName} tag (example: <{typeName} decName=\"TheNameOfYour{typeName}\">)");
20✔
67
                        continue;
20✔
68
                    }
69

70
                    readerDec.name = decNameAttribute.Value;
46,350✔
71
                    if (!UtilMisc.ValidateDecName(readerDec.name, readerDec.inputContext))
46,350✔
72
                    {
80✔
73
                        continue;
80✔
74
                    }
75

76
                    // Consume decName so we know it's not hanging around
77
                    decNameAttribute.Remove();
46,270✔
78

79
                    // Parse `class` if we can
80
                    if (decElement.Attribute("class") is var classAttribute && classAttribute != null)
46,270✔
81
                    {
70✔
82
                        var parsedClass = (Type)Serialization.ParseString(classAttribute.Value,
70✔
83
                            typeof(Type), null, readerDec.inputContext);
70✔
84

85
                        if (parsedClass == null)
70✔
86
                        {
20✔
87
                            // we have presumably already reported an error
88
                        }
20✔
89
                        else if (!readerDec.type.IsAssignableFrom(parsedClass))
50✔
90
                        {
20✔
91
                            Dbg.Err($"{readerDec.inputContext}: Attribute-parsed class {parsedClass} is not a subclass of {readerDec.type}; using the original class");
20✔
92
                        }
20✔
93
                        else
94
                        {
30✔
95
                            // yay
96
                            readerDec.type = parsedClass;
30✔
97
                        }
30✔
98

99
                        // clean up
100
                        classAttribute.Remove();
70✔
101
                    }
70✔
102

103
                    // Check to see if we're abstract
104
                    {
46,270✔
105
                        var abstractAttribute = decElement.Attribute("abstract");
46,270✔
106
                        if (abstractAttribute != null)
46,270✔
107
                        {
1,120✔
108
                            if (!bool.TryParse(abstractAttribute.Value, out bool abstrct))
1,120✔
109
                            {
20✔
110
                                Dbg.Err($"{readerDec.inputContext}: Error encountered when parsing abstract attribute");
20✔
111
                            }
20✔
112
                            readerDec.abstrct = abstrct; // little dance to deal with the fact that readerDec.abstrct is a `bool?`
1,120✔
113

114
                            abstractAttribute.Remove();
1,120✔
115
                        }
1,120✔
116
                    }
46,270✔
117

118
                    // Get our parent info
119
                    {
46,270✔
120
                        var parentAttribute = decElement.Attribute("parent");
46,270✔
121
                        if (parentAttribute != null)
46,270✔
122
                        {
1,300✔
123
                            readerDec.parent = parentAttribute.Value;
1,300✔
124

125
                            parentAttribute.Remove();
1,300✔
126
                        }
1,300✔
127
                    }
46,270✔
128

129
                    // Everything looks good!
130
                    readerDec.node = new ReaderNodeXml(decElement, fileIdentifier, userSettings);
46,270✔
131

132
                    result.Add(readerDec);
46,270✔
133
                }
46,270✔
134
            }
12,470✔
135

136
            return result;
12,470✔
137
        }
12,470✔
138
    }
139
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc