Skip to content

Commit

Permalink
bswap16 short header words in field_forall
Browse files Browse the repository at this point in the history
bswap32 cannot be indiscriminatly applied to the int32 temporary, as it
essentially is a byte-reorder and left-shift when applies to an int16.

The symptom is that certain header fields extracted this way show up in
the absurd range (some 65 million), when normal values are in the few
thousands, such as dt/sample-interval.

Addresses #368

#368
  • Loading branch information
jokva committed Apr 19, 2019
1 parent 112c7e3 commit 60ebd2b
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
16 changes: 14 additions & 2 deletions lib/src/segy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -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;
}

Expand All @@ -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;
}

Expand Down
11 changes: 11 additions & 0 deletions python/test/segy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down

0 comments on commit 60ebd2b

Please sign in to comment.