Skip to content

Commit a7e5f9e

Browse files
committed
use copy on write for internal arrays in Store
keep the synchronized basically restricted to write operations. follow up of #14 Sponsored by Lookout Inc.
1 parent ae46d1d commit a7e5f9e

File tree

1 file changed

+44
-50
lines changed
  • src/main/java/org/jruby/ext/openssl/x509store

1 file changed

+44
-50
lines changed

src/main/java/org/jruby/ext/openssl/x509store/Store.java

Lines changed: 44 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.io.FileNotFoundException;
3535
import java.security.cert.X509Certificate;
3636
import java.util.ArrayList;
37+
import java.util.Arrays;
3738
import java.util.List;
3839

3940
import javax.net.ssl.X509TrustManager;
@@ -113,8 +114,8 @@ public int call(StoreContext context) {
113114

114115
@Deprecated int cache = 1; // not-used
115116

116-
private final List<X509Object> objects;
117-
private final List<Lookup> certificateMethods;
117+
private X509Object[] objects = new X509Object[0];
118+
private Lookup[] certificateMethods = new Lookup[0];
118119

119120
public final VerifyParameter verifyParameter;
120121

@@ -135,9 +136,6 @@ public int call(StoreContext context) {
135136
* c: X509_STORE_new
136137
*/
137138
public Store() {
138-
objects = new ArrayList<X509Object>();
139-
certificateMethods = new ArrayList<Lookup>();
140-
141139
verifyParameter = new VerifyParameter();
142140

143141
extraData = new ArrayList<Object>(10);
@@ -147,15 +145,11 @@ public Store() {
147145
}
148146

149147
public List<X509Object> getObjects() {
150-
synchronized(objects) {
151-
return new ArrayList<X509Object>(objects);
152-
}
148+
return Arrays.asList(objects);
153149
}
154150

155151
public List<Lookup> getCertificateMethods() {
156-
synchronized(certificateMethods) {
157-
return new ArrayList<Lookup>(certificateMethods);
158-
}
152+
return Arrays.asList(certificateMethods);
159153
}
160154

161155
public VerifyParameter getVerifyParameter() {
@@ -188,11 +182,9 @@ public void setVerifyCallbackFunction(VerifyCallbackFunction func) {
188182
* c: X509_STORE_free
189183
*/
190184
public void free() throws Exception {
191-
synchronized(certificateMethods) {
192-
for (Lookup lu : certificateMethods) {
193-
lu.shutdown();
194-
lu.free();
195-
}
185+
for (Lookup lu : certificateMethods) {
186+
lu.shutdown();
187+
lu.free();
196188
}
197189
if (verifyParameter != null) {
198190
verifyParameter.free();
@@ -258,56 +250,60 @@ public int setParam(VerifyParameter pm) {
258250
* c: X509_STORE_add_lookup
259251
*/
260252
public Lookup addLookup(Ruby runtime, final LookupMethod method) throws Exception {
261-
synchronized(certificateMethods) {
262-
for ( Lookup lookup : certificateMethods ) {
263-
if ( lookup.equals(method) ) return lookup;
264-
}
265-
Lookup lookup = new Lookup(runtime, method);
266-
lookup.store = this;
267-
certificateMethods.add(lookup);
268-
return lookup;
253+
for ( Lookup lookup : certificateMethods ) {
254+
if ( lookup.equals(method) ) return lookup;
269255
}
256+
return doAddLookup(runtime, method);
257+
}
258+
259+
private synchronized Lookup doAddLookup(Ruby runtime, final LookupMethod method) throws Exception {
260+
Lookup lookup = new Lookup(runtime, method);
261+
lookup.store = this;
262+
Lookup[] newCertificateMethods = Arrays.copyOf(certificateMethods, certificateMethods.length + 1);
263+
newCertificateMethods[certificateMethods.length] = lookup;
264+
certificateMethods = newCertificateMethods;
265+
return lookup;
270266
}
271267

272268
/**
273269
* c: X509_STORE_add_cert
274270
*/
275-
public int addCertificate(final X509Certificate cert) {
271+
public synchronized int addCertificate(final X509Certificate cert) {
276272
if ( cert == null ) return 0;
277273

278274
final Certificate certObj = new Certificate();
279275
certObj.x509 = StoreContext.ensureAux(cert);
280276

281277
int ret = 1;
282-
synchronized (objects) {
283-
if ( X509Object.retrieveMatch(objects,certObj) != null ) {
284-
X509Error.addError(X509_R_CERT_ALREADY_IN_HASH_TABLE);
285-
ret = 0;
286-
}
287-
else {
288-
objects.add(certObj);
289-
}
278+
if ( X509Object.retrieveMatch(getObjects(), certObj) != null ) {
279+
X509Error.addError(X509_R_CERT_ALREADY_IN_HASH_TABLE);
280+
ret = 0;
281+
}
282+
else {
283+
X509Object[] newObjects = Arrays.copyOf(objects, objects.length + 1);
284+
newObjects[objects.length] = certObj;
285+
objects = newObjects;
290286
}
291287
return ret;
292288
}
293289

294290
/**
295291
* c: X509_STORE_add_crl
296292
*/
297-
public int addCRL(final java.security.cert.CRL crl) {
293+
public synchronized int addCRL(final java.security.cert.CRL crl) {
298294
if ( crl == null ) return 0;
299295

300296
final CRL crlObj = new CRL(); crlObj.crl = crl;
301297

302298
int ret = 1;
303-
synchronized (objects) {
304-
if ( X509Object.retrieveMatch(objects,crlObj) != null ) {
305-
X509Error.addError(X509_R_CERT_ALREADY_IN_HASH_TABLE);
306-
ret = 0;
307-
}
308-
else {
309-
objects.add(crlObj);
310-
}
299+
if ( X509Object.retrieveMatch(getObjects(), crlObj) != null ) {
300+
X509Error.addError(X509_R_CERT_ALREADY_IN_HASH_TABLE);
301+
ret = 0;
302+
}
303+
else {
304+
X509Object[] newObjects = Arrays.copyOf(objects, objects.length + 1);
305+
newObjects[objects.length] = crlObj;
306+
objects = newObjects;
311307
}
312308
return ret;
313309
}
@@ -379,16 +375,14 @@ public void checkServerTrusted(X509Certificate[] chain, String authType) {
379375
}
380376

381377
@Override
382-
public X509Certificate[] getAcceptedIssuers() {
383-
synchronized(objects) {
384-
ArrayList<X509Certificate> issuers = new ArrayList<X509Certificate>(objects.size());
385-
for ( X509Object object : objects ) {
386-
if ( object instanceof Certificate ) {
387-
issuers.add( ( (Certificate) object ).x509 );
388-
}
378+
public synchronized X509Certificate[] getAcceptedIssuers() {
379+
ArrayList<X509Certificate> issuers = new ArrayList<X509Certificate>(objects.length);
380+
for ( X509Object object : objects ) {
381+
if ( object instanceof Certificate ) {
382+
issuers.add( ( (Certificate) object ).x509 );
389383
}
390-
return issuers.toArray( new X509Certificate[ issuers.size() ] );
391384
}
385+
return issuers.toArray( new X509Certificate[ issuers.size() ] );
392386
}
393387

394388
}// X509_STORE

0 commit comments

Comments
 (0)