-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix event formatting with missing params (#6247)
There was a crash in the eventlogging module used in legacy Windows versions (XP and 2003 server). It is necessary to account for the case where an event contains fewer parameters than required by its format string. Closes #6234
- Loading branch information
1 parent
6fe02a4
commit a0ec41d
Showing
5 changed files
with
143 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package eventlogging | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
"unsafe" | ||
|
||
"github.com/elastic/beats/winlogbeat/sys" | ||
) | ||
|
||
const ( | ||
// MaxInsertStrings is the maximum number of strings that can be formatted by | ||
// FormatMessage API. | ||
MaxInsertStrings = 99 | ||
) | ||
|
||
var ( | ||
nullPlaceholder = []byte{'(', 0, 'n', 0, 'u', 0, 'l', 0, 'l', 0, ')', 0, 0, 0} | ||
nullPlaceholderPtr = uintptr(unsafe.Pointer(&nullPlaceholder[0])) | ||
) | ||
|
||
// StringInserts stores the string inserts for an event, as arrays of string | ||
// and pointer to UTF-16 zero-terminated string suitable to be passed to | ||
// the Windows API. The array of pointers has enough entries to ensure that | ||
// a call to FormatMessage will never crash. | ||
type StringInserts struct { | ||
pointers [MaxInsertStrings]uintptr | ||
inserts []string | ||
address uintptr | ||
} | ||
|
||
// Parse parses the insert strings from buffer which should contain | ||
// an eventLogRecord. | ||
func (b *StringInserts) Parse(record eventLogRecord, buffer []byte) error { | ||
if b.inserts == nil { // initialise struct | ||
b.inserts = make([]string, 0, MaxInsertStrings) | ||
b.address = reflect.ValueOf(&b.pointers[0]).Pointer() | ||
} | ||
b.clear() | ||
|
||
n := int(record.numStrings) | ||
if n > MaxInsertStrings { | ||
return fmt.Errorf("number of insert strings in the record (%d) is larger than the limit (%d)", n, MaxInsertStrings) | ||
} | ||
|
||
b.inserts = b.inserts[:n] | ||
if n == 0 { | ||
return nil | ||
} | ||
offset := int(record.stringOffset) | ||
bufferPtr := reflect.ValueOf(&buffer[0]).Pointer() | ||
|
||
for i := 0; i < n; i++ { | ||
if offset > len(buffer) { | ||
return fmt.Errorf("Failed reading string number %d, "+ | ||
"offset=%d, len(buffer)=%d, record=%+v", i+1, offset, | ||
len(buffer), record) | ||
} | ||
insertStr, length, err := sys.UTF16BytesToString(buffer[offset:]) | ||
if err != nil { | ||
return err | ||
} | ||
b.inserts[i] = insertStr | ||
b.pointers[i] = bufferPtr + uintptr(offset) | ||
offset += length | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Strings returns the array of strings representing the insert strings. | ||
func (b *StringInserts) Strings() []string { | ||
return b.inserts | ||
} | ||
|
||
// Pointer returns a pointer to an array of UTF-16 strings suitable to be | ||
// passed to the FormatMessage API. | ||
func (b *StringInserts) Pointer() uintptr { | ||
return b.address | ||
} | ||
|
||
func (b *StringInserts) clear() { | ||
for i := 0; i < MaxInsertStrings && b.pointers[i] != nullPlaceholderPtr; i++ { | ||
b.pointers[i] = nullPlaceholderPtr | ||
} | ||
} |