Fix several BigInteger failures.

From Java 7 on, BigInteger also accepts a leading "+" in its string
constructors.

BigInteger has always claimed to accept non-ASCII digits, but our
implementation never has.

BigInteger.isProbablePrime is defined to return true for certainty <= 0,
but OpenSSL (on which we're based) takes the opposite stance.

Change-Id: I00bfc591a4d583460f71b7eec3de91bf6b03cd87
diff --git a/libcore/luni/src/test/java/java/math/BigIntegerTest.java b/libcore/luni/src/test/java/java/math/BigIntegerTest.java
index 831ed62..ec63e20 100644
--- a/libcore/luni/src/test/java/java/math/BigIntegerTest.java
+++ b/libcore/luni/src/test/java/java/math/BigIntegerTest.java
@@ -30,13 +30,10 @@
         new BigInteger("1a", 16);
         new BigInteger("-1", 10);
         new BigInteger("-1a", 16);
+        // This is allowed from Java 7 on.
+        new BigInteger("+1");
         // Now check the invalid cases...
         try {
-            new BigInteger("+1"); // no positive sign allowed.
-            fail();
-        } catch (NumberFormatException expected) {
-        }
-        try {
             new BigInteger("-a"); // no digits from other bases.
             fail();
         } catch (NumberFormatException expected) {
diff --git a/libcore/math/src/main/java/java/math/BigInt.java b/libcore/math/src/main/java/java/math/BigInt.java
index d1bd29b..76ed1ff 100644
--- a/libcore/math/src/main/java/java/math/BigInt.java
+++ b/libcore/math/src/main/java/java/math/BigInt.java
@@ -151,49 +151,80 @@
         Check(NativeBN.putULongInt(this.bignum, val, neg));
     }
 
-    public void putDecString(String str) {
-        checkString(str, 10);
+    public void putDecString(String original) {
+        String s = checkString(original, 10);
         this.makeValid();
-        int usedLen = NativeBN.BN_dec2bn(this.bignum, str);
+        int usedLen = NativeBN.BN_dec2bn(this.bignum, s);
         Check((usedLen > 0));
-        if (usedLen < str.length()) {
-            throw new NumberFormatException(str);
+        if (usedLen < s.length()) {
+            throw new NumberFormatException(original);
         }
     }
 
-    public void putHexString(String str) {
-        checkString(str, 16);
+    public void putHexString(String original) {
+        String s = checkString(original, 16);
         this.makeValid();
-        int usedLen = NativeBN.BN_hex2bn(this.bignum, str);
+        int usedLen = NativeBN.BN_hex2bn(this.bignum, s);
         Check((usedLen > 0));
-        if (usedLen < str.length()) {
-            throw new NumberFormatException(str);
+        if (usedLen < s.length()) {
+            throw new NumberFormatException(original);
         }
     }
 
     /**
+     * Returns a string suitable for passing to OpenSSL.
      * Throws if 's' doesn't match Java's rules for valid BigInteger strings.
      * BN_dec2bn and BN_hex2bn do very little checking, so we need to manually
      * ensure we comply with Java's rules.
      * http://code.google.com/p/android/issues/detail?id=7036
      */
-    public void checkString(String s, int radix) {
+    public String checkString(String s, int radix) {
         if (s == null) {
             throw new NullPointerException();
         }
-        // A valid big integer consists of an optional '-' followed by
+        // A valid big integer consists of an optional '-' or '+' followed by
         // one or more digit characters appropriate to the given radix,
         // and no other characters.
-        final int charCount = s.length();
-        int i = (charCount > 0 && s.charAt(0) == '-') ? 1 : 0;
+        int charCount = s.length();
+        int i = 0;
+        if (charCount > 0) {
+            char ch = s.charAt(0);
+            if (ch == '+') {
+                // Java supports leading +, but OpenSSL doesn't, so we need to strip it.
+                s = s.substring(1);
+                --charCount;
+            } else if (ch == '-') {
+                ++i;
+            }
+        }
         if (charCount - i == 0) {
             throw new NumberFormatException(s);
         }
+        boolean nonAscii = false;
         for (; i < charCount; ++i) {
-            if (Character.digit(s.charAt(i), radix) == -1) {
+            char ch = s.charAt(i);
+            if (Character.digit(ch, radix) == -1) {
                 throw new NumberFormatException(s);
             }
+            if (ch < '0' || ch > '9') {
+                nonAscii = true;
+            }
         }
+        return nonAscii ? toAscii(s) : s;
+    }
+
+    // Java supports non-ASCII digits, but OpenSSL doesn't.
+    private static String toAscii(String s) {
+        int length = s.length();
+        StringBuilder result = new StringBuilder(length);
+        for (int i = 0; i < length; ++i) {
+            char ch = s.charAt(i);
+            if (ch != '-') {
+                ch = (char) ('0' + Character.digit(ch, 10));
+            }
+            result.append(ch);
+        }
+        return result.toString();
     }
 
     public void putBigEndian(byte[] a, boolean neg) {
diff --git a/libcore/math/src/main/java/java/math/BigInteger.java b/libcore/math/src/main/java/java/math/BigInteger.java
index 1fbeb48..adef534 100644
--- a/libcore/math/src/main/java/java/math/BigInteger.java
+++ b/libcore/math/src/main/java/java/math/BigInteger.java
@@ -271,8 +271,9 @@
 
     /**
      * Constructs a new {@code BigInteger} instance from the string
-     * representation. The string representation consists of an optional minus
+     * representation. The string representation consists of an optional plus or minus
      * sign followed by a non-empty sequence of decimal digits.
+     * Digits are interpreted as if by {@code Character.digit(char, 10)}.
      * 
      * @param val
      *            string representation of the new {@code BigInteger}.
@@ -291,10 +292,9 @@
 
     /**
      * Constructs a new {@code BigInteger} instance from the string
-     * representation. The string representation consists of an optional minus
+     * representation. The string representation consists of an optional plus or minus
      * sign followed by a non-empty sequence of digits in the specified radix.
-     * For the conversion the method {@code Character.digit(char, radix)} is
-     * used.
+     * Digits are interpreted as if by {@code Character.digit(char, radix)}.
      * 
      * @param val
      *            string representation of the new {@code BigInteger}.
@@ -1215,6 +1215,9 @@
      *         otherwise.
      */
     public boolean isProbablePrime(int certainty) {
+        if (certainty <= 0) {
+            return true;
+        }
         validate1("isProbablePrime", this);
         return bigInt.isPrime(certainty, null, null);
     }