diff options
author | Oren Hurvitz | 2015-07-05 16:05:01 +0300 |
---|---|---|
committer | Oren Hurvitz | 2015-08-11 07:35:37 +0100 |
commit | 4ad1468165b80f67439399e36688d36944996312 (patch) | |
tree | 541cfb87ecae92a3bff53aaa8875b06d83878a35 /OpenSim | |
parent | Fixed mistakes in string format specifiers (e.g., "{0)" instead of {0}") (diff) | |
download | opensim-SC_OLD-4ad1468165b80f67439399e36688d36944996312.zip opensim-SC_OLD-4ad1468165b80f67439399e36688d36944996312.tar.gz opensim-SC_OLD-4ad1468165b80f67439399e36688d36944996312.tar.bz2 opensim-SC_OLD-4ad1468165b80f67439399e36688d36944996312.tar.xz |
Better handling of invalid XML: a) prevent infinite loop on EOF; b) better logging
If the XML was truncated for some reason then ExecuteReadProcessors() would get into an infinite loop, using high CPU. Now it detects EOF (and several other error cases) and aborts.
The rest of the changes just improve logging of XML in case of errors, so that we can see what the bad XML is.
Diffstat (limited to '')
5 files changed, 115 insertions, 69 deletions
diff --git a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs index 1254086..55640ac 100644 --- a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs +++ b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Diagnostics; | ||
30 | using System.IO; | 31 | using System.IO; |
31 | using System.Reflection; | 32 | using System.Reflection; |
32 | using System.Xml; | 33 | using System.Xml; |
@@ -47,7 +48,7 @@ namespace OpenSim.Framework.Serialization.External | |||
47 | /// Populate a node with data read from xml using a dictinoary of processors | 48 | /// Populate a node with data read from xml using a dictinoary of processors |
48 | /// </summary> | 49 | /// </summary> |
49 | /// <param name="nodeToFill"></param> | 50 | /// <param name="nodeToFill"></param> |
50 | /// <param name="processors">/param> | 51 | /// <param name="processors"></param> |
51 | /// <param name="xtr"></param> | 52 | /// <param name="xtr"></param> |
52 | /// <returns>true on successful, false if there were any processing failures</returns> | 53 | /// <returns>true on successful, false if there were any processing failures</returns> |
53 | public static bool ExecuteReadProcessors<NodeType>( | 54 | public static bool ExecuteReadProcessors<NodeType>( |
@@ -57,10 +58,10 @@ namespace OpenSim.Framework.Serialization.External | |||
57 | nodeToFill, | 58 | nodeToFill, |
58 | processors, | 59 | processors, |
59 | xtr, | 60 | xtr, |
60 | (o, name, e) | 61 | (o, nodeName, e) => { |
61 | => m_log.DebugFormat( | 62 | m_log.Debug(string.Format("[ExternalRepresentationUtils]: Error while parsing element {0} ", |
62 | "[ExternalRepresentationUtils]: Exception while parsing element {0}, continuing. Exception {1}{2}", | 63 | nodeName), e); |
63 | name, e.Message, e.StackTrace)); | 64 | }); |
64 | } | 65 | } |
65 | 66 | ||
66 | /// <summary> | 67 | /// <summary> |
@@ -80,18 +81,22 @@ namespace OpenSim.Framework.Serialization.External | |||
80 | Action<NodeType, string, Exception> parseExceptionAction) | 81 | Action<NodeType, string, Exception> parseExceptionAction) |
81 | { | 82 | { |
82 | bool errors = false; | 83 | bool errors = false; |
84 | int numErrors = 0; | ||
85 | |||
86 | Stopwatch timer = new Stopwatch(); | ||
87 | timer.Start(); | ||
83 | 88 | ||
84 | string nodeName = string.Empty; | 89 | string nodeName = string.Empty; |
85 | while (xtr.NodeType != XmlNodeType.EndElement) | 90 | while (xtr.NodeType != XmlNodeType.EndElement) |
86 | { | 91 | { |
87 | nodeName = xtr.Name; | 92 | nodeName = xtr.Name; |
88 | 93 | ||
89 | // m_log.DebugFormat("[ExternalRepresentationUtils]: Processing: {0}", nodeName); | 94 | // m_log.DebugFormat("[ExternalRepresentationUtils]: Processing node: {0}", nodeName); |
90 | 95 | ||
91 | Action<NodeType, XmlReader> p = null; | 96 | Action<NodeType, XmlReader> p = null; |
92 | if (processors.TryGetValue(xtr.Name, out p)) | 97 | if (processors.TryGetValue(xtr.Name, out p)) |
93 | { | 98 | { |
94 | // m_log.DebugFormat("[ExternalRepresentationUtils]: Found {0} processor, nodeName); | 99 | // m_log.DebugFormat("[ExternalRepresentationUtils]: Found processor for {0}", nodeName); |
95 | 100 | ||
96 | try | 101 | try |
97 | { | 102 | { |
@@ -101,6 +106,18 @@ namespace OpenSim.Framework.Serialization.External | |||
101 | { | 106 | { |
102 | errors = true; | 107 | errors = true; |
103 | parseExceptionAction(nodeToFill, nodeName, e); | 108 | parseExceptionAction(nodeToFill, nodeName, e); |
109 | |||
110 | if (xtr.EOF) | ||
111 | { | ||
112 | m_log.Debug("[ExternalRepresentationUtils]: Aborting ExecuteReadProcessors due to unexpected end of XML"); | ||
113 | break; | ||
114 | } | ||
115 | |||
116 | if (++numErrors == 10) | ||
117 | { | ||
118 | m_log.Debug("[ExternalRepresentationUtils]: Aborting ExecuteReadProcessors due to too many parsing errors"); | ||
119 | break; | ||
120 | } | ||
104 | 121 | ||
105 | if (xtr.NodeType == XmlNodeType.EndElement) | 122 | if (xtr.NodeType == XmlNodeType.EndElement) |
106 | xtr.Read(); | 123 | xtr.Read(); |
@@ -108,9 +125,16 @@ namespace OpenSim.Framework.Serialization.External | |||
108 | } | 125 | } |
109 | else | 126 | else |
110 | { | 127 | { |
111 | // m_log.DebugFormat("[LandDataSerializer]: caught unknown element {0}", nodeName); | 128 | // m_log.DebugFormat("[ExternalRepresentationUtils]: found unknown element \"{0}\"", nodeName); |
112 | xtr.ReadOuterXml(); // ignore | 129 | xtr.ReadOuterXml(); // ignore |
113 | } | 130 | } |
131 | |||
132 | if (timer.Elapsed.TotalSeconds >= 60) | ||
133 | { | ||
134 | m_log.Debug("[ExternalRepresentationUtils]: Aborting ExecuteReadProcessors due to timeout"); | ||
135 | errors = true; | ||
136 | break; | ||
137 | } | ||
114 | } | 138 | } |
115 | 139 | ||
116 | return errors; | 140 | return errors; |
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 875f4ad..a5f798d 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs | |||
@@ -2910,6 +2910,16 @@ namespace OpenSim.Framework | |||
2910 | 2910 | ||
2911 | return name; | 2911 | return name; |
2912 | } | 2912 | } |
2913 | |||
2914 | public static void LogFailedXML(string message, string xml) | ||
2915 | { | ||
2916 | int length = xml.Length; | ||
2917 | if (length > 2000) | ||
2918 | xml = xml.Substring(0, 2000) + "..."; | ||
2919 | |||
2920 | m_log.ErrorFormat("{0} Failed XML ({1} bytes) = {2}", message, length, xml); | ||
2921 | } | ||
2922 | |||
2913 | } | 2923 | } |
2914 | 2924 | ||
2915 | public class DoubleQueue<T> where T:class | 2925 | public class DoubleQueue<T> where T:class |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index ac27716..b838177 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | |||
@@ -2243,13 +2243,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
2243 | 2243 | ||
2244 | if (isSingleObject || isAttachment) | 2244 | if (isSingleObject || isAttachment) |
2245 | { | 2245 | { |
2246 | SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(reader); | 2246 | SceneObjectGroup g; |
2247 | try | ||
2248 | { | ||
2249 | g = SceneObjectSerializer.FromOriginalXmlFormat(reader); | ||
2250 | } | ||
2251 | catch (Exception e) | ||
2252 | { | ||
2253 | m_log.Error("[AGENT INVENTORY]: Deserialization of xml failed ", e); | ||
2254 | Util.LogFailedXML("[AGENT INVENTORY]:", xmlData); | ||
2255 | g = null; | ||
2256 | } | ||
2257 | |||
2247 | if (g != null) | 2258 | if (g != null) |
2248 | { | 2259 | { |
2249 | objlist.Add(g); | 2260 | objlist.Add(g); |
2250 | veclist.Add(Vector3.Zero); | 2261 | veclist.Add(Vector3.Zero); |
2251 | bbox = g.GetAxisAlignedBoundingBox(out offsetHeight); | 2262 | bbox = g.GetAxisAlignedBoundingBox(out offsetHeight); |
2252 | } | 2263 | } |
2264 | |||
2253 | return true; | 2265 | return true; |
2254 | } | 2266 | } |
2255 | else | 2267 | else |
@@ -2291,9 +2303,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2291 | } | 2303 | } |
2292 | catch (Exception e) | 2304 | catch (Exception e) |
2293 | { | 2305 | { |
2294 | m_log.Error( | 2306 | m_log.Error("[AGENT INVENTORY]: Deserialization of xml failed when looking for CoalescedObject tag ", e); |
2295 | "[AGENT INVENTORY]: Deserialization of xml failed when looking for CoalescedObject tag. Exception ", | 2307 | Util.LogFailedXML("[AGENT INVENTORY]:", xmlData); |
2296 | e); | ||
2297 | } | 2308 | } |
2298 | 2309 | ||
2299 | return true; | 2310 | return true; |
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs index a556f9d..998789d 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs | |||
@@ -178,10 +178,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
178 | } | 178 | } |
179 | catch (Exception e) | 179 | catch (Exception e) |
180 | { | 180 | { |
181 | m_log.Error(string.Format( | 181 | m_log.Error("[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml failed ", e); |
182 | "[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml failed with {0} ", | 182 | Util.LogFailedXML("[COALESCED SCENE OBJECTS SERIALIZER]:", xml); |
183 | e.Message), e); | ||
184 | |||
185 | return false; | 183 | return false; |
186 | } | 184 | } |
187 | 185 | ||
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 463ef22..4caa9cb 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs | |||
@@ -62,8 +62,20 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
62 | { | 62 | { |
63 | String fixedData = ExternalRepresentationUtils.SanitizeXml(xmlData); | 63 | String fixedData = ExternalRepresentationUtils.SanitizeXml(xmlData); |
64 | using (XmlTextReader wrappedReader = new XmlTextReader(fixedData, XmlNodeType.Element, null)) | 64 | using (XmlTextReader wrappedReader = new XmlTextReader(fixedData, XmlNodeType.Element, null)) |
65 | { | ||
65 | using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment })) | 66 | using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment })) |
66 | return FromOriginalXmlFormat(reader); | 67 | { |
68 | try { | ||
69 | return FromOriginalXmlFormat(reader); | ||
70 | } | ||
71 | catch (Exception e) | ||
72 | { | ||
73 | m_log.Error("[SERIALIZER]: Deserialization of xml failed ", e); | ||
74 | Util.LogFailedXML("[SERIALIZER]:", fixedData); | ||
75 | return null; | ||
76 | } | ||
77 | } | ||
78 | } | ||
67 | } | 79 | } |
68 | 80 | ||
69 | /// <summary> | 81 | /// <summary> |
@@ -76,43 +88,33 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
76 | //m_log.DebugFormat("[SOG]: Starting deserialization of SOG"); | 88 | //m_log.DebugFormat("[SOG]: Starting deserialization of SOG"); |
77 | //int time = System.Environment.TickCount; | 89 | //int time = System.Environment.TickCount; |
78 | 90 | ||
79 | SceneObjectGroup sceneObject = null; | 91 | int linkNum; |
80 | 92 | ||
81 | try | 93 | reader.ReadToFollowing("RootPart"); |
82 | { | 94 | reader.ReadToFollowing("SceneObjectPart"); |
83 | int linkNum; | 95 | SceneObjectGroup sceneObject = new SceneObjectGroup(SceneObjectPart.FromXml(reader)); |
96 | reader.ReadToFollowing("OtherParts"); | ||
84 | 97 | ||
85 | reader.ReadToFollowing("RootPart"); | 98 | if (reader.ReadToDescendant("Part")) |
86 | reader.ReadToFollowing("SceneObjectPart"); | 99 | { |
87 | sceneObject = new SceneObjectGroup(SceneObjectPart.FromXml(reader)); | 100 | do |
88 | reader.ReadToFollowing("OtherParts"); | ||
89 | |||
90 | if (reader.ReadToDescendant("Part")) | ||
91 | { | 101 | { |
92 | do | 102 | if (reader.ReadToDescendant("SceneObjectPart")) |
93 | { | 103 | { |
94 | if (reader.ReadToDescendant("SceneObjectPart")) | 104 | SceneObjectPart part = SceneObjectPart.FromXml(reader); |
95 | { | 105 | linkNum = part.LinkNum; |
96 | SceneObjectPart part = SceneObjectPart.FromXml(reader); | 106 | sceneObject.AddPart(part); |
97 | linkNum = part.LinkNum; | 107 | part.LinkNum = linkNum; |
98 | sceneObject.AddPart(part); | 108 | part.TrimPermissions(); |
99 | part.LinkNum = linkNum; | 109 | } |
100 | part.TrimPermissions(); | 110 | } |
101 | } | 111 | while (reader.ReadToNextSibling("Part")); |
102 | } | ||
103 | while (reader.ReadToNextSibling("Part")); | ||
104 | } | ||
105 | |||
106 | // Script state may, or may not, exist. Not having any, is NOT | ||
107 | // ever a problem. | ||
108 | sceneObject.LoadScriptState(reader); | ||
109 | } | ||
110 | catch (Exception e) | ||
111 | { | ||
112 | m_log.ErrorFormat("[SERIALIZER]: Deserialization of xml failed. Exception {0}", e); | ||
113 | return null; | ||
114 | } | 112 | } |
115 | 113 | ||
114 | // Script state may, or may not, exist. Not having any, is NOT | ||
115 | // ever a problem. | ||
116 | sceneObject.LoadScriptState(reader); | ||
117 | |||
116 | return sceneObject; | 118 | return sceneObject; |
117 | } | 119 | } |
118 | 120 | ||
@@ -236,7 +238,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
236 | 238 | ||
237 | if (parts.Count == 0) | 239 | if (parts.Count == 0) |
238 | { | 240 | { |
239 | m_log.ErrorFormat("[SERIALIZER]: Deserialization of xml failed: No SceneObjectPart nodes. xml was " + xmlData); | 241 | m_log.Error("[SERIALIZER]: Deserialization of xml failed: No SceneObjectPart nodes"); |
242 | Util.LogFailedXML("[SERIALIZER]:", xmlData); | ||
240 | return null; | 243 | return null; |
241 | } | 244 | } |
242 | 245 | ||
@@ -280,7 +283,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
280 | } | 283 | } |
281 | catch (Exception e) | 284 | catch (Exception e) |
282 | { | 285 | { |
283 | m_log.ErrorFormat("[SERIALIZER]: Deserialization of xml failed with {0}. xml was {1}", e, xmlData); | 286 | m_log.Error("[SERIALIZER]: Deserialization of xml failed ", e); |
287 | Util.LogFailedXML("[SERIALIZER]:", xmlData); | ||
284 | return null; | 288 | return null; |
285 | } | 289 | } |
286 | } | 290 | } |
@@ -708,7 +712,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
708 | private static void ProcessShape(SceneObjectPart obj, XmlReader reader) | 712 | private static void ProcessShape(SceneObjectPart obj, XmlReader reader) |
709 | { | 713 | { |
710 | List<string> errorNodeNames; | 714 | List<string> errorNodeNames; |
711 | obj.Shape = ReadShape(reader, "Shape", out errorNodeNames); | 715 | obj.Shape = ReadShape(reader, "Shape", out errorNodeNames, obj); |
712 | 716 | ||
713 | if (errorNodeNames != null) | 717 | if (errorNodeNames != null) |
714 | { | 718 | { |
@@ -1599,18 +1603,21 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1599 | 1603 | ||
1600 | reader.ReadStartElement("SceneObjectPart"); | 1604 | reader.ReadStartElement("SceneObjectPart"); |
1601 | 1605 | ||
1602 | ExternalRepresentationUtils.ExecuteReadProcessors( | 1606 | bool errors = ExternalRepresentationUtils.ExecuteReadProcessors( |
1603 | obj, | 1607 | obj, |
1604 | m_SOPXmlProcessors, | 1608 | m_SOPXmlProcessors, |
1605 | reader, | 1609 | reader, |
1606 | (o, nodeName, e) | 1610 | (o, nodeName, e) => { |
1607 | => m_log.DebugFormat( | 1611 | m_log.Debug(string.Format("[SceneObjectSerializer]: Error while parsing element {0} in object {1} {2} ", |
1608 | "[SceneObjectSerializer]: Exception while parsing {0} in object {1} {2}: {3}{4}", | 1612 | nodeName, ((SceneObjectPart)o).Name, ((SceneObjectPart)o).UUID), e); |
1609 | ((SceneObjectPart)o).Name, ((SceneObjectPart)o).UUID, nodeName, e.Message, e.StackTrace)); | 1613 | }); |
1614 | |||
1615 | if (errors) | ||
1616 | throw new XmlException(string.Format("Error parsing object {0} {1}", obj.Name, obj.UUID)); | ||
1610 | 1617 | ||
1611 | reader.ReadEndElement(); // SceneObjectPart | 1618 | reader.ReadEndElement(); // SceneObjectPart |
1612 | 1619 | ||
1613 | //m_log.DebugFormat("[XXX]: parsed SOP {0} - {1}", obj.Name, obj.UUID); | 1620 | // m_log.DebugFormat("[SceneObjectSerializer]: parsed SOP {0} {1}", obj.Name, obj.UUID); |
1614 | return obj; | 1621 | return obj; |
1615 | } | 1622 | } |
1616 | 1623 | ||
@@ -1655,7 +1662,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1655 | /// <param name="name">The name of the xml element containing the shape</param> | 1662 | /// <param name="name">The name of the xml element containing the shape</param> |
1656 | /// <param name="errors">a list containing the failing node names. If no failures then null.</param> | 1663 | /// <param name="errors">a list containing the failing node names. If no failures then null.</param> |
1657 | /// <returns>The shape parsed</returns> | 1664 | /// <returns>The shape parsed</returns> |
1658 | public static PrimitiveBaseShape ReadShape(XmlReader reader, string name, out List<string> errorNodeNames) | 1665 | public static PrimitiveBaseShape ReadShape(XmlReader reader, string name, out List<string> errorNodeNames, SceneObjectPart obj) |
1659 | { | 1666 | { |
1660 | List<string> internalErrorNodeNames = null; | 1667 | List<string> internalErrorNodeNames = null; |
1661 | 1668 | ||
@@ -1674,18 +1681,14 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1674 | shape, | 1681 | shape, |
1675 | m_ShapeXmlProcessors, | 1682 | m_ShapeXmlProcessors, |
1676 | reader, | 1683 | reader, |
1677 | (o, nodeName, e) | 1684 | (o, nodeName, e) => { |
1678 | => | 1685 | m_log.Debug(string.Format("[SceneObjectSerializer]: Error while parsing element {0} in Shape property of object {1} {2} ", |
1679 | { | 1686 | nodeName, obj.Name, obj.UUID), e); |
1680 | // m_log.DebugFormat( | ||
1681 | // "[SceneObjectSerializer]: Exception while parsing Shape property {0}: {1}{2}", | ||
1682 | // nodeName, e.Message, e.StackTrace); | ||
1683 | if (internalErrorNodeNames == null) | ||
1684 | internalErrorNodeNames = new List<string>(); | ||
1685 | 1687 | ||
1686 | internalErrorNodeNames.Add(nodeName); | 1688 | if (internalErrorNodeNames == null) |
1687 | } | 1689 | internalErrorNodeNames = new List<string>(); |
1688 | ); | 1690 | internalErrorNodeNames.Add(nodeName); |
1691 | }); | ||
1689 | 1692 | ||
1690 | reader.ReadEndElement(); // Shape | 1693 | reader.ReadEndElement(); // Shape |
1691 | 1694 | ||