Skip to content

Commit 55f71cb

Browse files
committed
[fix] ASN.1 BitString pad bits being out of range
has been surfacing on CI a few times as: ``` Java::JavaLang::IllegalArgumentException: pad bits cannot be greater than 7 or less than 0 org.bouncycastle.asn1.ASN1BitString.<init>(Unknown Source) org.bouncycastle.asn1.DERBitString.<init>(Unknown Source) org.jruby.ext.openssl.ASN1$Primitive.toASN1Primitive(ASN1.java:1687) org.jruby.ext.openssl.ASN1$Primitive.toASN1(ASN1.java:1620) org.jruby.ext.openssl.ASN1$Constructive.addEntry(ASN1.java:1991) org.jruby.ext.openssl.ASN1$Constructive.toASN1EncodableVector(ASN1.java:1955) org.jruby.ext.openssl.ASN1$Constructive.toASN1(ASN1.java:1838) org.jruby.ext.openssl.ASN1$Constructive.addEntry(ASN1.java:1994) org.jruby.ext.openssl.ASN1$Constructive.toASN1EncodableVector(ASN1.java:1955) org.jruby.ext.openssl.ASN1$Constructive.toASN1(ASN1.java:1838) org.jruby.ext.openssl.ASN1$ASN1Data.toDER(ASN1.java:1421) ```
1 parent 969f7dc commit 55f71cb

File tree

1 file changed

+8
-14
lines changed

1 file changed

+8
-14
lines changed

src/main/java/org/jruby/ext/openssl/ASN1.java

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -945,7 +945,7 @@ static IRubyObject decodeObject(final ThreadContext context,
945945

946946
if ( obj instanceof ASN1BitString ) {
947947
final ASN1BitString derObj = (ASN1BitString) obj;
948-
RubyString str = runtime.newString( new ByteList(derObj.getBytes(), false) );
948+
RubyString str = runtime.newString(new ByteList(derObj.getBytes(), false));
949949
IRubyObject bitString = ASN1.getClass("BitString").newInstance(context, str, Block.NULL_BLOCK);
950950
bitString.getInstanceVariables().setInstanceVariable("@unused_bits", runtime.newFixnum(derObj.getPadBits()));
951951
return bitString;
@@ -1669,22 +1669,16 @@ private ASN1Encodable toASN1Primitive(final ThreadContext context) {
16691669
return new DEROctetString( val.asString().getBytes() );
16701670
}
16711671
if ( type == DERBitString.class ) {
1672-
final byte[] bs = val.asString().getBytes();
1673-
int unused = 0;
1674-
for ( int i = (bs.length - 1); i > -1; i-- ) {
1675-
if (bs[i] == 0) unused += 8;
1676-
else {
1677-
byte v2 = bs[i];
1678-
int x = 8;
1679-
while ( v2 != 0 ) {
1680-
v2 <<= 1;
1681-
x--;
1682-
}
1683-
unused += x;
1672+
final byte[] data = val.asString().getBytes();
1673+
int padBits = 0; // padBits < 8 && padBits >= 0
1674+
for (int i = (data.length - 1); i > -1; i--) {
1675+
int b = Byte.toUnsignedInt(data[i]);
1676+
if (b != 0) {
1677+
padBits = Integer.numberOfTrailingZeros(b);
16841678
break;
16851679
}
16861680
}
1687-
return new DERBitString(bs, unused);
1681+
return new DERBitString(data, padBits);
16881682
}
16891683
if ( type == DERIA5String.class ) {
16901684
return new DERIA5String( val.asString().toString() );

0 commit comments

Comments
 (0)