Uploaded image for project: 'Log4net'
  1. Log4net
  2. LOG4NET-360

EventLogAppender can corrupt the event log on Windows Vista and higher if the string is longer than 31839 bytes

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • 1.2.11
    • 1.2.12
    • Appenders
    • None
    • Windows Vista or higher

    Description

      Issue: EventLogAppender can corrupt the event log on Windows Vista and higher if the string is longer than 31839 bytes.

      The log4net EventLogAppender allows you to write up to 32000 bytes and there is a defect in the .NET Framework that will let you write that much data in Windows Vista and higher (which has a limit of 31839).

      See the attachment that shows "$exception

      {"The event log file is corrupted"}

      System.Exception

      {System.ComponentModel.Win32Exception}

      " along with the stack after a call to EventLog.WriteEntry() under Windows 7 that used a message string that was 31,876 bytes long.

      The issue has been reported to Microsoft as well: https://connect.microsoft.com/VisualStudio/feedback/details/770126/eventlog-writeentry-can-corrupt-the-event-log-because-of-invalid-argument-check-in-net-framework#tabs

      The code below is my workaround for determining a max message length that will not corrupt the event log. I've also written our own custom EventLogAppender that is able to work around this issue.

      private const int MaxEventLogMsgLength_PreVista = 32766;
      private const int MaxEventLogMsgLength_VistaOrHigher = 31839;

      /// <summary>
      /// Gets the maximum allowable size of event log message for the current operating system.
      /// </summary>
      /// <returns></returns>
      public static int GetMaxEventLogMessageSize()
      {
      // http://msdn.microsoft.com/en-us/library/xzwc042w(v=vs.100).aspx
      // The 32766 documented max size is two bytes shy of 32K (I'm assuming 32766 may leave space for a two byte null
      // terminator of #0#0). The 32766 max length is what the .NET 4.0 source code checks for, but this is WRONG!...
      // strings with a length > 31839 on Windows Vista or higher can CORRUPT the event log! See:
      // System.Diagnostics.EventLogInternal.InternalWriteEvent() for the use of the 32766 max size.
      var maxEventMsgSize = MaxEventLogMsgLength_PreVista;

      // Windows Vista and higher
      if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6)

      { // See ReportEvent API: http://msdn.microsoft.com/en-us/library/aa363679(VS.85).aspx // ReportEvent's lpStrings parameter: "A pointer to a buffer containing an array of null-terminated strings that are // merged into the message before Event Viewer displays the string to the user. This parameter must be a valid pointer // (or NULL), even if wNumStrings is zero. Each string is limited to 31,839 characters." // Going beyond the size of 31839 will (at some point) corrupt the event log on Windows Vista or higher! It may succeed // for a while...but you will eventually run into the error: "System.ComponentModel.Win32Exception : A device attached to // the system is not functioning", and the event log will then be corrupt (I was able to corrupt an event log using a // length of 31877 on Windows 7). // The max size for Windows Vista or higher is documented here: http://msdn.microsoft.com/en-us/library/xzwc042w(v=vs.100).aspx. // Going over this size may succeed a few times but the buffer will overrun and eventually corrupt the log (based on testing). // Log4net's own EventLogAppender will write up to 32000 bytes (0x7D00), which can corrupt the event log. // The maxEventMsgSize size is based on the max buffer size of the lpStrings parameter of the ReportEvent API. // The documented max size for EventLog.WriteEntry for Windows Vista and higher is 31839, but I'm leaving room for a // terminator of #0#0, as we cannot see the source of ReportEvent (though we could use an API monitor to examine the // buffer, given enough time). // TODO: Use an API monitor to examine how the ReportEvent API allocates a buffer for the event log message strings. const int terminatorLength = 2; // Safety for now. maxEventMsgSize = MaxEventLogMsgLength_VistaOrHigher - terminatorLength; }

      return maxEventMsgSize;
      }

      Attachments

        1. EventLogAppender.cs.patch
          4 kB
          Dominik Psenner
        2. Event Log Corruption.txt
          33 kB
          Michael Cessna

        Issue Links

          Activity

            People

              nachbarslumpi Dominik Psenner
              mcessna Michael Cessna
              Votes:
              1 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: