crotwell / seisFile

A library for reading and writing seismic file formats in java.
GNU Lesser General Public License v3.0
27 stars 20 forks source link

Negative index exception when miniseed blockette without data encountered #22

Closed ghost closed 3 years ago

ghost commented 3 years ago

When attempting to read the attached file, this exception occurs:

java.lang.NegativeArraySizeException: -256
    at edu.sc.seis.seisFile.mseed.DataRecord.readDataRecord(DataRecord.java:436)
    at edu.sc.seis.seisFile.mseed.SeedRecord.read(SeedRecord.java:66)

miniseed.zip

Parsing the miniseed and extracting information about the specific record (001465) that breaks:

Record 009798 (121) Type Q Network N4 Station L34B Location 00 Channel LHZ
Time 2020,197,13:42:27.9999 Samples 400 Factor 1 Mult 1 (1sps)
IO: GOODTM (0x20)
Blockettes 2 Correction 0 Data Start 64 First Block 48 Host Swap LE
1000-DATAONLY: STEIM-2 Swap=BE Len=9
1001-QTADEXT: Quality=100% Usec=98 Frames=7

Blockette 320 present
Record 001465 (122) Type Q Network N4 Station L34B Location 00 Channel LHZ
Time 2020,197,13:44:12.0000 Samples 0 Factor 0 Mult 1 (0sps)
Activity: CALSIG (0x01) IO: GOODTM (0x20)
Blockettes 3 Correction 0 Data Start 256 First Block 48 Host Swap LE
1000-DATAONLY: STEIM-2 Swap=BE Len=9
1001-QTADEXT: Quality=100% Usec=0 Frames=0
Blockette 320 seen

Record 009799 (123) Type Q Network N4 Station L34B Location 00 Channel LHZ
Time 2020,197,13:49:08.0000 (296000ms gap) Samples 400 Factor 1 Mult 1 (1sps)
Activity: CALSIG (0x01) IO: GOODTM (0x20)
Blockettes 2 Correction 0 Data Start 64 First Block 48 Host Swap LE
1000-DATAONLY: STEIM-2 Swap=BE Len=9
1001-QTADEXT: Quality=100% Usec=0 Frames=7

The record contains no data blockettes, only blockette information noticeably a blockette 320.

When debugging, I noticed these lines: https://github.com/crotwell/seisFile/blob/a021da9d842ffa677b2077bbf8376a2dc38bb631/src/main/java/edu/sc/seis/seisFile/mseed/DataRecord.java#L387-L391

I think this is causing line 436 to break: https://github.com/crotwell/seisFile/blob/a021da9d842ffa677b2077bbf8376a2dc38bb631/src/main/java/edu/sc/seis/seisFile/mseed/DataRecord.java#L434-L445

My understaing of what happens: There are 0 samples so at line 378, seisfile marks the current offset to be the end of the data record. However field 17 has a value of 256 which seisfile attempts to purge prior to reading data. However, it has already skipped to the end of that record and run out of bytes to read. It attempts to create an array of -256 length, which throws the exception

If you would like, I could code a patch up for this. Something like changing line 435 to the below, might patch the issue:

if (header.getDataOffset() != 0 && header.getNumSamples() != 0 ) {

Or moving the datarecord purge at line 387 to work with the purge at 444

crotwell commented 3 years ago

Interesting. I am tempted to say that this is malformed miniseed, but the seed manual is kind of ambiguous about what to put in field 17 when there is no data. When I have seen no-data records in the past the value was 0, following the convention for field 18 when there are no blockettes. It is also odd that the data offset would be 256 when the record size is 512 (Len=9), guessing that is left over from a 256 to 512 record size conversion. But accommodating this looks like it can be done without breaking existing data.

Fix is in https://github.com/crotwell/seisFile/commit/ae3e9cd31124a5ec00048ffbd2fe9730e3bb6cfa

Will try to put out a new release soon. Sorry for delay, was on vacation.

crotwell commented 3 years ago

fix in v2.0.2