Skip to content

Commit e781237

Browse files
michaelbeaumontsmira
authored andcommitted
fix: stop decoding without error if EOF encountered during header read
Linux v6.6.39 stops decoding with EOF in this situation but maintains the already decoded structures. See /drivers/firmware/dmi_scan.c Fixes #16 Signed-off-by: Mike Beaumont <[email protected]> Signed-off-by: Andrey Smirnov <[email protected]>
1 parent 6a719a6 commit e781237

File tree

5 files changed

+252
-9
lines changed

5 files changed

+252
-9
lines changed

smbios/internal/github.com/digitalocean/go-smbios/smbios/decoder.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"bufio"
1919
"bytes"
2020
"encoding/binary"
21+
"errors"
2122
"fmt"
2223
"io"
2324
)
@@ -99,11 +100,21 @@ func (d *Decoder) next() (*Structure, error) {
99100
return nil, err
100101
}
101102

103+
if h == nil {
104+
// unexpected structure end, pretend we hit the end of the table
105+
return &Structure{
106+
Header: Header{
107+
Type: typeEndOfTable,
108+
},
109+
}, nil
110+
}
111+
102112
// Length of formatted section is length specified by header, minus
103113
// the length of the header itself.
104114
l := int(h.Length) - headerLen
105115

106-
// Hyper-V SMBIOS tables seem to be broken, implement a workaround
116+
// Some SMBIOS tables, for example Hyper-V, seem to be broken, implement a
117+
// workaround
107118
if h.Length == 0 && h.Type == 0 {
108119
return &Structure{
109120
Header: Header{
@@ -132,6 +143,12 @@ func (d *Decoder) next() (*Structure, error) {
132143
// parseHeader parses a Structure's Header from the stream.
133144
func (d *Decoder) parseHeader() (*Header, error) {
134145
if _, err := io.ReadFull(d.br, d.b[:headerLen]); err != nil {
146+
// We do the same thing the kernel does in drivers/firmware/dmi_scan.c
147+
// since v6.6.39 and return early if we don't have enough bytes for a header
148+
if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF) {
149+
return nil, nil //nolint:nilnil
150+
}
151+
135152
return nil, fmt.Errorf("error reading header: %w", err)
136153
}
137154

smbios/internal/github.com/digitalocean/go-smbios/smbios/decoder_test.go

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ func TestDecoder(t *testing.T) {
3333
{
3434
name: "short header",
3535
b: []byte{0x00},
36+
ss: []*smbios.Structure{{
37+
Header: smbios.Header{
38+
Type: 127,
39+
},
40+
}},
41+
ok: true,
3642
},
3743
{
3844
name: "length too short",
@@ -49,14 +55,6 @@ func TestDecoder(t *testing.T) {
4955
'a', 'b', 'c', 'd',
5056
},
5157
},
52-
{
53-
name: "no end of table",
54-
b: []byte{
55-
0x01, 0x04, 0x01, 0x00,
56-
0x00,
57-
0x00,
58-
},
59-
},
6058
{
6159
name: "bad second message",
6260
b: []byte{
@@ -67,6 +65,46 @@ func TestDecoder(t *testing.T) {
6765

6866
0xff,
6967
},
68+
ss: []*smbios.Structure{
69+
{
70+
Header: smbios.Header{
71+
Type: 1,
72+
Length: 12,
73+
Handle: 2,
74+
},
75+
Formatted: []uint8{0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef},
76+
Strings: []string{"deadbeef"},
77+
},
78+
{
79+
Header: smbios.Header{
80+
Type: 127,
81+
},
82+
},
83+
},
84+
ok: true,
85+
},
86+
{
87+
name: "no end of table",
88+
b: []byte{
89+
0x01, 0x04, 0x01, 0x00,
90+
0x00,
91+
0x00,
92+
},
93+
ss: []*smbios.Structure{
94+
{
95+
Header: smbios.Header{
96+
Type: 1,
97+
Length: 4,
98+
Handle: 1,
99+
},
100+
},
101+
{
102+
Header: smbios.Header{
103+
Type: 127,
104+
},
105+
},
106+
},
107+
ok: true,
70108
},
71109
{
72110
name: "OK, one, no format, no strings",

smbios/smbios_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ func TestDecode(t *testing.T) {
2323
"SuperMicro-Dual-Xeon",
2424
"SuperMicro-Quad-Opteron",
2525
"HyperV",
26+
"Beelink-EQ12",
2627
} {
2728
t.Run(name, func(t *testing.T) {
2829
t.Parallel()

smbios/testdata/Beelink-EQ12.dmi

4.22 KB
Binary file not shown.

smbios/testdata/Beelink-EQ12.json

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
{
2+
"Version": {
3+
"Major": 3,
4+
"Minor": 3,
5+
"Revision": 0
6+
},
7+
"BIOSInformation": {
8+
"Vendor": "",
9+
"Version": "",
10+
"ReleaseDate": ""
11+
},
12+
"SystemInformation": {
13+
"Manufacturer": "AZW",
14+
"ProductName": "EQ",
15+
"Version": "Default string",
16+
"SerialNumber": "BN1004GH10075",
17+
"UUID": "03000200-0400-0500-0006-000700080009",
18+
"WakeUpType": 6,
19+
"SKUNumber": "Default string",
20+
"Family": "Default string"
21+
},
22+
"BaseboardInformation": {
23+
"Manufacturer": "AZW",
24+
"Product": "EQ",
25+
"Version": "Default string",
26+
"SerialNumber": "Default string",
27+
"AssetTag": "Default string",
28+
"LocationInChassis": "Default string",
29+
"BoardType": 10
30+
},
31+
"SystemEnclosure": {
32+
"Manufacturer": "Default string",
33+
"Version": "Default string",
34+
"SerialNumber": "Default string",
35+
"AssetTagNumber": "",
36+
"SKUNumber": "Default string"
37+
},
38+
"ProcessorInformation": [
39+
{
40+
"SocketDesignation": "U3E1",
41+
"ProcessorManufacturer": "Intel(R) Corporation",
42+
"ProcessorVersion": "Intel(R) N100",
43+
"MaxSpeed": 3400,
44+
"CurrentSpeed": 2871,
45+
"Status": 65,
46+
"SerialNumber": "",
47+
"AssetTag": "",
48+
"PartNumber": "",
49+
"CoreCount": 4,
50+
"CoreEnabled": 4,
51+
"ThreadCount": 4
52+
}
53+
],
54+
"CacheInformation": [
55+
{
56+
"SocketDesignation": "L1 Cache"
57+
},
58+
{
59+
"SocketDesignation": "L1 Cache"
60+
},
61+
{
62+
"SocketDesignation": "L2 Cache"
63+
},
64+
{
65+
"SocketDesignation": "L3 Cache"
66+
}
67+
],
68+
"PortConnectorInformation": [
69+
{
70+
"InternalReferenceDesignator": "Internal Connector 1",
71+
"ExternalReferenceDesignator": "External Connector 1"
72+
},
73+
{
74+
"InternalReferenceDesignator": "Internal Connector 2",
75+
"ExternalReferenceDesignator": "External Connector 2"
76+
},
77+
{
78+
"InternalReferenceDesignator": "Internal Connector 3",
79+
"ExternalReferenceDesignator": "External Connector 3"
80+
},
81+
{
82+
"InternalReferenceDesignator": "Internal Connector 4",
83+
"ExternalReferenceDesignator": "External Connector 4"
84+
},
85+
{
86+
"InternalReferenceDesignator": "Internal Connector 5",
87+
"ExternalReferenceDesignator": "External Connector 5"
88+
}
89+
],
90+
"SystemSlots": [
91+
{
92+
"SlotDesignation": "Slot 1"
93+
},
94+
{
95+
"SlotDesignation": "Slot 2"
96+
},
97+
{
98+
"SlotDesignation": "Slot 3"
99+
},
100+
{
101+
"SlotDesignation": "Slot 4"
102+
},
103+
{
104+
"SlotDesignation": "Slot 5"
105+
}
106+
],
107+
"OEMStrings": {
108+
"Strings": [
109+
"Default string"
110+
],
111+
"Count": 1
112+
},
113+
"SystemConfigurationOptions": {
114+
"Strings": [
115+
"Default string"
116+
],
117+
"Count": 1
118+
},
119+
"BIOSLanguageInformation": {
120+
"CurrentLanguage": "en|US|iso8859-1",
121+
"InstallableLanguages": [
122+
"en|US|iso8859-1"
123+
]
124+
},
125+
"GroupAssociations": {
126+
"GroupName": ""
127+
},
128+
"PhysicalMemoryArray": {
129+
"Location": 3,
130+
"Use": 3,
131+
"MemoryErrorCorrection": 3,
132+
"MaximumCapacity": 67108864,
133+
"MemoryErrorInformationHandle": 65534,
134+
"NumberOfMemoryDevices": 2,
135+
"ExtendedMaximumCapacity": 0
136+
},
137+
"MemoryDevices": [
138+
{
139+
"PhysicalMemoryArrayHandle": 39,
140+
"MemoryErrorInformationHandle": 65534,
141+
"TotalWidth": 64,
142+
"DataWidth": 64,
143+
"Size": 16384,
144+
"FormFactor": 13,
145+
"DeviceSet": "",
146+
"DeviceLocator": "Controller0-ChannelA-DIMM0",
147+
"BankLocator": "BANK 0",
148+
"MemoryType": 34,
149+
"TypeDetail": 128,
150+
"Speed": 5600,
151+
"Manufacturer": "Crucial Technology",
152+
"SerialNumber": "E8FBFFE2",
153+
"AssetTag": "9876543210",
154+
"PartNumber": "CT16G56C46S5.M8G1",
155+
"Attributes": 1,
156+
"ExtendedSize": 0,
157+
"ConfiguredMemorySpeed": 4800,
158+
"MinimumVoltage": 1100,
159+
"MaximumVoltage": 1100,
160+
"ConfiguredVoltage": 1100
161+
},
162+
{
163+
"PhysicalMemoryArrayHandle": 39,
164+
"MemoryErrorInformationHandle": 65534,
165+
"TotalWidth": 0,
166+
"DataWidth": 0,
167+
"Size": 0,
168+
"FormFactor": 2,
169+
"DeviceSet": "",
170+
"DeviceLocator": "Controller1-ChannelA-DIMM0",
171+
"BankLocator": "BANK 0",
172+
"MemoryType": 2,
173+
"TypeDetail": 0,
174+
"Speed": 0,
175+
"Manufacturer": "",
176+
"SerialNumber": "",
177+
"AssetTag": "",
178+
"PartNumber": "",
179+
"Attributes": 0,
180+
"ExtendedSize": 0,
181+
"ConfiguredMemorySpeed": 0,
182+
"MinimumVoltage": 0,
183+
"MaximumVoltage": 0,
184+
"ConfiguredVoltage": 0
185+
}
186+
]
187+
}

0 commit comments

Comments
 (0)