[
https://issues.apache.org/jira/browse/LOG4NET-360?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Michael Cessna updated LOG4NET-360:
-----------------------------------
Description:
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.
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;
}
was:
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;
}
> EventLogAppender can corrupt the event log on Windows Vista and higher if the
> string is longer than 31839 bytes
> ---------------------------------------------------------------------------------------------------------------
>
> Key: LOG4NET-360
> URL: https://issues.apache.org/jira/browse/LOG4NET-360
> Project: Log4net
> Issue Type: Bug
> Components: Appenders
> Affects Versions: 1.2.11
> Environment: Windows Vista or higher
> Reporter: Michael Cessna
> Priority: Blocker
> Attachments: Event Log Corruption.txt
>
>
> 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.
> 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;
> }
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira