Closed ghost closed 7 years ago
Thanks, we'll check this.
I looked at the code, and it has a clear off-by-one bug. In the first iteration of the loop at lines 48-56, part
will be equal to FieldT::num_limbs
. rval
is declared as bigint<FieldT::num_limbs> rval;
on line 29, so the rval.data[part] &= ~(1ul<<bit);
on line 53 will read/assign one past the end of the array.
The intent was probably to initialize bitno
to (GMP_NUMB_BITS * FieldT::num_limbs) - 1
. Also, nothing currently stops bitno
from underflowing if all bits were zero, so the loop condition should be changed to ensure correct termination.
Also, we should fix the weird dissociation of the while condition on line 62 from its corresponding do
loop ("just" a whitespace issue, but confusing).
See https://github.com/zcash/zcash/issues/780.
Also, the buggy code is trying to generate a field element uniformly at random, right? Generating an integer significantly larger than a field element (say by 128 bits) and then reducing it modulo the field size is a better way to do that than rejection sampling, IMHO.
I just want to emphasise that this code is clearly incorrect and has undefined behaviour.
In Zcash's fork of libsnark we removed this PRNG: https://github.com/zcash/zcash/pull/1104 . It's still broken (and potentially a security bug) in upstream libsnark.
Thanks! This has been fixed in libff.
Hi,
I'm currently digging through libsnark with ASan enabled, and I might have found a stack-buffer-overflow in libsnark::SHA512_rng triggered by various test-cases.
undefined behaviour:
stack-bo:
edit 2016/04/11: updated to human readable filenames and line numbers