From 73c4550f24fb0755ba2399f3a159d151c65fdd9d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 2 Oct 2019 13:47:17 +0200 Subject: decode-dimms: Detect and report truncated input files If using the wrong driver, or if reading from a truncated dump file, make sure we don't attempt to use data bytes beyond what is available. Doing so would spit pages of cryptic warnings to the user, explicit error messages are much better. Signed-off-by: Jean Delvare --- eeprom/decode-dimms | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/eeprom/decode-dimms b/eeprom/decode-dimms index c2fd253..4a77ff8 100755 --- a/eeprom/decode-dimms +++ b/eeprom/decode-dimms @@ -5,7 +5,7 @@ # Copyright 1998, 1999 Philip Edelbrock # modified by Christian Zuckschwerdt # modified by Burkart Lingner -# Copyright (C) 2005-2017 Jean Delvare +# Copyright (C) 2005-2019 Jean Delvare # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -2362,9 +2362,13 @@ sub spd_sizes($) sub readspd($$$) { my ($offset, $size, $dimm_i) = @_; - my @bytes; + my (@bytes, $read); if ($use_hexdump) { @bytes = read_hexdump($dimm_i); + if (@bytes < $offset + $size) { + print STDERR "WARNING: Dump file $dimm_i is truncated\n"; + $size = @bytes - $offset; + } return @bytes[$offset..($offset + $size - 1)]; } elsif ($use_sysfs) { # Kernel 2.6 with sysfs @@ -2373,9 +2377,12 @@ sub readspd($$$) binmode HANDLE; sysseek(HANDLE, $offset, SEEK_SET) or die "Cannot seek $dimm_i/eeprom"; - sysread(HANDLE, my $eeprom, $size) - or die "Cannot read $dimm_i/eeprom"; + $read = sysread(HANDLE, my $eeprom, $size) + or die "Cannot read $dimm_i/eeprom"; close HANDLE; + if ($read < $size) { + print STDERR "WARNING: $dimm_i/eeprom is smaller than expected\n"; + } @bytes = unpack("C*", $eeprom); } else { # Kernel 2.4 with procfs @@ -2666,11 +2673,14 @@ for $current (0 .. $#dimm) { printl("Total number of bytes in EEPROM", $spd_size); # If there's more data than what we've read, let's - # read it now. DDR3 will need this data. + # read it now. DDR3 and DDR4 will need this data. if ($spd_used > @bytes) { push (@bytes, readspd(@bytes, $spd_used - @bytes, $dimm[$current]->{file})); + if (@bytes < $spd_used) { + print STDERR "WARNING: Fewer data bytes available (".(scalar @bytes).") than needed ($spd_used)\n"; + } } } @@ -2703,14 +2713,18 @@ for $current (0 .. $#dimm) { if ($type eq "DDR3 SDRAM") { # Decode DDR3-specific manufacturing data in bytes # 117-149 - decode_ddr3_mfg_data(\@bytes) + if (@bytes >= 150) { + decode_ddr3_mfg_data(\@bytes) + } } elsif ($type eq "DDR4 SDRAM" || $type eq "DDR4E SDRAM" || $type eq "LPDDR4 SDRAM" || $type eq "LPDDR4X SDRAM") { # Decode DDR4-specific manufacturing data in bytes # 320-383 - decode_ddr4_mfg_data(\@bytes) + if (@bytes >= 384) { + decode_ddr4_mfg_data(\@bytes); + } } else { # Decode next 35 bytes (64-98, common to most # memory types) -- cgit v1.2.1