[Debian-med-packaging] Bug#876839: staden-io-lib FTBFS on big endian: error: invalid operands to binary &

Andreas Tille andreas at an3as.eu
Tue Sep 26 20:46:15 UTC 2017


control: forwarded -1 James Bonfield <jkb at sanger.ac.uk>
control: tags -1 upstream

Hi James,

There is a bug report against the Debian package of the latest
io_lib version.  See the full bug log here:

    https://bugs.debian.org/876839

Below you can read about a suggested solution.

Kind regards

       Andreas.

On Tue, Sep 26, 2017 at 10:31:01PM +0200, Christian Seiler wrote:
> On 09/26/2017 10:06 PM, Andreas Tille wrote:
> >> ...
> >> In file included from bgzip.c:56:0:
> >> bgzip.c: In function 'gzi_index_dump':
> >> ../io_lib/os.h:127:10: error: invalid operands to binary & (have 'uint64_t * {aka long long unsigned int *}' and 'long long int')
> >>      (((x & 0x00000000000000ffLL) << 56) + \
> >>           ^
> >> ../io_lib/os.h:185:20: note: in expansion of macro 'iswap_int8'
> >>  #define le_int8(x) iswap_int8((x))
> >>                     ^~~~~~~~~~
> >> bgzip.c:190:16: note: in expansion of macro 'le_int8'
> >>      if (fwrite(le_int8(&n), sizeof(n), 1, idx_f) != 1)
> >>                 ^~~~~~~
> 
> This code is completely wrong.
> 
> le_int8 appears to do a 64 bit byte order swap to adjust the
> endianness of a quantity. What bgzip.c does at this point is the
> following (removed if() for clarity):
> 
> uint64_t n = idx->n;
> fwrite(le_int8(&n), sizeof(n), 1, idx_f);
> 
> &n is the pointer to the 'n' variable, but you really don't want
> to byte swap a pointer to a local variable before passing it to
> a function that reads that pointer (also note that the pointer
> could be 32 bit on 32 bit systems!).
> 
> What you presumably want to do is byte swap the _contents_ of the
> pointer (especially since n is a 64 bit integer). If you look at
> the read code in the same file this is actually what happens:
> 
>     if (8 != fread(&n, 1, 8, fp))
> 	goto err;
>     n = le_int8(n);
> 
> So what you'd rather want to have is the following code:
> 
> uint64_t n = le_int8(idx->n);
> fwrite(&n, sizeof(n), 1, idx_f);
> 
> Or, if I adjust the entirety of that section in the original write
> code:
> 
>     int i;
>     uint64_t n = le_int8(idx->n);
>     if (fwrite(&n), sizeof(n), 1, idx_f) != 1)
> 	goto fail;
>     for (i=0; i<idx->n; i++) {
>         uint64_t nn;
>         nn = le_int8(idx->c_off[i]);
> 	if (fwrite(&nn, sizeof(nn), 1, idx_f) != 1)
> 	    goto fail;
>         nn = le_int8(idx->u_off[i]);
> 	if (fwrite(&nn, sizeof(nn), 1, idx_f) != 1)
> 	    goto fail;
>     }
> 
> That should fix the compiler error you're seeing.
> 
> The only reason that doesn't fail on Little Endian is because the
> le_int8(x) function is a no-op on those systems and just passes
> through the original pointer.
> 
> Regards,
> Christian
> 

-- 
http://fam-tille.de



More information about the Debian-med-packaging mailing list