diff --git a/lib/src/segy.c b/lib/src/segy.c index 2b8fea128..f836585dc 100644 --- a/lib/src/segy.c +++ b/lib/src/segy.c @@ -687,6 +687,14 @@ static int slicelength( int start, int stop, int step ) { return (stop - start - 1) / step + 1; } +static int32_t bswap_header_word(int32_t f, int word_size) { + if (word_size == 4) + return bswap32(f); + + int16_t shortf = f; + return bswap16(shortf); +} + int segy_field_forall( segy_file* fp, int field, int start, @@ -702,6 +710,10 @@ int segy_field_forall( segy_file* fp, err = segy_get_field( header, field, &f ); if( err != SEGY_OK ) return SEGY_INVALID_ARGS; + // since segy_get_field didn't fail earlier, it is safe to look up the word + // size + const int word_size = field_size[field]; + int slicelen = slicelength( start, stop, step ); // check *once* that we don't look past the end-of-file @@ -719,7 +731,7 @@ int segy_field_forall( segy_file* fp, for( int i = start; slicelen > 0; i += step, ++buf, --slicelen ) { segy_seek( fp, i, trace0, trace_bsize ); get_field( fp->cur, field_size, field, &f ); - if( lsb ) f = bswap32(f); + if (lsb) f = bswap_header_word(f, word_size); *buf = f; } @@ -744,7 +756,7 @@ int segy_field_forall( segy_file* fp, if( readc != 1 ) return SEGY_FREAD_ERROR; segy_get_field( header, field, &f ); - if( lsb ) f = bswap32(f); + if (lsb) f = bswap_header_word(f, word_size); *buf = f; } diff --git a/python/test/segy.py b/python/test/segy.py index a29c6ebae..0e5a3f7b9 100644 --- a/python/test/segy.py +++ b/python/test/segy.py @@ -1643,6 +1643,17 @@ def test_readtrace_int16(): assert list(tr[40:19:-5]) == [-888, -2213, 5198, -1170, 0] assert list(tr[53:50:-1]) == [-2609, -2625, 681] +def test_attributes_shortword_little_endian(): + f3msb = 'test-data/f3.sgy' + f3lsb = 'test-data/f3-lsb.sgy' + word = segyio.su.dt + # this test (in particular) is a pretty good candidate for fuzzing + with segyio.open(f3msb) as msb: + with segyio.open(f3lsb, endian = 'little') as lsb: + msba = msb.attributes(word) + lsba = lsb.attributes(word) + npt.assert_array_equal(msba[:], lsba[:]) + @tmpfiles('test-data/f3.sgy') def test_writetrace_int16(tmpdir):