diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 6c11aeca0e..3045a389f9 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2008-02-11 Daniel Jacobowitz + + * cache.c (cache_bread): Set bfd_error_file_truncated if EOF + was reached. + * srec.c (srec_scan): Calculate the checksum. Complain on mismatch. + 2008-02-07 Alan Modra * elf32-spu.c (spu_elf_size_stubs): Revert 2008-01-28 doubling diff --git a/bfd/cache.c b/bfd/cache.c index 039c1a941b..064cebeb3c 100644 --- a/bfd/cache.c +++ b/bfd/cache.c @@ -309,6 +309,10 @@ cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes) return -1; } #endif + if (nread < nbytes) + /* This may or may not be an error, but in case the calling code + bails out because of it, set the right error code. */ + bfd_set_error (bfd_error_file_truncated); return nread; } diff --git a/bfd/srec.c b/bfd/srec.c index 371e53a366..b7d515ccb9 100644 --- a/bfd/srec.c +++ b/bfd/srec.c @@ -458,6 +458,7 @@ srec_scan (bfd *abfd) unsigned int bytes; bfd_vma address; bfd_byte *data; + unsigned char check_sum; /* Starting an S-record. */ @@ -476,7 +477,7 @@ srec_scan (bfd *abfd) goto error_return; } - bytes = HEX (hdr + 1); + check_sum = bytes = HEX (hdr + 1); if (bytes * 2 > bufsize) { if (buf != NULL) @@ -505,18 +506,22 @@ srec_scan (bfd *abfd) break; case '3': + check_sum += HEX (data); address = HEX (data); data += 2; --bytes; /* Fall through. */ case '2': + check_sum += HEX (data); address = (address << 8) | HEX (data); data += 2; --bytes; /* Fall through. */ case '1': + check_sum += HEX (data); address = (address << 8) | HEX (data); data += 2; + check_sum += HEX (data); address = (address << 8) | HEX (data); data += 2; bytes -= 2; @@ -548,25 +553,56 @@ srec_scan (bfd *abfd) sec->size = bytes; sec->filepos = pos; } + + while (bytes > 0) + { + check_sum += HEX (data); + data += 2; + bytes--; + } + check_sum = 255 - (check_sum & 0xff); + if (check_sum != HEX (data)) + { + (*_bfd_error_handler) + (_("%B:%d: Bad checksum in S-record file\n"), + abfd, lineno); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + break; case '7': + check_sum += HEX (data); address = HEX (data); data += 2; /* Fall through. */ case '8': + check_sum += HEX (data); address = (address << 8) | HEX (data); data += 2; /* Fall through. */ case '9': + check_sum += HEX (data); address = (address << 8) | HEX (data); data += 2; + check_sum += HEX (data); address = (address << 8) | HEX (data); data += 2; /* This is a termination record. */ abfd->start_address = address; + check_sum = 255 - (check_sum & 0xff); + if (check_sum != HEX (data)) + { + (*_bfd_error_handler) + (_("%B:%d: Bad checksum in S-record file\n"), + abfd, lineno); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + if (buf != NULL) free (buf);