Fix some more negative zeros and add tests for each case.
See https://github.com/openssl/openssl/pull/1672.
Change-Id: I4c93a568b9b7ce582b03e955d3aa9cb6b0e89794
Reviewed-on: https://boringssl-review.googlesource.com/12314
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/bn/bn_test.cc b/crypto/bn/bn_test.cc
index efb6bc5..672d83f 100644
--- a/crypto/bn/bn_test.cc
+++ b/crypto/bn/bn_test.cc
@@ -1203,6 +1203,37 @@
return false;
}
+ // Test that |BN_rshift| and |BN_rshift1| will not produce a negative zero.
+ if (!BN_set_word(a.get(), 1)) {
+ return false;
+ }
+
+ BN_set_negative(a.get(), 1);
+ if (!BN_rshift(b.get(), a.get(), 1) ||
+ !BN_rshift1(c.get(), a.get())) {
+ return false;
+ }
+
+ if (!BN_is_zero(b.get()) || BN_is_negative(b.get())) {
+ fprintf(stderr, "BN_rshift(-1, 1) produced the wrong result.\n");
+ return false;
+ }
+
+ if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
+ fprintf(stderr, "BN_rshift1(-1) produced the wrong result.\n");
+ return false;
+ }
+
+ // Test that |BN_div_word| will not produce a negative zero.
+ if (BN_div_word(a.get(), 2) == (BN_ULONG)-1) {
+ return false;
+ }
+
+ if (!BN_is_zero(a.get()) || BN_is_negative(a.get())) {
+ fprintf(stderr, "BN_div_word(-1, 2) produced the wrong result.\n");
+ return false;
+ }
+
return true;
}
diff --git a/crypto/bn/div.c b/crypto/bn/div.c
index 03577f2..ab49281 100644
--- a/crypto/bn/div.c
+++ b/crypto/bn/div.c
@@ -628,6 +628,10 @@
a->top--;
}
+ if (a->top == 0) {
+ a->neg = 0;
+ }
+
ret >>= j;
return ret;
}
diff --git a/crypto/bn/shift.c b/crypto/bn/shift.c
index defec92..22006d1 100644
--- a/crypto/bn/shift.c
+++ b/crypto/bn/shift.c
@@ -182,6 +182,10 @@
}
}
+ if (r->top == 0) {
+ r->neg = 0;
+ }
+
return 1;
}
@@ -215,6 +219,10 @@
}
r->top = j;
+ if (r->top == 0) {
+ r->neg = 0;
+ }
+
return 1;
}