Author: bodewig
Date: Tue Sep 13 10:14:42 2011
New Revision: 1170104

URL: http://svn.apache.org/viewvc?rev=1170104&view=rev
Log:
fix bounds-checks in NamedPatternConverter.  LOG4NET-215

Modified:
    logging/log4net/trunk/src/Layout/Pattern/NamedPatternConverter.cs
    logging/log4net/trunk/tests/src/Layout/PatternLayoutTest.cs

Modified: logging/log4net/trunk/src/Layout/Pattern/NamedPatternConverter.cs
URL: 
http://svn.apache.org/viewvc/logging/log4net/trunk/src/Layout/Pattern/NamedPatternConverter.cs?rev=1170104&r1=1170103&r2=1170104&view=diff
==============================================================================
--- logging/log4net/trunk/src/Layout/Pattern/NamedPatternConverter.cs (original)
+++ logging/log4net/trunk/src/Layout/Pattern/NamedPatternConverter.cs Tue Sep 
13 10:14:42 2011
@@ -42,9 +42,9 @@ namespace log4net.Layout.Pattern
        /// </para>
        /// </remarks>
        /// <author>Nicko Cadell</author>
-       internal abstract class NamedPatternConverter : PatternLayoutConverter, 
IOptionHandler
+       public abstract class NamedPatternConverter : PatternLayoutConverter, 
IOptionHandler
        {
-               protected int m_precision = 0;
+               private int m_precision = 0;
 
                #region Implementation of IOptionHandler
 
@@ -120,31 +120,37 @@ namespace log4net.Layout.Pattern
                /// Render the <see cref="GetFullyQualifiedName"/> to the 
precision
                /// specified by the <see cref="PatternConverter.Option"/> 
property.
                /// </remarks>
-               override protected void Convert(TextWriter writer, LoggingEvent 
loggingEvent)
+               sealed override protected void Convert(TextWriter writer, 
LoggingEvent loggingEvent)
                {
                        string name = GetFullyQualifiedName(loggingEvent);
-                       if (m_precision <= 0)
+                       if (m_precision <= 0 || name == null || name.Length < 2)
                        {
                                writer.Write(name);
                        }
                        else 
                        {
                                int len = name.Length;
+                string trailingDot = string.Empty;
+                if (name.EndsWith(DOT))
+                {
+                    trailingDot = DOT;
+                    name = name.Substring(0, len - 1);
+                    len--;
+                }
 
-                               // We subtract 1 from 'len' when assigning to 
'end' to avoid out of
-                               // bounds exception in return 
name.Substring(end+1, len). This can happen if
-                               // precision is 1 and the logger name ends with 
a dot. 
-                               int end = len - 1;
-                               for(int i=m_precision; i>0; i--) 
-                               {         
-                                       end = name.LastIndexOf('.', end-1);
-                                       if (end == -1)
-                                       {
-                                               writer.Write(name);
-                                               return;
-                                       }
-                               }
-                               writer.Write(name.Substring(end+1, len-end-1));
+                int end = name.LastIndexOf(DOT);
+                               for(int i = 1; end > 0 && i < m_precision; i++) 
+                               {
+                    end = name.LastIndexOf('.', end - 1);
+                }
+                if (end == -1)
+                {
+                    writer.Write(name + trailingDot);
+                }
+                else
+                {
+                    writer.Write(name.Substring(end + 1, len - end - 1) + 
trailingDot);
+                }
                        }         
                }
 
@@ -159,6 +165,7 @@ namespace log4net.Layout.Pattern
            /// </remarks>
            private readonly static Type declaringType = 
typeof(NamedPatternConverter);
 
+        private const string DOT = ".";
            #endregion Private Static Fields
        }
 }

Modified: logging/log4net/trunk/tests/src/Layout/PatternLayoutTest.cs
URL: 
http://svn.apache.org/viewvc/logging/log4net/trunk/tests/src/Layout/PatternLayoutTest.cs?rev=1170104&r1=1170103&r2=1170104&view=diff
==============================================================================
--- logging/log4net/trunk/tests/src/Layout/PatternLayoutTest.cs (original)
+++ logging/log4net/trunk/tests/src/Layout/PatternLayoutTest.cs Tue Sep 13 
10:14:42 2011
@@ -33,10 +33,10 @@ using NUnit.Framework;
 namespace log4net.Tests.Layout
 {
        /// <summary>
-       /// Used for internal unit testing the <see cref="PatternLayoutTest"/> 
class.
+       /// Used for internal unit testing the <see cref="PatternLayout"/> 
class.
        /// </summary>
        /// <remarks>
-       /// Used for internal unit testing the <see cref="PatternLayoutTest"/> 
class.
+       /// Used for internal unit testing the <see cref="PatternLayout"/> 
class.
        /// </remarks>
        [TestFixture]
        public class PatternLayoutTest
@@ -145,7 +145,147 @@ namespace log4net.Tests.Layout
                        stringAppender.Reset();
                }
 
-               /// <summary>
+        [Test]
+        public void NamedPatternConverterWithoutPrecisionShouldReturnFullName()
+        {
+            StringAppender stringAppender = new StringAppender();
+            PatternLayout layout = new PatternLayout();
+            layout.AddConverter("message-as-name", 
typeof(MessageAsNamePatternConverter));
+            layout.ConversionPattern = "%message-as-name";
+            layout.ActivateOptions();
+            stringAppender.Layout = layout;
+            ILoggerRepository rep = 
LogManager.CreateRepository(Guid.NewGuid().ToString());
+            BasicConfigurator.Configure(rep, stringAppender);
+            ILog log1 = LogManager.GetLogger(rep.Name, 
"TestAddingCustomPattern");
+
+            log1.Info("NoDots");
+            Assert.AreEqual("NoDots", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info("One.Dot");
+            Assert.AreEqual("One.Dot", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info("Tw.o.Dots");
+            Assert.AreEqual("Tw.o.Dots", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info("TrailingDot.");
+            Assert.AreEqual("TrailingDot.", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info(".LeadingDot");
+            Assert.AreEqual(".LeadingDot", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            // empty string and other evil combinations as tests for of-by-one 
mistakes in index calculations
+            log1.Info(string.Empty);
+            Assert.AreEqual(string.Empty, stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info(".");
+            Assert.AreEqual(".", stringAppender.GetString(), "%message-as-name 
not registered");
+            stringAppender.Reset();
+
+            log1.Info("x");
+            Assert.AreEqual("x", stringAppender.GetString(), "%message-as-name 
not registered");
+            stringAppender.Reset();
+        }
+
+        [Test]
+        public void 
NamedPatternConverterWithPrecision1ShouldStripLeadingStuffIfPresent()
+        {
+            StringAppender stringAppender = new StringAppender();
+            PatternLayout layout = new PatternLayout();
+            layout.AddConverter("message-as-name", 
typeof(MessageAsNamePatternConverter));
+            layout.ConversionPattern = "%message-as-name{1}";
+            layout.ActivateOptions();
+            stringAppender.Layout = layout;
+            ILoggerRepository rep = 
LogManager.CreateRepository(Guid.NewGuid().ToString());
+            BasicConfigurator.Configure(rep, stringAppender);
+            ILog log1 = LogManager.GetLogger(rep.Name, 
"TestAddingCustomPattern");
+
+            log1.Info("NoDots");
+            Assert.AreEqual("NoDots", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info("One.Dot");
+            Assert.AreEqual("Dot", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info("Tw.o.Dots");
+            Assert.AreEqual("Dots", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info("TrailingDot.");
+            Assert.AreEqual("TrailingDot.", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info(".LeadingDot");
+            Assert.AreEqual("LeadingDot", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            // empty string and other evil combinations as tests for of-by-one 
mistakes in index calculations
+            log1.Info(string.Empty);
+            Assert.AreEqual(string.Empty, stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info("x");
+            Assert.AreEqual("x", stringAppender.GetString(), "%message-as-name 
not registered");
+            stringAppender.Reset();
+
+            log1.Info(".");
+            Assert.AreEqual(".", stringAppender.GetString(), "%message-as-name 
not registered");
+            stringAppender.Reset();
+        }
+
+        [Test]
+        public void 
NamedPatternConverterWithPrecision2ShouldStripLessLeadingStuffIfPresent() {
+            StringAppender stringAppender = new StringAppender();
+            PatternLayout layout = new PatternLayout();
+            layout.AddConverter("message-as-name", 
typeof(MessageAsNamePatternConverter));
+            layout.ConversionPattern = "%message-as-name{2}";
+            layout.ActivateOptions();
+            stringAppender.Layout = layout;
+            ILoggerRepository rep = 
LogManager.CreateRepository(Guid.NewGuid().ToString());
+            BasicConfigurator.Configure(rep, stringAppender);
+            ILog log1 = LogManager.GetLogger(rep.Name, 
"TestAddingCustomPattern");
+
+            log1.Info("NoDots");
+            Assert.AreEqual("NoDots", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info("One.Dot");
+            Assert.AreEqual("One.Dot", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info("Tw.o.Dots");
+            Assert.AreEqual("o.Dots", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info("TrailingDot.");
+            Assert.AreEqual("TrailingDot.", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info(".LeadingDot");
+            Assert.AreEqual("LeadingDot", stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            // empty string and other evil combinations as tests for of-by-one 
mistakes in index calculations
+            log1.Info(string.Empty);
+            Assert.AreEqual(string.Empty, stringAppender.GetString(), 
"%message-as-name not registered");
+            stringAppender.Reset();
+
+            log1.Info("x");
+            Assert.AreEqual("x", stringAppender.GetString(), "%message-as-name 
not registered");
+            stringAppender.Reset();
+
+            log1.Info(".");
+            Assert.AreEqual(".", stringAppender.GetString(), "%message-as-name 
not registered");
+            stringAppender.Reset();
+        }
+
+        /// <summary>
                /// Converter to include event message
                /// </summary>
                private class TestMessagePatternConverter : 
PatternLayoutConverter
@@ -181,5 +321,13 @@ namespace log4net.Tests.Layout
 
                        stringAppender.Reset();
                }
-       }
+
+        private class MessageAsNamePatternConverter : NamedPatternConverter
+        {
+            protected override string GetFullyQualifiedName(LoggingEvent 
loggingEvent)
+            {
+                return loggingEvent.MessageObject.ToString();
+            }
+        }
+    }
 }
\ No newline at end of file


Reply via email to