From 0b22e0caace8558692a3b3ca1057a28ad767040e Mon Sep 17 00:00:00 2001 From: Alexandre Possebom Date: Fri, 9 Oct 2026 16:03:17 -0300 Subject: [PATCH] pdh: add slack to counter array buffers for Windows Server 2012 R2 (#2630) Signed-off-by: Alexandre Possebom --- internal/pdh/collector.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/pdh/collector.go b/internal/pdh/collector.go index bfd66662..ae02bc70 100644 --- a/internal/pdh/collector.go +++ b/internal/pdh/collector.go @@ -483,6 +483,13 @@ func (c *Collector[T]) collect(dst *[]T, state *collectState) (err error) { return nil } +// pdhBufferSlack is extra space allocated beyond the buffer size reported by PDH. +// On Windows Server 2012 R2, PdhGetRawCounterArrayW reports the size of the item array of a single-instance +// object (e.g. System) without the terminator of the empty instance name, and writes that terminator right after +// the array: 48 bytes reported, 2 bytes written past them. Without the slack, the write corrupts the neighboring +// heap object and SzName points into it, which the GC reports as "found pointer to free object". +const pdhBufferSlack = 8 + // getCounterArray reads the counter array of instance into buf and returns the number of items. // ok is false if the counter has no data in this sample. func (c *Collector[T]) getCounterArray(instance pdhCounterHandle, buf *[]byte) (uint32, bool, error) { @@ -515,7 +522,7 @@ func (c *Collector[T]) getCounterArray(instance pdhCounterHandle, buf *[]byte) ( return 0, false, fmt.Errorf("%s reports buffer too small (%d), but buffer is large enough (%d): %w", name, uint32(len(*buf)), bytesNeeded, NewPdhError(ret)) } - *buf = make([]byte, bytesNeeded) + *buf = make([]byte, bytesNeeded+pdhBufferSlack) } }