From 638e7dc12a692c515eb2b6ca795df24d031fafb1 Mon Sep 17 00:00:00 2001 From: henrygd Date: Sun, 8 Mar 2026 13:34:16 -0400 Subject: [PATCH] fix(smart): handle negative ATA device statistics values (#1791) --- agent/smart.go | 4 ++-- agent/smart_test.go | 37 ++++++++++++++++++++++++++++++++ internal/entities/smart/smart.go | 4 ++-- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/agent/smart.go b/agent/smart.go index d3a131dd..c2598518 100644 --- a/agent/smart.go +++ b/agent/smart.go @@ -223,7 +223,7 @@ func (sm *SmartManager) ScanDevices(force bool) error { } func (sm *SmartManager) parseConfiguredDevices(config string) ([]*DeviceInfo, error) { - splitChar := os.Getenv("SMART_DEVICES_SEPARATOR") + splitChar, _ := utils.GetEnv("SMART_DEVICES_SEPARATOR") if splitChar == "" { splitChar = "," } @@ -919,7 +919,7 @@ func temperatureFromAtaDeviceStatistics(stats smart.AtaDeviceStatistics) (uint8, if entry == nil || entry.Value == nil { return 0, false } - if *entry.Value > 255 { + if *entry.Value < 0 || *entry.Value > 255 { return 0, false } return uint8(*entry.Value), true diff --git a/agent/smart_test.go b/agent/smart_test.go index 14add02f..8ff7c6df 100644 --- a/agent/smart_test.go +++ b/agent/smart_test.go @@ -121,6 +121,43 @@ func TestParseSmartForSataDeviceStatisticsTemperature(t *testing.T) { assert.Equal(t, uint8(22), deviceData.Temperature) } +func TestParseSmartForSataNegativeDeviceStatistics(t *testing.T) { + // Tests that negative values in ata_device_statistics (e.g. min operating temp) + // do not cause the entire SAT parser to fail. + jsonPayload := []byte(`{ + "smartctl": {"exit_status": 0}, + "device": {"name": "/dev/sdb", "type": "sat"}, + "model_name": "SanDisk SSD U110 16GB", + "serial_number": "NEGATIVE123", + "firmware_version": "U21B001", + "user_capacity": {"bytes": 16013942784}, + "smart_status": {"passed": true}, + "temperature": {"current": 38}, + "ata_smart_attributes": {"table": []}, + "ata_device_statistics": { + "pages": [ + { + "number": 5, + "name": "Temperature Statistics", + "table": [ + {"name": "Current Temperature", "value": 38, "flags": {"valid": true}}, + {"name": "Specified Minimum Operating Temperature", "value": -20, "flags": {"valid": true}} + ] + } + ] + } + }`) + + sm := &SmartManager{SmartDataMap: make(map[string]*smart.SmartData)} + hasData, exitStatus := sm.parseSmartForSata(jsonPayload) + require.True(t, hasData) + assert.Equal(t, 0, exitStatus) + + deviceData, ok := sm.SmartDataMap["NEGATIVE123"] + require.True(t, ok, "expected smart data entry for serial NEGATIVE123") + assert.Equal(t, uint8(38), deviceData.Temperature) +} + func TestParseSmartForSataParentheticalRawValue(t *testing.T) { jsonPayload := []byte(`{ "smartctl": {"exit_status": 0}, diff --git a/internal/entities/smart/smart.go b/internal/entities/smart/smart.go index 2a7b11f3..cda462e4 100644 --- a/internal/entities/smart/smart.go +++ b/internal/entities/smart/smart.go @@ -143,8 +143,8 @@ type AtaDeviceStatisticsPage struct { } type AtaDeviceStatisticsEntry struct { - Name string `json:"name"` - Value *uint64 `json:"value,omitempty"` + Name string `json:"name"` + Value *int64 `json:"value,omitempty"` } type AtaSmartAttribute struct {