Skip to content

Commit 7f4bceb

Browse files
committed
fix(collector): handle large LBA values in SMART data parsing
Change LBA fields from int to uint64 to handle large unsigned 64-bit values that exceed int64 max. This fixes JSON unmarshaling errors when parsing SMART data from drives with large LBA addresses. Fields changed: - AtaSmartErrorLog.Summary.Table[].CompletionRegisters.Lba - AtaSmartErrorLog.Summary.Table[].PreviousCommands[].Registers.Lba - AtaSmartSelectiveSelfTestLog.Table[].LbaMin - AtaSmartSelectiveSelfTestLog.Table[].LbaMax Fixes #24 Upstream: AnalogJ#800
1 parent 03513b7 commit 7f4bceb

File tree

2 files changed

+95
-4
lines changed

2 files changed

+95
-4
lines changed

webapp/backend/pkg/models/collector/smart.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ type SmartInfo struct {
146146
Error int `json:"error"`
147147
Status int `json:"status"`
148148
Count int `json:"count"`
149-
Lba int `json:"lba"`
149+
Lba uint64 `json:"lba"`
150150
Device int `json:"device"`
151151
} `json:"completion_registers"`
152152
ErrorDescription string `json:"error_description"`
@@ -155,7 +155,7 @@ type SmartInfo struct {
155155
Command int `json:"command"`
156156
Features int `json:"features"`
157157
Count int `json:"count"`
158-
Lba int `json:"lba"`
158+
Lba uint64 `json:"lba"`
159159
Device int `json:"device"`
160160
DeviceControl int `json:"device_control"`
161161
} `json:"registers"`
@@ -188,8 +188,8 @@ type SmartInfo struct {
188188
AtaSmartSelectiveSelfTestLog struct {
189189
Revision int `json:"revision"`
190190
Table []struct {
191-
LbaMin int `json:"lba_min"`
192-
LbaMax int `json:"lba_max"`
191+
LbaMin uint64 `json:"lba_min"`
192+
LbaMax uint64 `json:"lba_max"`
193193
Status struct {
194194
Value int `json:"value"`
195195
String string `json:"string"`

webapp/backend/pkg/models/collector/smart_test.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package collector
22

33
import (
4+
"encoding/json"
45
"testing"
56

67
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
79
)
810

911
func TestSmartInfo_Capacity(t *testing.T) {
@@ -31,3 +33,92 @@ func TestSmartInfo_Capacity(t *testing.T) {
3133
assert.Zero(t, smartInfo.Capacity())
3234
})
3335
}
36+
37+
func TestSmartInfo_LargeLBAValues(t *testing.T) {
38+
// Test for GitHub issue #24 / upstream issue #800
39+
// LBA values can be large unsigned 64-bit integers that overflow signed int
40+
t.Run("should parse large LBA values in selective self-test log", func(t *testing.T) {
41+
// This JSON contains LBA values that exceed int64 max (9223372036854775807)
42+
// Value 18446743534724713985 is a valid uint64 but overflows int64
43+
jsonData := `{
44+
"ata_smart_selective_self_test_log": {
45+
"revision": 1,
46+
"table": [
47+
{
48+
"lba_min": 18446743534724713985,
49+
"lba_max": 7205816247684983039,
50+
"status": {
51+
"value": 0,
52+
"string": "Not_testing"
53+
}
54+
}
55+
],
56+
"flags": {
57+
"value": 0,
58+
"remainder_scan_enabled": false
59+
},
60+
"power_up_scan_resume_minutes": 0
61+
}
62+
}`
63+
64+
var smartInfo SmartInfo
65+
err := json.Unmarshal([]byte(jsonData), &smartInfo)
66+
require.NoError(t, err, "should unmarshal large LBA values without error")
67+
68+
// Verify the values were parsed correctly
69+
require.Len(t, smartInfo.AtaSmartSelectiveSelfTestLog.Table, 1)
70+
assert.Equal(t, uint64(18446743534724713985), smartInfo.AtaSmartSelectiveSelfTestLog.Table[0].LbaMin)
71+
assert.Equal(t, uint64(7205816247684983039), smartInfo.AtaSmartSelectiveSelfTestLog.Table[0].LbaMax)
72+
})
73+
74+
t.Run("should parse large LBA values in error log", func(t *testing.T) {
75+
// LBA values in error logs can also be large
76+
jsonData := `{
77+
"ata_smart_error_log": {
78+
"summary": {
79+
"revision": 1,
80+
"count": 1,
81+
"logged_count": 1,
82+
"table": [
83+
{
84+
"error_number": 1,
85+
"lifetime_hours": 1000,
86+
"completion_registers": {
87+
"error": 0,
88+
"status": 0,
89+
"count": 0,
90+
"lba": 18446744073709551615,
91+
"device": 0
92+
},
93+
"error_description": "test",
94+
"previous_commands": [
95+
{
96+
"registers": {
97+
"command": 0,
98+
"features": 0,
99+
"count": 0,
100+
"lba": 18446744073709551615,
101+
"device": 0,
102+
"device_control": 0
103+
},
104+
"powerup_milliseconds": 0,
105+
"command_name": "test"
106+
}
107+
]
108+
}
109+
]
110+
}
111+
}
112+
}`
113+
114+
var smartInfo SmartInfo
115+
err := json.Unmarshal([]byte(jsonData), &smartInfo)
116+
require.NoError(t, err, "should unmarshal large LBA values in error log without error")
117+
118+
// Verify the values were parsed correctly
119+
require.Len(t, smartInfo.AtaSmartErrorLog.Summary.Table, 1)
120+
assert.Equal(t, uint64(18446744073709551615), smartInfo.AtaSmartErrorLog.Summary.Table[0].CompletionRegisters.Lba)
121+
require.Len(t, smartInfo.AtaSmartErrorLog.Summary.Table[0].PreviousCommands, 1)
122+
assert.Equal(t, uint64(18446744073709551615), smartInfo.AtaSmartErrorLog.Summary.Table[0].PreviousCommands[0].Registers.Lba)
123+
})
124+
}

0 commit comments

Comments
 (0)