summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2014-05-09 12:35:15 +0200
committerWerner Koch <wk@gnupg.org>2014-05-09 13:31:05 +0200
commit2c05a943c5183ca7bfc76115abde29c634198bac (patch)
tree25354245594687a50a6b38c02fe6ab12a2922b80
parent636634871211da16ca5659926e744599a3538d26 (diff)
downloadlibgcrypt-2c05a943c5183ca7bfc76115abde29c634198bac.tar.gz
mpi: Fix a subtle bug setting spurious bits with in mpi_set_bit.
* mpi/mpi-bit.c (_gcry_mpi_set_bit, _gcry_mpi_set_highbit): Clear allocated but not used bits before resizing. * tests/t-mpi-bits.c (set_bit_with_resize): New. -- Reported-by: Martin Sewelies. This bug is probably with us for many years. Probably due to different memory allocation patterns, it did first revealed itself with 1.6. It could be the reason for other heisenbugs. Signed-off-by: Werner Koch <wk@gnupg.org>
-rw-r--r--mpi/mpi-bit.c8
-rw-r--r--tests/t-mpi-bit.c54
2 files changed, 60 insertions, 2 deletions
diff --git a/mpi/mpi-bit.c b/mpi/mpi-bit.c
index cdc6b0b3..ff42ba39 100644
--- a/mpi/mpi-bit.c
+++ b/mpi/mpi-bit.c
@@ -115,13 +115,15 @@ gcry_mpi_test_bit( gcry_mpi_t a, unsigned int n )
void
gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n )
{
- unsigned int limbno, bitno;
+ unsigned int i, limbno, bitno;
limbno = n / BITS_PER_MPI_LIMB;
bitno = n % BITS_PER_MPI_LIMB;
if ( limbno >= a->nlimbs )
{
+ for (i=a->nlimbs; i < a->alloced; i++)
+ a->d[i] = 0;
mpi_resize (a, limbno+1 );
a->nlimbs = limbno+1;
}
@@ -134,13 +136,15 @@ gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n )
void
gcry_mpi_set_highbit( gcry_mpi_t a, unsigned int n )
{
- unsigned int limbno, bitno;
+ unsigned int i, limbno, bitno;
limbno = n / BITS_PER_MPI_LIMB;
bitno = n % BITS_PER_MPI_LIMB;
if ( limbno >= a->nlimbs )
{
+ for (i=a->nlimbs; i < a->alloced; i++)
+ a->d[i] = 0;
mpi_resize (a, limbno+1 );
a->nlimbs = limbno+1;
}
diff --git a/tests/t-mpi-bit.c b/tests/t-mpi-bit.c
index 85bd32e9..f1c90a3a 100644
--- a/tests/t-mpi-bit.c
+++ b/tests/t-mpi-bit.c
@@ -327,6 +327,58 @@ test_lshift (int pass)
}
+/* Bug fixed on 2014-05-09:
+ a = gcry_mpi_new (1523);
+ gcry_mpi_set_bit (a, 1536);
+ didn't initialized all limbs in A. */
+static void
+set_bit_with_resize (void)
+{
+ gcry_mpi_t a;
+ int i;
+
+ wherestr = "set_bit_with_resize";
+ show ("checking that set_bit initializes all limbs\n");
+
+ a = gcry_mpi_new (1536);
+ gcry_mpi_set_bit (a, 1536);
+
+ if (!gcry_mpi_test_bit (a, 1536))
+ fail ("failed to set a bit\n");
+ for (i=0; i < 1536; i++)
+ {
+ if (gcry_mpi_test_bit (a, i))
+ {
+ fail ("spurious bit detected\n");
+ break;
+ }
+ }
+ if (gcry_mpi_test_bit (a, 1537))
+ fail ("more bits set than expected\n");
+ gcry_mpi_release (a);
+
+ wherestr = "set_highbit_with_resize";
+ show ("checking that set_highbit initializes all limbs\n");
+
+ a = gcry_mpi_new (1536);
+ gcry_mpi_set_highbit (a, 1536);
+
+ if (!gcry_mpi_test_bit (a, 1536))
+ fail ("failed to set a bit\n");
+ for (i=0; i < 1536; i++)
+ {
+ if (gcry_mpi_test_bit (a, i))
+ {
+ fail ("spurious bit detected\n");
+ break;
+ }
+ }
+ if (gcry_mpi_test_bit (a, 1537))
+ fail ("more bits set than expected\n");
+ gcry_mpi_release (a);
+}
+
+
int
main (int argc, char **argv)
{
@@ -356,6 +408,8 @@ main (int argc, char **argv)
for (i=0; i < 5; i++)
test_lshift (i); /* Run several times due to random initializations. */
+ set_bit_with_resize ();
+
show ("All tests completed. Errors: %d\n", error_count);
return error_count ? 1 : 0;
}