Skip to content

Commit 729a031

Browse files
authored
Fix OpenBSD interrupt device parsing (#3288)
Sanitize zero terminated strings from OpenBSD device name parsing. * Add byte-to-string util function. Fixes: #3287 Signed-off-by: Ben Kochie <[email protected]>
1 parent e768aad commit 729a031

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

collector/interrupts_openbsd_amd64.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121
"strconv"
2222
"unsafe"
2323

24+
"github.com/prometheus/node_exporter/collector/utils"
25+
2426
"github.com/prometheus/client_golang/prometheus"
2527
"golang.org/x/sys/unix"
2628
)
@@ -49,7 +51,7 @@ func intr(idx _C_int) (itr interrupt, err error) {
4951
return
5052
}
5153
dev := *(*[128]byte)(unsafe.Pointer(&buf[0]))
52-
itr.device = string(dev[:])
54+
itr.device = utils.SafeBytesToString(dev[:])
5355

5456
mib[2] = KERN_INTRCNT_VECTOR
5557
buf, err = sysctl(mib[:])

collector/utils/utils.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313

1414
package utils
1515

16+
import (
17+
"bytes"
18+
"strings"
19+
)
20+
1621
func SafeDereference[T any](s ...*T) []T {
1722
var resolved []T
1823
for _, v := range s {
@@ -25,3 +30,18 @@ func SafeDereference[T any](s ...*T) []T {
2530
}
2631
return resolved
2732
}
33+
34+
// SafeBytesToString takes a slice of bytes and sanitizes it for Prometheus label
35+
// values.
36+
// * Terminate the string at the first null byte.
37+
// * Convert any invalid UTF-8 to "�".
38+
func SafeBytesToString(b []byte) string {
39+
var s string
40+
zeroIndex := bytes.IndexByte(b, 0)
41+
if zeroIndex == -1 {
42+
s = string(b)
43+
} else {
44+
s = string(b[:zeroIndex])
45+
}
46+
return strings.ToValidUTF8(s, "�")
47+
}

collector/utils/utils_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2025 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file ewcept in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package utils
15+
16+
import (
17+
"testing"
18+
)
19+
20+
func TestSafeBytesToString(t *testing.T) {
21+
foo := []byte("foo\x00")
22+
if want, got := SafeBytesToString(foo), "foo"; want != got {
23+
t.Errorf("Expected: %s, Got: %s", want, got)
24+
}
25+
26+
foo = []byte{115, 97, 110, 101, 253, 190, 214}
27+
if want, got := SafeBytesToString(foo), "sane�"; want != got {
28+
t.Errorf("Expected: %s, Got: %s", want, got)
29+
}
30+
}

0 commit comments

Comments
 (0)