access to uninitialized FstatResults fields from SWIG
Hi @karl-wette as discussed by e-mail, there seems to be some suspicious behaviour of the FstatResults
when called from python through SWIG: when trying to access a field that was not computed, e.g. FstatResults.twoF
when the FSTATQ_2F
bit wasn't set in the FstatQuantities
input, then one can access random numbers / previous results in memory.
What happens from python?
In the attached test script, I set up a minimum set of ComputeFstat inputs, then (interesting part begins in line 56) loop over three "whatToCompute" choices (FSTATQ_NONE, FSTATQ_2F and once again FSTATQ_NONE), making sure to re-init the results struct every time.
Output looks like this:
whatToCompute: 0
twoF init: []
max(abs(twoF)): 6.3680986e+36
whatToCompute: 1
twoF init: []
max(abs(twoF)): 8.668501
whatToCompute: 0
twoF init: []
max(abs(twoF)): 8.668501
where the first max(abs(twoF)) will be a random unreasonable number, the second a reasonable one (for 2F over noise), and the third reads again the same memory as the second, even though it was set to empty in-between.
As a further test, when activating the additional FaPerDet output in the second-to-last line, the last output will match that one instead.
Hence, it seems that a fresh FstatResults structure is well-behaved (exposes empty members to python, which probably correspond to NULL pointers in C). But after a call to ComputeFstat, python sees what seem like valid pointers to somewhere, but that "somewhere" is random memory junk at first call, and keeps being inherited from previous calls when repeated.
What happens under C?
By contrast, if I try something similar in C, e.g. in ComputeFstatTest I change L175 to just
FstatQuantities whatToCompute = FSTATQ_FAFB;
and add after L197
if ( results_seg1[iMethod]->twoF ) {
printf("after XLALComputeFstat: 2F=%.4f\n", results_seg1[iMethod]->twoF[0]);
} else {
printf("after XLALComputeFstat: 2F=NULL\n");
}
then it sees these as NULL; or just trying to print out twoF[0] without the if-else gives instead a segfault.