You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by bo...@apache.org on 2011/09/13 12:14:43 UTC

svn commit: r1170104 - in /logging/log4net/trunk: src/Layout/Pattern/NamedPatternConverter.cs tests/src/Layout/PatternLayoutTest.cs

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