Skip to content

Fix a long-standing typo in hts_lrand48.#1171

Merged
daviesrob merged 1 commit intosamtools:developfrom
jkbonfield:hts_lrand48_fix
Nov 4, 2020
Merged

Fix a long-standing typo in hts_lrand48.#1171
daviesrob merged 1 commit intosamtools:developfrom
jkbonfield:hts_lrand48_fix

Conversation

@jkbonfield
Copy link
Copy Markdown
Contributor

Note: this function is never used. It was only added for reasons of completeness when we were putting in hts_drand48, used by htslib/ksort.h.

@jmarshall
Copy link
Copy Markdown
Member

jmarshall commented Nov 2, 2020

Okay, this was not completely trivial as it turns out 😄

Fortunately no true ABI implications either as it's not the header file that was wrong. At worst it's a bug fix in the results of a mostly unused function. At least on the common platforms, by luck on return from hts_lrand48() the return value will have been in both the int and float return registers — so it has been returning the right result by luck anyway, which will have contributed to no-one noticing for three years.

Note: this function is never used.

Currently never used in htslib/samtools/bcftools. It may be in use by other third-party code.

@jkbonfield
Copy link
Copy Markdown
Contributor Author

jkbonfield commented Nov 2, 2020

I'd already done some basic github searches and it turns up absolutely nowhere.

I suspect it really is 100% unused.

Edit: also interpretting a double as a long and getting gibberish back is somewhat harmless for a random number generator. lol

@jkbonfield
Copy link
Copy Markdown
Contributor Author

jkbonfield commented Nov 3, 2020

At worst it's a bug fix in the results of a mostly unused function. At least on the common platforms, by luck on return from hts_lrand48() the return value will have been in both the int and float return registers — so it has been returning the right result by luck anyway, which will have contributed to no-one noticing for three years.

Oh I see what you mean. The usual implementation would be call lrand48 (result in rax) and then migrate that to double via something like "cvtsi2sdq %rax, %xmm0". The calling function with the proper declaration assumes it's long and just reads %rax anyway.

That works, but it's compiler specific and fails with clang optimisations. Eg:

@ deskpro[/tmp]; cat dr.c
#include <stdlib.h>
double hts_lrand48(void) { return lrand48(); }

@ deskpro[/tmp]; cat r.c
#include <stdio.h>
#include <stdlib.h>

long hts_lrand48(void);

int main(void) {
    srand48(10);

    int i;
    long l;
    for (i = 0; i < 10; i++) {
	l = hts_lrand48();
	printf("%ld\n", l);
    }
}

@ deskpro[/tmp]; clang70 -c dr.c; clang70 r.c dr.o; ./a.out
1887318415
1708981709
1032568723
1128874726
986043905
2030393807
1387591810
1257232211
1374034427
2054885217

@ deskpro[/tmp]; clang70 -O2 -c dr.c; clang70 r.c dr.o; ./a.out
0
1
2
3
4
5
6
7
8
9

Comically non-random! (I'm guessing that's the loop counter.)

I still just view this as a bug fix and not an ABI change. The ABI is 100% the same, but our random number generator is now more random. (Edit: kind of... API the same. ABI compatible although the return registers may hold different values.)

The return type of the definition was wrong, causing callers
using the function to get incorrect results in some cases,
mainly depending on the platform and compiler options used.

Note: this function is not used by htslib.  It was only added for
reasons of completeness when we were putting in hts_drand48, used
by htslib/ksort.h.
@daviesrob
Copy link
Copy Markdown
Member

Agreed, given the mismatch between header and definition can result in undefined behaviour this is really a bug fix.

@daviesrob daviesrob merged commit b211b4c into samtools:develop Nov 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants