Skip to content

Commit 8138537

Browse files
committed
fix crash in check_pdh
filled buffer must use the actual sizeOf to be large enough.
1 parent 33a5855 commit 8138537

File tree

11 files changed

+41
-33
lines changed

11 files changed

+41
-33
lines changed

Changes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ This file documents the revision history for the SNClient agent.
33
next:
44
- change showing performance data in check_files and check_services (#243)
55
- kill orphanded managed exporters which might block listen ports
6+
- fix crash in check_pdh
67

78
0.34 Wed May 28 13:56:57 CEST 2025
89
- add /api/v1/admin/csr endpoint to create csr

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/consol-monitoring/snclient
22

3-
go 1.23.8
3+
go 1.23.10
44

55
require (
66
github.com/beevik/ntp v1.4.3
@@ -9,6 +9,7 @@ require (
99
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
1010
github.com/go-chi/chi/v5 v5.2.1
1111
github.com/go-ole/go-ole v1.3.0
12+
github.com/goccy/go-json v0.10.5
1213
github.com/kdar/factorlog v0.0.0-20211012144011-6ea75a169038
1314
github.com/mackerelio/checkers v0.2.0
1415
github.com/miekg/dns v1.1.66

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hH
2626
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
2727
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
2828
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
29+
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
30+
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
2931
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
3032
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
3133
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=

pkg/snclient/check_omd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package snclient
33
import (
44
"bytes"
55
"context"
6-
"encoding/json"
76
"errors"
87
"fmt"
98
"io"
@@ -15,6 +14,7 @@ import (
1514
"time"
1615

1716
"github.com/consol-monitoring/snclient/pkg/convert"
17+
"github.com/goccy/go-json"
1818
)
1919

2020
func init() {

pkg/snclient/check_pdh_windows.go

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ import (
77
"strconv"
88
"strings"
99
"time"
10+
"unsafe"
1011

1112
"github.com/consol-monitoring/snclient/pkg/pdh"
1213
"golang.org/x/sys/windows"
1314
)
1415

16+
const querySleepDuration = 500 * time.Millisecond
17+
1518
type PdhValue struct {
1619
CounterInstance string
1720
Value int64
@@ -29,12 +32,11 @@ func (c *CheckPDH) check(_ context.Context, _ *Agent, check *CheckData, args []A
2932
var possiblePaths []string
3033
var hQuery pdh.PDH_HQUERY
3134
// Open Query - Data Source = 0 => Real Time Datasource
32-
ret := pdh.PdhOpenQuery(uintptr(0), uintptr(0), &hQuery)
33-
defer pdh.PdhCloseQuery(hQuery)
34-
35+
ret := pdh.PdhOpenQuery(0, 0, &hQuery)
3536
if ret != pdh.ERROR_SUCCESS {
3637
return nil, fmt.Errorf("could not open query, something is wrong with the countername")
3738
}
39+
defer pdh.PdhCloseQuery(hQuery)
3840

3941
tmpPath := c.CounterPath
4042
if c.EnglishFallBackNames {
@@ -168,7 +170,7 @@ func collectQueryData(hQuery *pdh.PDH_HQUERY) uint32 {
168170
return ret
169171
}
170172
// PDH requires a double collection with a second wait between the calls See MSDN
171-
time.Sleep(time.Duration(1))
173+
time.Sleep(querySleepDuration)
172174
ret = pdh.PdhCollectQueryData(*hQuery)
173175

174176
return ret
@@ -180,26 +182,24 @@ func collectQueryData(hQuery *pdh.PDH_HQUERY) uint32 {
180182
- if More Data -> Create Actual Array and fill
181183
*/
182184
func collectLargeValuesArray(hCounter pdh.PDH_HCOUNTER, hQuery pdh.PDH_HQUERY) (values []PdhValue, apiResponseCode uint32) {
183-
var resArr [1]pdh.PDH_FMT_COUNTERVALUE_ITEM_LARGE // Need at least one nil pointer
184-
var ret uint32
185-
var filledBuf []pdh.PDH_FMT_COUNTERVALUE_ITEM_LARGE
186-
size := uint32(0)
187-
bufferCount := uint32(0)
185+
var bufCount uint32
186+
var bufSize uint32
187+
size := uint32(unsafe.Sizeof(pdh.PDH_FMT_COUNTERVALUE_ITEM_LARGE{}))
188+
var emptyBuf [1]pdh.PDH_FMT_COUNTERVALUE_ITEM_LARGE // need at least 1 addressable null ptr.
188189
if res := collectQueryData(&hQuery); res != pdh.ERROR_SUCCESS {
189190
return nil, res
190191
}
191-
if ret = pdh.PdhGetFormattedCounterArrayLarge(hCounter, &size, &bufferCount, &resArr[0]); ret == pdh.PDH_MORE_DATA {
192-
// create array of size = bufferCount * sizeOf(pdh.PDH_FMT_COUNTERVALUE_ITEM_LARGE)
193-
filledBuf = make([]pdh.PDH_FMT_COUNTERVALUE_ITEM_LARGE, bufferCount)
194-
ret = pdh.PdhGetFormattedCounterArrayLarge(hCounter, &size, &bufferCount, &filledBuf[0])
195-
}
196-
returnArray := make([]PdhValue, 0, bufferCount)
197-
for _, pdhVal := range filledBuf {
198-
returnArray = append(returnArray, PdhValue{
199-
CounterInstance: windows.UTF16PtrToString(pdhVal.SzName),
200-
Value: pdhVal.FmtValue.LargeValue,
201-
})
192+
returnArray := []PdhValue{}
193+
if ret := pdh.PdhGetFormattedCounterArrayLarge(hCounter, &bufSize, &bufCount, &emptyBuf[0]); ret == pdh.PDH_MORE_DATA {
194+
filledBuf := make([]pdh.PDH_FMT_COUNTERVALUE_ITEM_LARGE, bufCount*size)
195+
pdh.PdhGetFormattedCounterArrayLarge(hCounter, &bufSize, &bufCount, &filledBuf[0])
196+
for i := range int(bufCount) {
197+
returnArray = append(returnArray, PdhValue{
198+
CounterInstance: windows.UTF16PtrToString(filledBuf[i].SzName),
199+
Value: filledBuf[i].FmtValue.LargeValue,
200+
})
201+
}
202202
}
203203

204-
return returnArray, ret
204+
return returnArray, pdh.ERROR_SUCCESS
205205
}

pkg/snclient/check_tasksched_windows.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ package snclient
55
import (
66
"context"
77
_ "embed"
8-
"encoding/json"
98
"fmt"
109
"strconv"
1110
"syscall"
1211
"time"
12+
13+
"github.com/goccy/go-json"
1314
)
1415

1516
//go:embed embed/scripts/windows/scheduled_tasks.ps1

pkg/snclient/commands/inventory.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ package commands
22

33
import (
44
"context"
5-
"encoding/json"
65
"fmt"
76

87
"github.com/consol-monitoring/snclient/pkg/snclient"
8+
"github.com/goccy/go-json"
99
"github.com/spf13/cobra"
1010
)
1111

pkg/snclient/listen_exporterexporter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ func (l *HandlerExporterExporter) listModules(res http.ResponseWriter, req *http
238238
switch req.Header.Get("Accept") {
239239
case "application/json":
240240
log.Debugf("Listing modules in json")
241-
moduleJSON, err := json.Marshal(l.modules) //nolint:musttag // no idea what this linter wants to have tagged
241+
moduleJSON, err := json.Marshal(l.modules)
242242
if err != nil {
243243
log.Error(err)
244244
http.Error(res, "Failed to produce JSON", http.StatusInternalServerError)

pkg/snclient/listen_web.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package snclient
22

33
import (
4-
"encoding/json"
54
"fmt"
65
"net/http"
76
"net/url"
@@ -10,6 +9,7 @@ import (
109

1110
"github.com/consol-monitoring/snclient/pkg/utils"
1211
"github.com/go-chi/chi/v5"
12+
"github.com/goccy/go-json"
1313
)
1414

1515
func init() {
@@ -369,7 +369,7 @@ type HandlerWebLegacy struct {
369369
func (l *HandlerWebLegacy) ServeHTTP(res http.ResponseWriter, req *http.Request) {
370370
command := chi.URLParam(req, "command")
371371
result := l.Handler.runCheck(req, command)
372-
data, err := json.Marshal(map[string]interface{}{
372+
jsonData := map[string]interface{}{
373373
"payload": []interface{}{
374374
map[string]interface{}{
375375
"command": command,
@@ -382,7 +382,8 @@ func (l *HandlerWebLegacy) ServeHTTP(res http.ResponseWriter, req *http.Request)
382382
},
383383
},
384384
},
385-
})
385+
}
386+
data, err := json.Marshal(jsonData)
386387
if err != nil {
387388
msg := fmt.Sprintf("json error: %s", err.Error())
388389
log.Errorf("%s", msg)
@@ -440,11 +441,12 @@ func (l *HandlerWebV1) serveCommand(res http.ResponseWriter, req *http.Request)
440441
command := chi.URLParam(req, "command")
441442
result := l.Handler.runCheck(req, command)
442443
res.Header().Set("Content-Type", "application/json")
443-
data, err := json.Marshal(map[string]interface{}{
444+
jsonData := map[string]interface{}{
444445
"command": command,
445446
"result": result.State,
446447
"lines": l.Handler.result2V1(result),
447-
})
448+
}
449+
data, err := json.Marshal(jsonData)
448450
if err != nil {
449451
msg := fmt.Sprintf("json error: %s", err.Error())
450452
log.Errorf("%s", msg)

pkg/snclient/listen_web_admin.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ import (
66
"crypto/x509"
77
"crypto/x509/pkix"
88
"encoding/base64"
9-
"encoding/json"
109
"encoding/pem"
1110
"fmt"
1211
"net/http"
1312
"os"
1413
"strings"
1514
"syscall"
15+
16+
"github.com/goccy/go-json"
1617
)
1718

1819
func init() {

0 commit comments

Comments
 (0)