diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index c6eac6b5f16..36359168f23 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -35,6 +35,8 @@ https://github.com/elastic/beats/compare/v1.2.2...1.2[Check the HEAD diff] *Winlogbeat* +- Fix panic when reading messages larger than 32K characters on Windows XP and 2003. {pull}1498[1498] + ==== Added *Affecting all Beats* diff --git a/winlogbeat/sys/eventlogging/eventlogging_windows.go b/winlogbeat/sys/eventlogging/eventlogging_windows.go index 11f8c90145a..322ff04e9c0 100644 --- a/winlogbeat/sys/eventlogging/eventlogging_windows.go +++ b/winlogbeat/sys/eventlogging/eventlogging_windows.go @@ -132,8 +132,8 @@ func RenderEvents( } event.MessageInserts = stringInserts - // Format the parameterized message using the insert strings. - event.Message, _, err = formatMessage(record.sourceName, + // Format the parametrized message using the insert strings. + event.Message, err = formatMessage(record.sourceName, record.eventID, lang, stringInsertPtrs, buffer, pubHandleProvider) event.MessageErr = err @@ -154,6 +154,8 @@ func unixTime(sec uint32) *time.Time { return &t } +// formatMessage takes event data and formats the event message into a +// normalized format. func formatMessage( sourceName string, eventID uint32, @@ -161,7 +163,7 @@ func formatMessage( stringInserts []uintptr, buffer []byte, pubHandleProvider func(string) MessageFiles, -) (string, int, error) { +) (string, error) { var addr uintptr if len(stringInserts) > 0 { addr = reflect.ValueOf(&stringInserts[0]).Pointer() @@ -184,20 +186,28 @@ func formatMessage( Handle(fh.Handle), eventID, lang, - &buffer[0], - uint32(len(buffer)), + &buffer[0], // Max size allowed is 64k bytes. + uint32(len(buffer)/2), // Size of buffer in TCHARS addr) + // bufferUsed = numChars * sizeof(TCHAR) + sizeof(null-terminator) + bufferUsed := int(numChars*2 + 2) if err == syscall.ERROR_INSUFFICIENT_BUFFER { - return "", int(numChars), err + return "", err } if err != nil { lastErr = err continue } - message, _, err = UTF16BytesToString(buffer[:numChars*2]) + if bufferUsed > len(buffer) { + return "", fmt.Errorf("Windows FormatMessage reported that "+ + "message contains %d characters plus a null-terminator "+ + "(%d bytes), but the buffer can only hold %d bytes", + numChars, bufferUsed, len(buffer)) + } + message, _, err = UTF16BytesToString(buffer[:bufferUsed]) if err != nil { - return "", 0, err + return "", err } message = RemoveWindowsLineEndings(message) @@ -206,16 +216,16 @@ func formatMessage( if message == "" { switch lastErr { case nil: - return "", 0, messageFiles.Err + return "", messageFiles.Err case ERROR_MR_MID_NOT_FOUND: - return "", 0, fmt.Errorf("The system cannot find message text for "+ + return "", fmt.Errorf("The system cannot find message text for "+ "message number %d in the message file for %s.", eventID, fh.File) default: - return "", 0, fh.Err + return "", fh.Err } } - return message, 0, nil + return message, nil } // parseEventLogRecord parses a single Windows EVENTLOGRECORD struct from the