(lockList);
+ lockList.clear();
+ return result;
}
}
diff --git a/jdk/src/share/classes/sun/nio/ch/FileLockImpl.java b/jdk/src/share/classes/sun/nio/ch/FileLockImpl.java
index 9efd1532b50..8f12bcf0fdb 100644
--- a/jdk/src/share/classes/sun/nio/ch/FileLockImpl.java
+++ b/jdk/src/share/classes/sun/nio/ch/FileLockImpl.java
@@ -31,25 +31,24 @@ import java.nio.channels.*;
public class FileLockImpl
extends FileLock
{
- boolean valid;
+ private volatile boolean valid = true;
FileLockImpl(FileChannel channel, long position, long size, boolean shared)
{
super(channel, position, size, shared);
- this.valid = true;
}
FileLockImpl(AsynchronousFileChannel channel, long position, long size, boolean shared)
{
super(channel, position, size, shared);
- this.valid = true;
}
- public synchronized boolean isValid() {
+ public boolean isValid() {
return valid;
}
- synchronized void invalidate() {
+ void invalidate() {
+ assert Thread.holdsLock(this);
valid = false;
}
@@ -66,5 +65,4 @@ public class FileLockImpl
valid = false;
}
}
-
}
diff --git a/jdk/src/share/classes/sun/nio/ch/FileLockTable.java b/jdk/src/share/classes/sun/nio/ch/FileLockTable.java
index 137ab88872b..39cee5abfe8 100644
--- a/jdk/src/share/classes/sun/nio/ch/FileLockTable.java
+++ b/jdk/src/share/classes/sun/nio/ch/FileLockTable.java
@@ -60,23 +60,12 @@ abstract class FileLockTable {
*/
public abstract void remove(FileLock fl);
- /**
- * An implementation of this interface releases a given file lock.
- * Used with removeAll.
- */
- public abstract interface Releaser {
- void release(FileLock fl) throws IOException;
- }
-
/**
* Removes all file locks from the table.
- *
- * The Releaser#release method is invoked for each file lock before
- * it is removed.
*
- * @throws IOException if the release method throws IOException
+ * @return The list of file locks removed
*/
- public abstract void removeAll(Releaser r) throws IOException;
+ public abstract List removeAll();
/**
* Replaces an existing file lock in the table.
@@ -195,7 +184,7 @@ class SharedFileLockTable extends FileLockTable {
FileLockReference ref = list.get(index);
FileLock lock = ref.get();
if (lock == fl) {
- assert (lock != null) && (lock.channel() == channel);
+ assert (lock != null) && (lock.acquiredBy() == channel);
ref.clear();
list.remove(index);
break;
@@ -206,7 +195,8 @@ class SharedFileLockTable extends FileLockTable {
}
@Override
- public void removeAll(Releaser releaser) throws IOException {
+ public List removeAll() {
+ List result = new ArrayList();
List list = lockMap.get(fileKey);
if (list != null) {
synchronized (list) {
@@ -216,13 +206,13 @@ class SharedFileLockTable extends FileLockTable {
FileLock lock = ref.get();
// remove locks obtained by this channel
- if (lock != null && lock.channel() == channel) {
- // invoke the releaser to invalidate/release the lock
- releaser.release(lock);
-
+ if (lock != null && lock.acquiredBy() == channel) {
// remove the lock from the list
ref.clear();
list.remove(index);
+
+ // add to result
+ result.add(lock);
} else {
index++;
}
@@ -232,6 +222,7 @@ class SharedFileLockTable extends FileLockTable {
removeKeyIfEmpty(fileKey, list);
}
}
+ return result;
}
@Override
diff --git a/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java
index 52fe5a2802f..fb82f330be4 100644
--- a/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java
+++ b/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java
@@ -97,6 +97,9 @@ public class SimpleAsynchronousFileChannelImpl
// then it will throw ClosedChannelException
}
+ // Invalidate and release any locks that we still hold
+ invalidateAllLocks();
+
// signal any threads blocked on this channel
nd.preClose(fdObj);
threads.signalAndWait();
@@ -109,9 +112,6 @@ public class SimpleAsynchronousFileChannelImpl
closeLock.writeLock().unlock();
}
- // Invalidate and release any locks that we still hold
- invalidateAllLocks();
-
// close file
nd.close(fdObj);
@@ -226,11 +226,9 @@ public class SimpleAsynchronousFileChannelImpl
do {
n = nd.lock(fdObj, true, position, size, shared);
} while ((n == FileDispatcher.INTERRUPTED) && isOpen());
- if (n == FileDispatcher.LOCKED) {
+ if (n == FileDispatcher.LOCKED && isOpen()) {
result.setResult(fli);
} else {
- if (n != FileDispatcher.INTERRUPTED)
- throw new AssertionError();
throw new AsynchronousCloseException();
}
} catch (IOException x) {
@@ -279,16 +277,16 @@ public class SimpleAsynchronousFileChannelImpl
do {
n = nd.lock(fdObj, false, position, size, shared);
} while ((n == FileDispatcher.INTERRUPTED) && isOpen());
- if (n != FileDispatcher.LOCKED) {
- if (n == FileDispatcher.NO_LOCK)
- return null; // locked by someone else
- if (n == FileDispatcher.INTERRUPTED)
- throw new AsynchronousCloseException();
- // should not get here
- throw new AssertionError();
+ if (n == FileDispatcher.LOCKED && isOpen()) {
+ gotLock = true;
+ return fli; // lock acquired
}
- gotLock = true;
- return fli;
+ if (n == FileDispatcher.NO_LOCK)
+ return null; // locked by someone else
+ if (n == FileDispatcher.INTERRUPTED)
+ throw new AsynchronousCloseException();
+ // should not get here
+ throw new AssertionError();
} finally {
if (!gotLock)
removeFromFileLockTable(fli);
@@ -298,14 +296,8 @@ public class SimpleAsynchronousFileChannelImpl
}
@Override
- void release(FileLockImpl fli) throws IOException {
- try {
- begin();
- nd.release(fdObj, fli.position(), fli.size());
- removeFromFileLockTable(fli);
- } finally {
- end();
- }
+ protected void implRelease(FileLockImpl fli) throws IOException {
+ nd.release(fdObj, fli.position(), fli.size());
}
@Override
diff --git a/jdk/src/share/classes/sun/security/krb5/Config.java b/jdk/src/share/classes/sun/security/krb5/Config.java
index 07c78e2959a..e036776f53e 100644
--- a/jdk/src/share/classes/sun/security/krb5/Config.java
+++ b/jdk/src/share/classes/sun/security/krb5/Config.java
@@ -736,6 +736,14 @@ public class Config {
return name;
}
+ private static String trimmed(String s) {
+ s = s.trim();
+ if (s.charAt(0) == '"' && s.charAt(s.length()-1) == '"' ||
+ s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\'') {
+ s = s.substring(1, s.length()-1).trim();
+ }
+ return s;
+ }
/**
* Parses key-value pairs under a stanza name.
*/
@@ -747,7 +755,7 @@ public class Config {
for (int j = 0; j < line.length(); j++) {
if (line.charAt(j) == '=') {
String key = (line.substring(0, j)).trim();
- String value = (line.substring(j + 1)).trim();
+ String value = trimmed(line.substring(j + 1));
table.put(key, value);
break;
}
@@ -820,7 +828,7 @@ public class Config {
} else {
nameVector = table.get(key);
}
- nameVector.addElement((line.substring(j + 1)).trim());
+ nameVector.addElement(trimmed(line.substring(j + 1)));
table.put(key, nameVector);
break;
}
@@ -1263,4 +1271,32 @@ public class Config {
}
}
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ toStringIndented("", stanzaTable, sb);
+ return sb.toString();
+ }
+ private static void toStringIndented(String prefix, Object obj,
+ StringBuffer sb) {
+ if (obj instanceof String) {
+ sb.append(prefix);
+ sb.append(obj);
+ sb.append('\n');
+ } else if (obj instanceof Hashtable) {
+ Hashtable tab = (Hashtable)obj;
+ for (Object o: tab.keySet()) {
+ sb.append(prefix);
+ sb.append(o);
+ sb.append(" = {\n");
+ toStringIndented(prefix + " ", tab.get(o), sb);
+ sb.append(prefix + "}\n");
+ }
+ } else if (obj instanceof Vector) {
+ Vector v = (Vector)obj;
+ for (Object o: v.toArray()) {
+ toStringIndented(prefix + " ", o, sb);
+ }
+ }
+ }
}
diff --git a/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java b/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java
index e9ff9cc04d5..259aedd66fa 100644
--- a/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java
+++ b/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java
@@ -274,27 +274,31 @@ public abstract class KrbKdcReq {
+ ",Attempt =" + i
+ ", #bytes=" + obuf.length);
}
- /*
- * Send the data to the kdc.
- */
+ try {
+ /*
+ * Send the data to the kdc.
+ */
kdcClient.send(obuf);
- /*
- * And get a response.
- */
- try {
- ibuf = kdcClient.receive();
- break;
- } catch (SocketTimeoutException se) {
- if (DEBUG) {
- System.out.println ("SocketTimeOutException with " +
- "attempt: " + i);
- }
- if (i == DEFAULT_KDC_RETRY_LIMIT) {
- ibuf = null;
- throw se;
+ /*
+ * And get a response.
+ */
+ try {
+ ibuf = kdcClient.receive();
+ break;
+ } catch (SocketTimeoutException se) {
+ if (DEBUG) {
+ System.out.println ("SocketTimeOutException with " +
+ "attempt: " + i);
+ }
+ if (i == DEFAULT_KDC_RETRY_LIMIT) {
+ ibuf = null;
+ throw se;
+ }
}
+ } finally {
+ kdcClient.close();
}
}
}
diff --git a/jdk/src/share/classes/sun/security/krb5/internal/UDPClient.java b/jdk/src/share/classes/sun/security/krb5/internal/UDPClient.java
index c9e440f1ef7..670df9210df 100644
--- a/jdk/src/share/classes/sun/security/krb5/internal/UDPClient.java
+++ b/jdk/src/share/classes/sun/security/krb5/internal/UDPClient.java
@@ -93,4 +93,7 @@ public class UDPClient {
return data;
}
+ public void close() {
+ dgSocket.close();
+ }
}
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java b/jdk/src/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java
index 701e104d529..1027df9ddb7 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,8 @@ import static sun.security.pkcs11.TemplateManager.*;
import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+import sun.security.rsa.RSAKeyFactory;
+
/**
* KeyPairGenerator implementation class. This class currently supports
* RSA, DSA, DH, and EC.
@@ -66,7 +68,7 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
private AlgorithmParameterSpec params;
// for RSA, selected or default value of public exponent, always valid
- private BigInteger rsaPublicExponent;
+ private BigInteger rsaPublicExponent = RSAKeyGenParameterSpec.F4;
// SecureRandom instance, if specified in init
private SecureRandom random;
@@ -88,19 +90,19 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
public void initialize(int keySize, SecureRandom random) {
token.ensureValid();
try {
- checkKeySize(keySize);
+ checkKeySize(keySize, null);
} catch (InvalidAlgorithmParameterException e) {
throw new InvalidParameterException(e.getMessage());
}
this.keySize = keySize;
this.params = null;
this.random = random;
- this.rsaPublicExponent = RSAKeyGenParameterSpec.F4;
if (algorithm.equals("EC")) {
params = P11ECKeyFactory.getECParameterSpec(keySize);
if (params == null) {
- throw new InvalidParameterException
- ("No EC parameters available for key size " + keySize + " bits");
+ throw new InvalidParameterException(
+ "No EC parameters available for key size "
+ + keySize + " bits");
}
}
}
@@ -115,8 +117,10 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
("DHParameterSpec required for Diffie-Hellman");
}
DHParameterSpec dhParams = (DHParameterSpec)params;
- this.keySize = dhParams.getP().bitLength();
- this.params = params;
+ int tmpKeySize = dhParams.getP().bitLength();
+ checkKeySize(tmpKeySize, dhParams);
+ this.keySize = tmpKeySize;
+ this.params = dhParams;
// XXX sanity check params
} else if (algorithm.equals("RSA")) {
if (params instanceof RSAKeyGenParameterSpec == false) {
@@ -124,7 +128,9 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
("RSAKeyGenParameterSpec required for RSA");
}
RSAKeyGenParameterSpec rsaParams = (RSAKeyGenParameterSpec)params;
- this.keySize = rsaParams.getKeysize();
+ int tmpKeySize = rsaParams.getKeysize();
+ checkKeySize(tmpKeySize, rsaParams);
+ this.keySize = tmpKeySize;
this.params = null;
this.rsaPublicExponent = rsaParams.getPublicExponent();
// XXX sanity check params
@@ -134,13 +140,16 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
("DSAParameterSpec required for DSA");
}
DSAParameterSpec dsaParams = (DSAParameterSpec)params;
- this.keySize = dsaParams.getP().bitLength();
- this.params = params;
+ int tmpKeySize = dsaParams.getP().bitLength();
+ checkKeySize(tmpKeySize, dsaParams);
+ this.keySize = tmpKeySize;
+ this.params = dsaParams;
// XXX sanity check params
} else if (algorithm.equals("EC")) {
ECParameterSpec ecParams;
if (params instanceof ECParameterSpec) {
- ecParams = P11ECKeyFactory.getECParameterSpec((ECParameterSpec)params);
+ ecParams = P11ECKeyFactory.getECParameterSpec(
+ (ECParameterSpec)params);
if (ecParams == null) {
throw new InvalidAlgorithmParameterException
("Unsupported curve: " + params);
@@ -156,16 +165,17 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
throw new InvalidAlgorithmParameterException
("ECParameterSpec or ECGenParameterSpec required for EC");
}
- this.keySize = ecParams.getCurve().getField().getFieldSize();
+ int tmpKeySize = ecParams.getCurve().getField().getFieldSize();
+ checkKeySize(tmpKeySize, ecParams);
+ this.keySize = tmpKeySize;
this.params = ecParams;
} else {
throw new ProviderException("Unknown algorithm: " + algorithm);
}
this.random = random;
- checkKeySize(keySize);
}
- private void checkKeySize(int keySize)
+ private void checkKeySize(int keySize, AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException {
if (algorithm.equals("EC")) {
if (keySize < 112) {
@@ -178,13 +188,28 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
("Key size must be at most 2048 bit");
}
return;
+ } else if (algorithm.equals("RSA")) {
+ BigInteger tmpExponent = rsaPublicExponent;
+ if (params != null) {
+ // Already tested for instanceof RSAKeyGenParameterSpec above
+ tmpExponent =
+ ((RSAKeyGenParameterSpec)params).getPublicExponent();
+ }
+ try {
+ // This provider supports 64K or less.
+ RSAKeyFactory.checkKeyLengths(keySize, tmpExponent,
+ 512, 64 * 1024);
+ } catch (InvalidKeyException e) {
+ throw new InvalidAlgorithmParameterException(e.getMessage());
+ }
+ return;
}
+
if (keySize < 512) {
throw new InvalidAlgorithmParameterException
("Key size must be at least 512 bit");
}
- if (algorithm.equals("RSA") ||
- (algorithm.equals("DH") && (params != null))) {
+ if (algorithm.equals("DH") && (params != null)) {
// sanity check, nobody really wants keys this large
if (keySize > 64 * 1024) {
throw new InvalidAlgorithmParameterException
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11KeyStore.java b/jdk/src/share/classes/sun/security/pkcs11/P11KeyStore.java
index 839a2f3ba64..b0e20711dc8 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11KeyStore.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11KeyStore.java
@@ -80,6 +80,8 @@ import static sun.security.pkcs11.P11Util.*;
import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+import sun.security.rsa.RSAKeyFactory;
+
final class P11KeyStore extends KeyStoreSpi {
private static final CK_ATTRIBUTE ATTR_CLASS_CERT =
@@ -1328,6 +1330,15 @@ final class P11KeyStore extends KeyStoreSpi {
BigInteger modulus = attrs[0].getBigInteger();
keyLength = modulus.bitLength();
+ // This check will combine our "don't care" values here
+ // with the system-wide min/max values.
+ try {
+ RSAKeyFactory.checkKeyLengths(keyLength, null,
+ -1, Integer.MAX_VALUE);
+ } catch (InvalidKeyException e) {
+ throw new KeyStoreException(e.getMessage());
+ }
+
return P11Key.privateKey(session,
oHandle,
keyType,
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java b/jdk/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java
index 5f3cbbf93c9..1bd764d326e 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,8 @@ import static sun.security.pkcs11.TemplateManager.*;
import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+import sun.security.rsa.RSAKeyFactory;
+
/**
* RSA KeyFactory implemenation.
*
@@ -131,6 +133,9 @@ final class P11RSAKeyFactory extends P11KeyFactory {
} catch (PKCS11Exception e) {
throw new InvalidKeySpecException
("Could not create RSA public key", e);
+ } catch (InvalidKeyException e) {
+ throw new InvalidKeySpecException
+ ("Could not create RSA public key", e);
}
}
@@ -175,11 +180,15 @@ final class P11RSAKeyFactory extends P11KeyFactory {
} catch (PKCS11Exception e) {
throw new InvalidKeySpecException
("Could not create RSA private key", e);
+ } catch (InvalidKeyException e) {
+ throw new InvalidKeySpecException
+ ("Could not create RSA private key", e);
}
}
private PublicKey generatePublic(BigInteger n, BigInteger e)
- throws PKCS11Exception {
+ throws PKCS11Exception, InvalidKeyException {
+ RSAKeyFactory.checkKeyLengths(n.bitLength(), e, -1, 64 * 1024);
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
@@ -200,7 +209,8 @@ final class P11RSAKeyFactory extends P11KeyFactory {
}
private PrivateKey generatePrivate(BigInteger n, BigInteger d)
- throws PKCS11Exception {
+ throws PKCS11Exception, InvalidKeyException {
+ RSAKeyFactory.checkKeyLengths(n.bitLength(), null, -1, 64 * 1024);
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
@@ -222,7 +232,9 @@ final class P11RSAKeyFactory extends P11KeyFactory {
private PrivateKey generatePrivate(BigInteger n, BigInteger e,
BigInteger d, BigInteger p, BigInteger q, BigInteger pe,
- BigInteger qe, BigInteger coeff) throws PKCS11Exception {
+ BigInteger qe, BigInteger coeff) throws PKCS11Exception,
+ InvalidKeyException {
+ RSAKeyFactory.checkKeyLengths(n.bitLength(), e, -1, 64 * 1024);
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
diff --git a/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java b/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java
index b6eb1c258f4..6d0e045f2ee 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java
@@ -120,11 +120,13 @@ public final class SunPKCS11 extends AuthProvider {
}
/**
- * @deprecated use new SunPKCS11(String) or new SunPKCS11(InputStream) instead
+ * @deprecated use new SunPKCS11(String) or new SunPKCS11(InputStream)
+ * instead
*/
@Deprecated
public SunPKCS11(String configName, InputStream configStream) {
- super("SunPKCS11-" + Config.getConfig(configName, configStream).getName(),
+ super("SunPKCS11-" +
+ Config.getConfig(configName, configStream).getName(),
1.7d, Config.getConfig(configName, configStream).getDescription());
this.configName = configName;
this.config = Config.removeConfig(configName);
@@ -153,7 +155,8 @@ public final class SunPKCS11 extends AuthProvider {
//
// If we are in Secmod mode and configured to use either the
// nssKeyStore or the nssTrustAnchors module, we automatically
- // switch to using the NSS trust attributes for trusted certs (KeyStore).
+ // switch to using the NSS trust attributes for trusted certs
+ // (KeyStore).
//
if (useSecmod) {
@@ -168,33 +171,40 @@ public final class SunPKCS11 extends AuthProvider {
if (secmod.isInitialized()) {
if (nssSecmodDirectory != null) {
String s = secmod.getConfigDir();
- if ((s != null) && (s.equals(nssSecmodDirectory) == false)) {
+ if ((s != null) &&
+ (s.equals(nssSecmodDirectory) == false)) {
throw new ProviderException("Secmod directory "
+ nssSecmodDirectory
- + " invalid, NSS already initialized with " + s);
+ + " invalid, NSS already initialized with "
+ + s);
}
}
if (nssLibraryDirectory != null) {
String s = secmod.getLibDir();
- if ((s != null) && (s.equals(nssLibraryDirectory) == false)) {
+ if ((s != null) &&
+ (s.equals(nssLibraryDirectory) == false)) {
throw new ProviderException("NSS library directory "
+ nssLibraryDirectory
- + " invalid, NSS already initialized with " + s);
+ + " invalid, NSS already initialized with "
+ + s);
}
}
} else {
if (nssDbMode != DbMode.NO_DB) {
if (nssSecmodDirectory == null) {
- throw new ProviderException("Secmod not initialized and "
- + "nssSecmodDirectory not specified");
+ throw new ProviderException(
+ "Secmod not initialized and "
+ + "nssSecmodDirectory not specified");
}
} else {
if (nssSecmodDirectory != null) {
- throw new ProviderException
- ("nssSecmodDirectory must not be specified in noDb mode");
+ throw new ProviderException(
+ "nssSecmodDirectory must not be "
+ + "specified in noDb mode");
}
}
- secmod.initialize(nssDbMode, nssSecmodDirectory, nssLibraryDirectory);
+ secmod.initialize(nssDbMode, nssSecmodDirectory,
+ nssLibraryDirectory);
}
} catch (IOException e) {
// XXX which exception to throw
@@ -211,7 +221,8 @@ public final class SunPKCS11 extends AuthProvider {
if (nssModule != null) {
moduleName = "fips";
} else {
- moduleName = (nssDbMode == DbMode.NO_DB) ? "crypto" : "keystore";
+ moduleName = (nssDbMode == DbMode.NO_DB) ?
+ "crypto" : "keystore";
}
}
if (moduleName.equals("fips")) {
@@ -253,10 +264,12 @@ public final class SunPKCS11 extends AuthProvider {
+ ": only " + k + " external NSS modules available");
}
} else {
- throw new ProviderException("Unknown NSS module: " + moduleName);
+ throw new ProviderException(
+ "Unknown NSS module: " + moduleName);
}
if (nssModule == null) {
- throw new ProviderException("NSS module not available: " + moduleName);
+ throw new ProviderException(
+ "NSS module not available: " + moduleName);
}
if (nssModule.hasInitializedProvider()) {
throw new ProviderException("Secmod module already configured");
@@ -296,8 +309,9 @@ public final class SunPKCS11 extends AuthProvider {
initArgs.flags = CKF_OS_LOCKING_OK;
PKCS11 tmpPKCS11;
try {
- tmpPKCS11 = PKCS11.getInstance
- (library, functionList, initArgs, config.getOmitInitialize());
+ tmpPKCS11 = PKCS11.getInstance(
+ library, functionList, initArgs,
+ config.getOmitInitialize());
} catch (PKCS11Exception e) {
if (debug != null) {
debug.println("Multi-threaded initialization failed: " + e);
@@ -312,8 +326,8 @@ public final class SunPKCS11 extends AuthProvider {
} else {
initArgs.flags = 0;
}
- tmpPKCS11 = PKCS11.getInstance
- (library, functionList, initArgs, config.getOmitInitialize());
+ tmpPKCS11 = PKCS11.getInstance(library,
+ functionList, initArgs, config.getOmitInitialize());
}
p11 = tmpPKCS11;
@@ -336,8 +350,10 @@ public final class SunPKCS11 extends AuthProvider {
System.out.println("Slots with tokens: " + toString(slots));
}
if (slotID < 0) {
- if ((slotListIndex < 0) || (slotListIndex >= slots.length)) {
- throw new ProviderException("slotListIndex is " + slotListIndex
+ if ((slotListIndex < 0)
+ || (slotListIndex >= slots.length)) {
+ throw new ProviderException("slotListIndex is "
+ + slotListIndex
+ " but token only has " + slots.length + " slots");
}
slotID = slots[slotListIndex];
@@ -575,12 +591,15 @@ public final class SunPKCS11 extends AuthProvider {
d(KF, "DH", P11DHKeyFactory, s("DiffieHellman"),
m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));
d(KF, "EC", P11DHKeyFactory,
- m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE, CKM_ECDSA, CKM_ECDSA_SHA1));
+ m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
+ CKM_ECDSA, CKM_ECDSA_SHA1));
// AlgorithmParameters for EC.
// Only needed until we have an EC implementation in the SUN provider.
- d(AGP, "EC", "sun.security.ec.ECParameters", s("1.2.840.10045.2.1"),
- m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE, CKM_ECDSA, CKM_ECDSA_SHA1));
+ d(AGP, "EC", "sun.security.ec.ECParameters",
+ s("1.2.840.10045.2.1"),
+ m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
+ CKM_ECDSA, CKM_ECDSA_SHA1));
d(KA, "DH", P11KeyAgreement, s("DiffieHellman"),
m(CKM_DH_PKCS_DERIVE));
@@ -654,12 +673,16 @@ public final class SunPKCS11 extends AuthProvider {
d(SIG, "SHA512withRSA", P11Signature,
m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
- d(KG, "SunTlsRsaPremasterSecret", "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
+ d(KG, "SunTlsRsaPremasterSecret",
+ "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));
- d(KG, "SunTlsMasterSecret", "sun.security.pkcs11.P11TlsMasterSecretGenerator",
+ d(KG, "SunTlsMasterSecret",
+ "sun.security.pkcs11.P11TlsMasterSecretGenerator",
m(CKM_SSL3_MASTER_KEY_DERIVE, CKM_TLS_MASTER_KEY_DERIVE,
- CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_MASTER_KEY_DERIVE_DH));
- d(KG, "SunTlsKeyMaterial", "sun.security.pkcs11.P11TlsKeyMaterialGenerator",
+ CKM_SSL3_MASTER_KEY_DERIVE_DH,
+ CKM_TLS_MASTER_KEY_DERIVE_DH));
+ d(KG, "SunTlsKeyMaterial",
+ "sun.security.pkcs11.P11TlsKeyMaterialGenerator",
m(CKM_SSL3_KEY_AND_MAC_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE));
d(KG, "SunTlsPrf", "sun.security.pkcs11.P11TlsPrfGenerator",
m(CKM_TLS_PRF, CKM_NSS_TLS_PRF_GENERAL));
@@ -773,6 +796,13 @@ public final class SunPKCS11 extends AuthProvider {
System.out.println(token.tokenInfo);
}
long[] supportedMechanisms = p11.C_GetMechanismList(slotID);
+
+ // Create a map from the various Descriptors to the "most
+ // preferred" mechanism that was defined during the
+ // static initialization. For example, DES/CBC/PKCS5Padding
+ // could be mapped to CKM_DES_CBC_PAD or CKM_DES_CBC. Prefer
+ // the earliest entry. When asked for "DES/CBC/PKCS5Padding", we
+ // return a CKM_DES_CBC_PAD.
final Map supportedAlgs =
new HashMap();
for (int i = 0; i < supportedMechanisms.length; i++) {
@@ -807,6 +837,9 @@ public final class SunPKCS11 extends AuthProvider {
supportedAlgs.put(d, integerMech);
continue;
}
+ // See if there is something "more preferred"
+ // than what we currently have in the supportedAlgs
+ // map.
int intOldMech = oldMech.intValue();
for (int j = 0; j < d.mechanisms.length; j++) {
int nextMech = d.mechanisms[j];
diff --git a/jdk/src/share/classes/sun/security/rsa/RSAKeyFactory.java b/jdk/src/share/classes/sun/security/rsa/RSAKeyFactory.java
index 17ce8cde639..d877f28fb54 100644
--- a/jdk/src/share/classes/sun/security/rsa/RSAKeyFactory.java
+++ b/jdk/src/share/classes/sun/security/rsa/RSAKeyFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,8 @@ import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
+import sun.security.action.GetPropertyAction;
+
/**
* KeyFactory for RSA keys. Keys must be instances of PublicKey or PrivateKey
* and getAlgorithm() must return "RSA". For such keys, it supports conversion
@@ -68,6 +70,24 @@ public final class RSAKeyFactory extends KeyFactorySpi {
private final static Class> x509KeySpecClass = X509EncodedKeySpec.class;
private final static Class> pkcs8KeySpecClass = PKCS8EncodedKeySpec.class;
+ public final static int MIN_MODLEN = 512;
+ public final static int MAX_MODLEN = 16384;
+
+ /*
+ * If the modulus length is above this value, restrict the size of
+ * the exponent to something that can be reasonably computed. We
+ * could simply hardcode the exp len to something like 64 bits, but
+ * this approach allows flexibility in case impls would like to use
+ * larger module and exponent values.
+ */
+ public final static int MAX_MODLEN_RESTRICT_EXP = 3072;
+ public final static int MAX_RESTRICTED_EXPLEN = 64;
+
+ private static final boolean restrictExpLen =
+ "true".equalsIgnoreCase(AccessController.doPrivileged(
+ new GetPropertyAction(
+ "sun.security.rsa.restrictRSAExponent", "true")));
+
// instance used for static translateKey();
private final static RSAKeyFactory INSTANCE = new RSAKeyFactory();
@@ -76,74 +96,79 @@ public final class RSAKeyFactory extends KeyFactorySpi {
}
/**
- * Static method to convert Key into a useable instance of
- * RSAPublicKey or RSAPrivate(Crt)Key. Check the key and convert it
- * to a SunRsaSign key if necessary. If the key is not an RSA key
- * or cannot be used, throw an InvalidKeyException.
- *
- * The difference between this method and engineTranslateKey() is that
- * we do not convert keys of other providers that are already an
- * instance of RSAPublicKey or RSAPrivate(Crt)Key.
+ * Static method to convert Key into an instance of RSAPublicKeyImpl
+ * or RSAPrivate(Crt)KeyImpl. If the key is not an RSA key or cannot be
+ * used, throw an InvalidKeyException.
*
* Used by RSASignature and RSACipher.
*/
public static RSAKey toRSAKey(Key key) throws InvalidKeyException {
- if (key instanceof RSAKey) {
- RSAKey rsaKey = (RSAKey)key;
- checkKey(rsaKey);
- return rsaKey;
+ if ((key instanceof RSAPrivateKeyImpl) ||
+ (key instanceof RSAPrivateCrtKeyImpl) ||
+ (key instanceof RSAPublicKeyImpl)) {
+ return (RSAKey)key;
} else {
return (RSAKey)INSTANCE.engineTranslateKey(key);
}
}
- /**
- * Check that the given RSA key is valid.
+ /*
+ * Single test entry point for all of the mechanisms in the SunRsaSign
+ * provider (RSA*KeyImpls). All of the tests are the same.
+ *
+ * For compatibility, we round up to the nearest byte here:
+ * some Key impls might pass in a value within a byte of the
+ * real value.
*/
- private static void checkKey(RSAKey key) throws InvalidKeyException {
- // check for subinterfaces, omit additional checks for our keys
- if (key instanceof RSAPublicKey) {
- if (key instanceof RSAPublicKeyImpl) {
- return;
- }
- } else if (key instanceof RSAPrivateKey) {
- if ((key instanceof RSAPrivateCrtKeyImpl)
- || (key instanceof RSAPrivateKeyImpl)) {
- return;
- }
- } else {
- throw new InvalidKeyException("Neither a public nor a private key");
- }
- // RSAKey does not extend Key, so we need to do a cast
- String keyAlg = ((Key)key).getAlgorithm();
- if (keyAlg.equals("RSA") == false) {
- throw new InvalidKeyException("Not an RSA key: " + keyAlg);
- }
- BigInteger modulus;
- // some providers implement RSAKey for keys where the values are
- // not accessible (although they should). Detect those here
- // for a more graceful failure.
- try {
- modulus = key.getModulus();
- if (modulus == null) {
- throw new InvalidKeyException("Modulus is missing");
- }
- } catch (RuntimeException e) {
- throw new InvalidKeyException(e);
- }
- checkKeyLength(modulus);
+ static void checkRSAProviderKeyLengths(int modulusLen, BigInteger exponent)
+ throws InvalidKeyException {
+ checkKeyLengths(((modulusLen + 7) & ~7), exponent,
+ RSAKeyFactory.MIN_MODLEN, Integer.MAX_VALUE);
}
/**
- * Check the length of the modulus of an RSA key. We only support keys
- * at least 505 bits long.
+ * Check the length of an RSA key modulus/exponent to make sure it
+ * is not too short or long. Some impls have their own min and
+ * max key sizes that may or may not match with a system defined value.
+ *
+ * @param modulusLen the bit length of the RSA modulus.
+ * @param exponent the RSA exponent
+ * @param minModulusLen if > 0, check to see if modulusLen is at
+ * least this long, otherwise unused.
+ * @param maxModulusLen caller will allow this max number of bits.
+ * Allow the smaller of the system-defined maximum and this param.
+ *
+ * @throws InvalidKeyException if any of the values are unacceptable.
*/
- static void checkKeyLength(BigInteger modulus) throws InvalidKeyException {
- if (modulus.bitLength() < 505) {
- // some providers may generate slightly shorter keys
- // accept them if the encoding is at least 64 bytes long
- throw new InvalidKeyException
- ("RSA keys must be at least 512 bits long");
+ public static void checkKeyLengths(int modulusLen, BigInteger exponent,
+ int minModulusLen, int maxModulusLen) throws InvalidKeyException {
+
+ if ((minModulusLen > 0) && (modulusLen < (minModulusLen))) {
+ throw new InvalidKeyException( "RSA keys must be at least " +
+ minModulusLen + " bits long");
+ }
+
+ // Even though our policy file may allow this, we don't want
+ // either value (mod/exp) to be too big.
+
+ int maxLen = Math.min(maxModulusLen, MAX_MODLEN);
+
+ // If a RSAPrivateKey/RSAPublicKey, make sure the
+ // modulus len isn't too big.
+ if (modulusLen > maxLen) {
+ throw new InvalidKeyException(
+ "RSA keys must be no longer than " + maxLen + " bits");
+ }
+
+ // If a RSAPublicKey, make sure the exponent isn't too big.
+ if (restrictExpLen && (exponent != null) &&
+ (modulusLen > MAX_MODLEN_RESTRICT_EXP) &&
+ (exponent.bitLength() > MAX_RESTRICTED_EXPLEN)) {
+ throw new InvalidKeyException(
+ "RSA exponents can be no longer than " +
+ MAX_RESTRICTED_EXPLEN + " bits " +
+ " if modulus is greater than " +
+ MAX_MODLEN_RESTRICT_EXP + " bits");
}
}
diff --git a/jdk/src/share/classes/sun/security/rsa/RSAKeyPairGenerator.java b/jdk/src/share/classes/sun/security/rsa/RSAKeyPairGenerator.java
index f800dec543b..2898a3d1f51 100644
--- a/jdk/src/share/classes/sun/security/rsa/RSAKeyPairGenerator.java
+++ b/jdk/src/share/classes/sun/security/rsa/RSAKeyPairGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,7 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// public exponent to use
private BigInteger publicExponent;
- // size of the key to generate, >= 512
+ // size of the key to generate, >= RSAKeyFactory.MIN_MODLEN
private int keySize;
// PRNG to use
@@ -60,15 +60,16 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// initialize the generator. See JCA doc
public void initialize(int keySize, SecureRandom random) {
- if (keySize < 512) {
- throw new InvalidParameterException
- ("Key size must be at least 512 bits");
- }
- if (keySize > 64 * 1024) {
- // do not allow unreasonably large key sizes, probably user error
- throw new InvalidParameterException
- ("Key size must be 65536 bits or less");
+
+ // do not allow unreasonably small or large key sizes,
+ // probably user error
+ try {
+ RSAKeyFactory.checkKeyLengths(keySize, RSAKeyGenParameterSpec.F4,
+ 512, 64 * 1024);
+ } catch (InvalidKeyException e) {
+ throw new InvalidParameterException(e.getMessage());
}
+
this.keySize = keySize;
this.random = random;
this.publicExponent = RSAKeyGenParameterSpec.F4;
@@ -77,35 +78,41 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// second initialize method. See JCA doc.
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException {
+
if (params instanceof RSAKeyGenParameterSpec == false) {
throw new InvalidAlgorithmParameterException
("Params must be instance of RSAKeyGenParameterSpec");
}
+
RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params;
- keySize = rsaSpec.getKeysize();
- publicExponent = rsaSpec.getPublicExponent();
- this.random = random;
- if (keySize < 512) {
- throw new InvalidAlgorithmParameterException
- ("Key size must be at least 512 bits");
- }
- if (keySize > 64 * 1024) {
- // do not allow unreasonably large key sizes, probably user error
- throw new InvalidAlgorithmParameterException
- ("Key size must be 65536 bits or less");
- }
- if (publicExponent == null) {
- publicExponent = RSAKeyGenParameterSpec.F4;
+ int tmpKeySize = rsaSpec.getKeysize();
+ BigInteger tmpPublicExponent = rsaSpec.getPublicExponent();
+
+ if (tmpPublicExponent == null) {
+ tmpPublicExponent = RSAKeyGenParameterSpec.F4;
} else {
- if (publicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) {
+ if (tmpPublicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) {
throw new InvalidAlgorithmParameterException
("Public exponent must be 3 or larger");
}
- if (publicExponent.bitLength() > keySize) {
+ if (tmpPublicExponent.bitLength() > tmpKeySize) {
throw new InvalidAlgorithmParameterException
("Public exponent must be smaller than key size");
}
}
+
+ // do not allow unreasonably large key sizes, probably user error
+ try {
+ RSAKeyFactory.checkKeyLengths(tmpKeySize, tmpPublicExponent,
+ 512, 64 * 1024);
+ } catch (InvalidKeyException e) {
+ throw new InvalidAlgorithmParameterException(
+ "Invalid key sizes", e);
+ }
+
+ this.keySize = tmpKeySize;
+ this.publicExponent = tmpPublicExponent;
+ this.random = random;
}
// generate the keypair. See JCA doc
diff --git a/jdk/src/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java b/jdk/src/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java
index ac296b49f60..640972a2495 100644
--- a/jdk/src/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java
+++ b/jdk/src/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -89,7 +89,7 @@ public final class RSAPrivateCrtKeyImpl
*/
RSAPrivateCrtKeyImpl(byte[] encoded) throws InvalidKeyException {
decode(encoded);
- RSAKeyFactory.checkKeyLength(n);
+ RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
}
/**
@@ -107,7 +107,8 @@ public final class RSAPrivateCrtKeyImpl
this.pe = pe;
this.qe = qe;
this.coeff = coeff;
- RSAKeyFactory.checkKeyLength(n);
+ RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
+
// generate the encoding
algid = rsaId;
try {
diff --git a/jdk/src/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java b/jdk/src/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java
index 1f883f4205d..860e7706bc9 100644
--- a/jdk/src/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java
+++ b/jdk/src/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,7 @@ public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey {
RSAPrivateKeyImpl(BigInteger n, BigInteger d) throws InvalidKeyException {
this.n = n;
this.d = d;
- RSAKeyFactory.checkKeyLength(n);
+ RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), null);
// generate the encoding
algid = RSAPrivateCrtKeyImpl.rsaId;
try {
diff --git a/jdk/src/share/classes/sun/security/rsa/RSAPublicKeyImpl.java b/jdk/src/share/classes/sun/security/rsa/RSAPublicKeyImpl.java
index c500ca2dee4..6db08f6a393 100644
--- a/jdk/src/share/classes/sun/security/rsa/RSAPublicKeyImpl.java
+++ b/jdk/src/share/classes/sun/security/rsa/RSAPublicKeyImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -56,10 +56,11 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {
* Construct a key from its components. Used by the
* RSAKeyFactory and the RSAKeyPairGenerator.
*/
- public RSAPublicKeyImpl(BigInteger n, BigInteger e) throws InvalidKeyException {
+ public RSAPublicKeyImpl(BigInteger n, BigInteger e)
+ throws InvalidKeyException {
this.n = n;
this.e = e;
- RSAKeyFactory.checkKeyLength(n);
+ RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
// generate the encoding
algid = RSAPrivateCrtKeyImpl.rsaId;
try {
@@ -80,7 +81,7 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {
*/
public RSAPublicKeyImpl(byte[] encoded) throws InvalidKeyException {
decode(encoded);
- RSAKeyFactory.checkKeyLength(n);
+ RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
}
// see JCA doc
diff --git a/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java b/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java
index 2ad04c0b360..717e5bcf65e 100644
--- a/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java
+++ b/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java
@@ -26,7 +26,8 @@
package sun.security.util;
import java.io.*;
-
+import java.math.BigInteger;
+import java.util.Arrays;
/**
* Represent an ISO Object Identifier.
@@ -44,105 +45,186 @@ import java.io.*;
* hierarchy, and other organizations can easily acquire the ability
* to assign such unique identifiers.
*
- *
* @author David Brownell
* @author Amit Kapoor
* @author Hemma Prafullchandra
*/
+
final public
class ObjectIdentifier implements Serializable
{
- /** use serialVersionUID from JDK 1.1. for interoperability */
+ /**
+ * We use the DER value (no tag, no length) as the internal format
+ * @serial
+ */
+ private byte[] encoding = null;
+
+ private transient volatile String stringForm;
+
+ /*
+ * IMPORTANT NOTES FOR CODE CHANGES (bug 4811968) IN JDK 1.7.0
+ * ===========================================================
+ *
+ * (Almost) serialization compatibility with old versions:
+ *
+ * serialVersionUID is unchanged. Old field "component" is changed to
+ * type Object so that "poison" (unknown object type for old versions)
+ * can be put inside if there are huge components that cannot be saved
+ * as integers.
+ *
+ * New version use the new filed "encoding" only.
+ *
+ * Below are all 4 cases in a serialization/deserialization process:
+ *
+ * 1. old -> old: Not covered here
+ * 2. old -> new: There's no "encoding" field, new readObject() reads
+ * "components" and "componentLen" instead and inits correctly.
+ * 3. new -> new: "encoding" field exists, new readObject() uses it
+ * (ignoring the other 2 fields) and inits correctly.
+ * 4. new -> old: old readObject() only recognizes "components" and
+ * "componentLen" fields. If no huge components are involved, they
+ * are serialized as legal values and old object can init correctly.
+ * Otherwise, old object cannot recognize the form (component not int[])
+ * and throw a ClassNotFoundException at deserialization time.
+ *
+ * Therfore, for the first 3 cases, exact compatibility is preserved. In
+ * the 4th case, non-huge OID is still supportable in old versions, while
+ * huge OID is not.
+ */
private static final long serialVersionUID = 8697030238860181294L;
- private static final int maxFirstComponent = 2;
- private static final int maxSecondComponent = 39;
/**
- * Constructs an object identifier from a string. This string
- * should be of the form 1.23.34.45.56 etc.
+ * Changed to Object
+ * @serial
+ */
+ private Object components = null; // path from root
+ /**
+ * @serial
+ */
+ private int componentLen = -1; // how much is used.
+
+ // Is the components field calculated?
+ transient private boolean componentsCalculated = false;
+
+ private void readObject(ObjectInputStream is)
+ throws IOException, ClassNotFoundException {
+ is.defaultReadObject();
+
+ if (encoding == null) { // from an old version
+ init((int[])components, componentLen);
+ }
+ }
+
+ private void writeObject(ObjectOutputStream os)
+ throws IOException {
+ if (!componentsCalculated) {
+ int[] comps = toIntArray();
+ if (comps != null) { // every one understands this
+ components = comps;
+ componentLen = comps.length;
+ } else {
+ components = HugeOidNotSupportedByOldJDK.theOne;
+ }
+ componentsCalculated = true;
+ }
+ os.defaultWriteObject();
+ }
+
+ static class HugeOidNotSupportedByOldJDK implements Serializable {
+ private static final long serialVersionUID = 1L;
+ static HugeOidNotSupportedByOldJDK theOne = new HugeOidNotSupportedByOldJDK();
+ }
+
+ /**
+ * Constructs, from a string. This string should be of the form 1.23.56.
+ * Validity check included.
*/
public ObjectIdentifier (String oid) throws IOException
{
int ch = '.';
- int start = 0;
+ int start = 0;
int end = 0;
- // Calculate length of oid
- componentLen = 0;
- while ((end = oid.indexOf(ch,start)) != -1) {
- start = end + 1;
- componentLen += 1;
- }
- componentLen += 1;
- components = new int[componentLen];
+ int pos = 0;
+ byte[] tmp = new byte[oid.length()];
+ int first = 0, second;
+ int count = 0;
- start = 0;
- int i = 0;
- String comp = null;
try {
- while ((end = oid.indexOf(ch,start)) != -1) {
- comp = oid.substring(start,end);
- components[i++] = Integer.valueOf(comp).intValue();
+ String comp = null;
+ do {
+ int length = 0; // length of one section
+ end = oid.indexOf(ch,start);
+ if (end == -1) {
+ comp = oid.substring(start);
+ length = oid.length() - start;
+ } else {
+ comp = oid.substring(start,end);
+ length = end - start;
+ }
+
+ if (length > 9) {
+ BigInteger bignum = new BigInteger(comp);
+ if (count == 0) {
+ checkFirstComponent(bignum);
+ first = bignum.intValue();
+ } else {
+ if (count == 1) {
+ checkSecondComponent(first, bignum);
+ bignum = bignum.add(BigInteger.valueOf(40*first));
+ } else {
+ checkOtherComponent(count, bignum);
+ }
+ pos += pack7Oid(bignum, tmp, pos);
+ }
+ } else {
+ int num = Integer.parseInt(comp);
+ if (count == 0) {
+ checkFirstComponent(num);
+ first = num;
+ } else {
+ if (count == 1) {
+ checkSecondComponent(first, num);
+ num += 40 * first;
+ } else {
+ checkOtherComponent(count, num);
+ }
+ pos += pack7Oid(num, tmp, pos);
+ }
+ }
start = end + 1;
- }
- comp = oid.substring(start);
- components[i] = Integer.valueOf(comp).intValue();
+ count++;
+ } while (end != -1);
+
+ checkCount(count);
+ encoding = new byte[pos];
+ System.arraycopy(tmp, 0, encoding, 0, pos);
+ this.stringForm = oid;
+ } catch (IOException ioe) { // already detected by checkXXX
+ throw ioe;
} catch (Exception e) {
throw new IOException("ObjectIdentifier() -- Invalid format: "
+ e.toString(), e);
}
- checkValidOid(components, componentLen);
- this.stringForm = oid;
}
/**
- * Check if the values make a legal OID. There must be at least 2
- * components and they must be all non-negative. The first component
- * should be 0,1 or 2. When the first component is 0 or 1, the
- * second component should be less than or equal to 39
- *
- * @param values the components that will make the OID
- * @param len the number of components to check. Note that the allocation
- * size of values
may be longer than len
.
- * In this case, only the first len
items are checked.
- * @exception IOException if this is not a legal OID
- */
- private void checkValidOid(int[] values, int len) throws IOException {
- if (values == null || len < 2) {
- throw new IOException("ObjectIdentifier() -- " +
- "Must be at least two oid components ");
- }
-
- for (int i=0; i maxFirstComponent) {
- throw new IOException("ObjectIdentifier() -- " +
- "First oid component is invalid ");
- }
-
- if (values[0] < 2 && values[1] > maxSecondComponent) {
- throw new IOException("ObjectIdentifier() -- " +
- "Second oid component is invalid ");
- }
- }
- /**
- * Constructs an object ID from an array of integers. This
- * is used to construct constant object IDs.
+ * Constructor, from an array of integers.
+ * Validity check included.
*/
public ObjectIdentifier (int values []) throws IOException
{
- checkValidOid(values, values.length);
- components = values.clone();
- componentLen = values.length;
+ checkCount(values.length);
+ checkFirstComponent(values[0]);
+ checkSecondComponent(values[0], values[1]);
+ for (int i=2; i bufferEnd;
- ) {
- component = getComponent (in);
- if (component < 0) {
- throw new IOException(
- "ObjectIdentifier() -- " +
- "component values must be nonnegative");
- }
- if (first_subid) {
- int X, Y;
-
- /*
- * NOTE: the allocation quantum is large enough that we know
- * we don't have to reallocate here!
- */
- if (component < 40)
- X = 0;
- else if (component < 80)
- X = 1;
- else
- X = 2;
- Y = component - ( X * 40);
- components [0] = X;
- components [1] = Y;
- componentLen = 2;
-
- first_subid = false;
-
- } else {
-
- /*
- * Other components are encoded less exotically. The only
- * potential trouble is the need to grow the array.
- */
- if (componentLen >= components.length) {
- int tmp_components [];
-
- tmp_components = new int [components.length
- + allocationQuantum];
- System.arraycopy (components, 0, tmp_components, 0,
- components.length);
- components = tmp_components;
- }
- components [componentLen++] = component;
- }
- }
-
- checkValidOid(components, componentLen);
-
- /*
- * Final sanity check -- if we didn't use exactly the number of bytes
- * specified, something's quite wrong.
- */
- if (in.available () != bufferEnd) {
- throw new IOException (
- "ObjectIdentifier() -- malformed input data");
+ try {
+ return new ObjectIdentifier(values);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ // Should not happen, internal calls always uses legal values.
}
}
-
/*
* n.b. the only public interface is DerOutputStream.putOID()
*/
void encode (DerOutputStream out) throws IOException
{
- DerOutputStream bytes = new DerOutputStream ();
- int i;
-
- // According to ISO X.660, when the 1st component is 0 or 1, the 2nd
- // component is restricted to be less than or equal to 39, thus make
- // it small enough to be encoded into one single byte.
- if (components[0] < 2) {
- bytes.write ((components [0] * 40) + components [1]);
- } else {
- putComponent(bytes, (components [0] * 40) + components [1]);
- }
- for (i = 2; i < componentLen; i++)
- putComponent (bytes, components [i]);
-
- /*
- * Now that we've constructed the component, encode
- * it in the stream we were given.
- */
- out.write (DerValue.tag_ObjectId, bytes);
- }
-
- /*
- * Tricky OID component parsing technique ... note that one bit
- * per octet is lost, this returns at most 28 bits of component.
- * Also, notice this parses in big-endian format.
- */
- private static int getComponent (DerInputStream in)
- throws IOException
- {
- int retval, i, tmp;
-
- for (i = 0, retval = 0; i < 4; i++) {
- retval <<= 7;
- tmp = in.getByte ();
- retval |= (tmp & 0x07f);
- if ((tmp & 0x080) == 0)
- return retval;
- }
-
- throw new IOException ("ObjectIdentifier() -- component value too big");
- }
-
- /*
- * Reverse of the above routine. Notice it needs to emit in
- * big-endian form, so it buffers the output until it's ready.
- * (Minimum length encoding is a DER requirement.)
- */
- private static void putComponent (DerOutputStream out, int val)
- throws IOException
- {
- int i;
- // TODO: val must be <128*128*128*128 here, otherwise, 4 bytes is not
- // enough to hold it. Will address this later.
- byte buf [] = new byte [4] ;
-
- for (i = 0; i < 4; i++) {
- buf [i] = (byte) (val & 0x07f);
- val >>>= 7;
- if (val == 0)
- break;
- }
- for ( ; i > 0; --i)
- out.write (buf [i] | 0x080);
- out.write (buf [0]);
- }
-
- // XXX this API should probably facilitate the JDK sort utility
-
- /**
- * Compares this identifier with another, for sorting purposes.
- * An identifier does not precede itself.
- *
- * @param other identifer that may precede this one.
- * @return true iff other precedes this one
- * in a particular sorting order.
- */
- public boolean precedes (ObjectIdentifier other)
- {
- int i;
-
- // shorter IDs go first
- if (other == this || componentLen < other.componentLen)
- return false;
- if (other.componentLen < componentLen)
- return true;
-
- // for each component, the lesser component goes first
- for (i = 0; i < componentLen; i++) {
- if (other.components [i] < components [i])
- return true;
- }
-
- // identical IDs don't precede each other
- return false;
+ out.write (DerValue.tag_ObjectId, encoding);
}
/**
@@ -398,6 +331,7 @@ class ObjectIdentifier implements Serializable
*
* @return true iff the names are identical.
*/
+ @Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
@@ -406,23 +340,71 @@ class ObjectIdentifier implements Serializable
return false;
}
ObjectIdentifier other = (ObjectIdentifier)obj;
- if (componentLen != other.componentLen) {
- return false;
- }
- for (int i = 0; i < componentLen; i++) {
- if (components[i] != other.components[i]) {
- return false;
- }
- }
- return true;
+ return Arrays.equals(encoding, other.encoding);
}
+ @Override
public int hashCode() {
- int h = componentLen;
- for (int i = 0; i < componentLen; i++) {
- h += components[i] * 37;
+ return Arrays.hashCode(encoding);
+ }
+
+ /**
+ * Private helper method for serialization. To be compatible with old
+ * versions of JDK.
+ * @return components in an int array, if all the components are less than
+ * Integer.MAX_VALUE. Otherwise, null.
+ */
+ private int[] toIntArray() {
+ int length = encoding.length;
+ int[] result = new int[20];
+ int which = 0;
+ int fromPos = 0;
+ for (int i = 0; i < length; i++) {
+ if ((encoding[i] & 0x80) == 0) {
+ // one section [fromPos..i]
+ if (i - fromPos + 1 > 4) {
+ BigInteger big = new BigInteger(pack(encoding, fromPos, i-fromPos+1, 7, 8));
+ if (fromPos == 0) {
+ result[which++] = 2;
+ BigInteger second = big.subtract(BigInteger.valueOf(80));
+ if (second.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 1) {
+ return null;
+ } else {
+ result[which++] = second.intValue();
+ }
+ } else {
+ if (big.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 1) {
+ return null;
+ } else {
+ result[which++] = big.intValue();
+ }
+ }
+ } else {
+ int retval = 0;
+ for (int j = fromPos; j <= i; j++) {
+ retval <<= 7;
+ byte tmp = encoding[j];
+ retval |= (tmp & 0x07f);
+ }
+ if (fromPos == 0) {
+ if (retval < 80) {
+ result[which++] = retval / 40;
+ result[which++] = retval % 40;
+ } else {
+ result[which++] = 2;
+ result[which++] = retval - 80;
+ }
+ } else {
+ result[which++] = retval;
+ }
+ }
+ fromPos = i+1;
+ }
+ if (which >= result.length) {
+ result = Arrays.copyOf(result, which + 10);
+ }
}
- return h;
+ return Arrays.copyOf(result, which);
}
/**
@@ -431,15 +413,52 @@ class ObjectIdentifier implements Serializable
* user-friendly descriptive strings, since those strings
* will not be understood everywhere.
*/
+ @Override
public String toString() {
String s = stringForm;
if (s == null) {
- StringBuffer sb = new StringBuffer(componentLen * 4);
- for (int i = 0; i < componentLen; i++) {
- if (i != 0) {
- sb.append('.');
+ int length = encoding.length;
+ StringBuffer sb = new StringBuffer(length * 4);
+
+ int fromPos = 0;
+ for (int i = 0; i < length; i++) {
+ if ((encoding[i] & 0x80) == 0) {
+ // one section [fromPos..i]
+ if (fromPos != 0) { // not the first segment
+ sb.append('.');
+ }
+ if (i - fromPos + 1 > 4) { // maybe big integer
+ BigInteger big = new BigInteger(pack(encoding, fromPos, i-fromPos+1, 7, 8));
+ if (fromPos == 0) {
+ // first section encoded with more than 4 bytes,
+ // must be 2.something
+ sb.append("2.");
+ sb.append(big.subtract(BigInteger.valueOf(80)));
+ } else {
+ sb.append(big);
+ }
+ } else { // small integer
+ int retval = 0;
+ for (int j = fromPos; j <= i; j++) {
+ retval <<= 7;
+ byte tmp = encoding[j];
+ retval |= (tmp & 0x07f);
+ }
+ if (fromPos == 0) {
+ if (retval < 80) {
+ sb.append(retval/40);
+ sb.append('.');
+ sb.append(retval%40);
+ } else {
+ sb.append("2.");
+ sb.append(retval - 80);
+ }
+ } else {
+ sb.append(retval);
+ }
+ }
+ fromPos = i+1;
}
- sb.append(components[i]);
}
s = sb.toString();
stringForm = s;
@@ -447,15 +466,197 @@ class ObjectIdentifier implements Serializable
return s;
}
- /*
- * To simplify, we assume no individual component of an object ID is
- * larger than 32 bits. Then we represent the path from the root as
- * an array that's (usually) only filled at the beginning.
+ /**
+ * Repack all bits from input to output. On the both sides, only a portion
+ * (from the least significant bit) of the 8 bits in a byte is used. This
+ * number is defined as the number of useful bits (NUB) for the array. All the
+ * used bits from the input byte array and repacked into the output in the
+ * exactly same order. The output bits are aligned so that the final bit of
+ * the input (the least significant bit in the last byte), when repacked as
+ * the final bit of the output, is still at the least significant position.
+ * Zeroes will be padded on the left side of the first output byte if
+ * necessary. All unused bits in the output are also zeroed.
+ *
+ * For example: if the input is 01001100 with NUB 8, the output which
+ * has a NUB 6 will look like:
+ * 00000001 00001100
+ * The first 2 bits of the output bytes are unused bits. The other bits
+ * turn out to be 000001 001100. While the 8 bits on the right are from
+ * the input, the left 4 zeroes are padded to fill the 6 bits space.
+ *
+ * @param in the input byte array
+ * @param ioffset start point inside in
+ * @param ilength number of bytes to repack
+ * @param iw NUB for input
+ * @param ow NUB for output
+ * @return the repacked bytes
*/
- private int components []; // path from root
- private int componentLen; // how much is used.
+ private static byte[] pack(byte[] in, int ioffset, int ilength, int iw, int ow) {
+ assert (iw > 0 && iw <= 8): "input NUB must be between 1 and 8";
+ assert (ow > 0 && ow <= 8): "output NUB must be between 1 and 8";
- private transient volatile String stringForm;
+ if (iw == ow) {
+ return in.clone();
+ }
- private static final int allocationQuantum = 5; // >= 2
+ int bits = ilength * iw; // number of all used bits
+ byte[] out = new byte[(bits+ow-1)/ow];
+
+ // starting from the 0th bit in the input
+ int ipos = 0;
+
+ // the number of padding 0's needed in the output, skip them
+ int opos = (bits+ow-1)/ow*ow-bits;
+
+ while(ipos < bits) {
+ int count = iw - ipos%iw; // unpacked bits in current input byte
+ if (count > ow - opos%ow) { // free space available in output byte
+ count = ow - opos%ow; // choose the smaller number
+ }
+ // and move them!
+ out[opos/ow] |= // paste!
+ (((in[ioffset+ipos/iw]+256) // locate the byte (+256 so that it's never negative)
+ >> (iw-ipos%iw-count)) // move to the end of a byte
+ & ((1 << (count))-1)) // zero out all other bits
+ << (ow-opos%ow-count); // move to the output position
+ ipos += count; // advance
+ opos += count; // advance
+ }
+ return out;
+ }
+
+ /**
+ * Repack from NUB 8 to a NUB 7 OID sub-identifier, remove all
+ * unnecessary 0 headings, set the first bit of all non-tail
+ * output bytes to 1 (as ITU-T Rec. X.690 8.19.2 says), and
+ * paste it into an existing byte array.
+ * @param out the existing array to be pasted into
+ * @param ooffset the starting position to paste
+ * @return the number of bytes pasted
+ */
+ private static int pack7Oid(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) {
+ byte[] pack = pack(in, ioffset, ilength, 8, 7);
+ int firstNonZero = pack.length-1; // paste at least one byte
+ for (int i=pack.length-2; i>=0; i--) {
+ if (pack[i] != 0) {
+ firstNonZero = i;
+ }
+ pack[i] |= 0x80;
+ }
+ System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero);
+ return pack.length-firstNonZero;
+ }
+
+ /**
+ * Repack from NUB 7 to NUB 8, remove all unnecessary 0
+ * headings, and paste it into an existing byte array.
+ * @param out the existing array to be pasted into
+ * @param ooffset the starting position to paste
+ * @return the number of bytes pasted
+ */
+ private static int pack8(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) {
+ byte[] pack = pack(in, ioffset, ilength, 7, 8);
+ int firstNonZero = pack.length-1; // paste at least one byte
+ for (int i=pack.length-2; i>=0; i--) {
+ if (pack[i] != 0) {
+ firstNonZero = i;
+ }
+ }
+ System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero);
+ return pack.length-firstNonZero;
+ }
+
+ /**
+ * Pack the int into a OID sub-identifier DER encoding
+ */
+ private static int pack7Oid(int input, byte[] out, int ooffset) {
+ byte[] b = new byte[4];
+ b[0] = (byte)(input >> 24);
+ b[1] = (byte)(input >> 16);
+ b[2] = (byte)(input >> 8);
+ b[3] = (byte)(input);
+ return pack7Oid(b, 0, 4, out, ooffset);
+ }
+
+ /**
+ * Pack the BigInteger into a OID subidentifier DER encoding
+ */
+ private static int pack7Oid(BigInteger input, byte[] out, int ooffset) {
+ byte[] b = input.toByteArray();
+ return pack7Oid(b, 0, b.length, out, ooffset);
+ }
+
+ /**
+ * Private methods to check validity of OID. They must be --
+ * 1. at least 2 components
+ * 2. all components must be non-negative
+ * 3. the first must be 0, 1 or 2
+ * 4. if the first is 0 or 1, the second must be <40
+ */
+
+ /**
+ * Check the DER encoding. Since DER encoding defines that the integer bits
+ * are unsigned, so there's no need to check the MSB.
+ */
+ private static void check(byte[] encoding) throws IOException {
+ int length = encoding.length;
+ if (length < 1 || // too short
+ (encoding[length - 1] & 0x80) != 0) { // not ended
+ throw new IOException("ObjectIdentifier() -- " +
+ "Invalid DER encoding, not ended");
+ }
+ for (int i=0; i 2) {
+ throw new IOException("ObjectIdentifier() -- " +
+ "First oid component is invalid ");
+ }
+ }
+ private static void checkFirstComponent(BigInteger first) throws IOException {
+ if (first.signum() == -1 ||
+ first.compareTo(BigInteger.valueOf(2)) == 1) {
+ throw new IOException("ObjectIdentifier() -- " +
+ "First oid component is invalid ");
+ }
+ }
+ private static void checkSecondComponent(int first, int second) throws IOException {
+ if (second < 0 || first != 2 && second > 39) {
+ throw new IOException("ObjectIdentifier() -- " +
+ "Second oid component is invalid ");
+ }
+ }
+ private static void checkSecondComponent(int first, BigInteger second) throws IOException {
+ if (second.signum() == -1 ||
+ first != 2 &&
+ second.compareTo(BigInteger.valueOf(39)) == 1) {
+ throw new IOException("ObjectIdentifier() -- " +
+ "Second oid component is invalid ");
+ }
+ }
+ private static void checkOtherComponent(int i, int num) throws IOException {
+ if (num < 0) {
+ throw new IOException("ObjectIdentifier() -- " +
+ "oid component #" + (i+1) + " must be non-negative ");
+ }
+ }
+ private static void checkOtherComponent(int i, BigInteger num) throws IOException {
+ if (num.signum() == -1) {
+ throw new IOException("ObjectIdentifier() -- " +
+ "oid component #" + (i+1) + " must be non-negative ");
+ }
+ }
}
diff --git a/jdk/src/share/lib/management/jmxremote.access b/jdk/src/share/lib/management/jmxremote.access
index 765f118a364..ce80b47a1a8 100644
--- a/jdk/src/share/lib/management/jmxremote.access
+++ b/jdk/src/share/lib/management/jmxremote.access
@@ -8,7 +8,7 @@
# passwords. To be functional, a role must have an entry in
# both the password and the access files.
#
-# Default location of this file is $JRE/lib/management/jmxremote.access
+# The default location of this file is $JRE/lib/management/jmxremote.access
# You can specify an alternate location by specifying a property in
# the management config file $JRE/lib/management/management.properties
# (See that file for details)
@@ -16,7 +16,7 @@
# The file format for password and access files is syntactically the same
# as the Properties file format. The syntax is described in the Javadoc
# for java.util.Properties.load.
-# Typical access file has multiple lines, where each line is blank,
+# A typical access file has multiple lines, where each line is blank,
# a comment (like this one), or an access control entry.
#
# An access control entry consists of a role name, and an
@@ -29,10 +29,38 @@
# role can read measurements but cannot perform any action
# that changes the environment of the running program.
# "readwrite" grants access to read and write attributes of MBeans,
-# to invoke operations on them, and to create or remove them.
-# This access should be granted to only trusted clients,
-# since they can potentially interfere with the smooth
-# operation of a running program
+# to invoke operations on them, and optionally
+# to create or remove them. This access should be granted
+# only to trusted clients, since they can potentially
+# interfere with the smooth operation of a running program.
+#
+# The "readwrite" access level can optionally be followed by the "create" and/or
+# "unregister" keywords. The "unregister" keyword grants access to unregister
+# (delete) MBeans. The "create" keyword grants access to create MBeans of a
+# particular class or of any class matching a particular pattern. Access
+# should only be granted to create MBeans of known and trusted classes.
+#
+# For example, the following entry would grant readwrite access
+# to "controlRole", as well as access to create MBeans of the class
+# javax.management.monitor.CounterMonitor and to unregister any MBean:
+# controlRole readwrite \
+# create javax.management.monitor.CounterMonitorMBean \
+# unregister
+# or equivalently:
+# controlRole readwrite unregister create javax.management.monitor.CounterMBean
+#
+# The following entry would grant readwrite access as well as access to create
+# MBeans of any class in the packages javax.management.monitor and
+# javax.management.timer:
+# controlRole readwrite \
+# create javax.management.monitor.*,javax.management.timer.* \
+# unregister
+#
+# The \ character is defined in the Properties file syntax to allow continuation
+# lines as shown here. A * in a class pattern matches a sequence of characters
+# other than dot (.), so javax.management.monitor.* matches
+# javax.management.monitor.CounterMonitor but not
+# javax.management.monitor.foo.Bar.
#
# A given role should have at most one entry in this file. If a role
# has no entry, it has no access.
@@ -42,7 +70,10 @@
#
# Default access control entries:
# o The "monitorRole" role has readonly access.
-# o The "controlRole" role has readwrite access.
+# o The "controlRole" role has readwrite access and can create the standard
+# Timer and Monitor MBeans defined by the JMX API.
monitorRole readonly
-controlRole readwrite
+controlRole readwrite \
+ create javax.management.monitor.*,javax.management.timer.* \
+ unregister
diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp
index c78644c289d..a0d64dc63f4 100644
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -94,6 +94,7 @@ void band::readData(int expectedLength) {
assert(!valc->isMalloc);
}
xvs.init(u->rp, u->rplimit, valc);
+ CHECK;
int X = xvs.getInt();
if (valc->S() != 0) {
assert(valc->min <= -256);
@@ -117,6 +118,7 @@ void band::readData(int expectedLength) {
byte XB_byte = (byte) XB;
byte* XB_ptr = &XB_byte;
cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, null);
+ CHECK;
} else {
NOT_PRODUCT(byte* meta_rp0 = u->meta_rp);
assert(u->meta_rp != null);
@@ -215,8 +217,19 @@ int band::getIntTotal() {
if (length == 0) return 0;
if (total_memo > 0) return total_memo-1;
int total = getInt();
+ // overflow checks require that none of the addends are <0,
+ // and that the partial sums never overflow (wrap negative)
+ if (total < 0) {
+ abort("overflow detected");
+ return 0;
+ }
for (int k = length-1; k > 0; k--) {
+ int prev_total = total;
total += vs[0].getInt();
+ if (total < prev_total) {
+ abort("overflow detected");
+ return 0;
+ }
}
rewind();
total_memo = total+1;
diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/bytes.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/bytes.cpp
index ecc45ce2cb5..097c51cee42 100644
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/bytes.cpp
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/bytes.cpp
@@ -56,7 +56,7 @@ void bytes::realloc(size_t len_) {
return;
}
byte* oldptr = ptr;
- ptr = (byte*)::realloc(ptr, len_+1);
+ ptr = (len_ >= PSIZE_MAX) ? null : (byte*)::realloc(ptr, len_+1);
if (ptr != null) {
mtrace('r', oldptr, 0);
mtrace('m', ptr, len_+1);
@@ -128,7 +128,7 @@ const char* bytes::string() {
// Make sure there are 'o' bytes beyond the fill pointer,
// advance the fill pointer, and return the old fill pointer.
byte* fillbytes::grow(size_t s) {
- size_t nlen = b.len+s;
+ size_t nlen = add_size(b.len, s);
if (nlen <= allocated) {
b.len = nlen;
return limit()-s;
diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/coding.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/coding.cpp
index dec681ccfe4..df021042d62 100644
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/coding.cpp
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/coding.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -814,6 +814,7 @@ void coding_method::init(byte* &band_rp, byte* band_limit,
}
band_rp = vs.rp;
}
+ CHECK;
// Get an accurate upper limit now.
vs0.rplimit = band_rp;
diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/defines.h b/jdk/src/share/native/com/sun/java/util/jar/pack/defines.h
index 0bf25d5b0dd..87ce338067d 100644
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/defines.h
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/defines.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,11 +47,13 @@
#define NOT_PRODUCT(xxx)
#define assert(p)
#define PRINTCR(args)
+#define VERSION_STRING "%s version %s\n"
#else
#define IF_PRODUCT(xxx)
#define NOT_PRODUCT(xxx) xxx
#define assert(p) ((p) || assert_failed(#p))
#define PRINTCR(args) u->verbose && u->printcr_if_verbose args
+#define VERSION_STRING "%s version non-product %s\n"
extern "C" void breakpoint();
extern int assert_failed(const char*);
#define BREAK (breakpoint())
@@ -79,9 +81,9 @@ extern int assert_failed(const char*);
#define lengthof(array) (sizeof(array)/sizeof(array[0]))
-#define NEW(T, n) (T*) must_malloc((int)(sizeof(T)*(n)))
-#define U_NEW(T, n) (T*) u->alloc(sizeof(T)*(n))
-#define T_NEW(T, n) (T*) u->temp_alloc(sizeof(T)*(n))
+#define NEW(T, n) (T*) must_malloc((int)(scale_size(n, sizeof(T))))
+#define U_NEW(T, n) (T*) u->alloc(scale_size(n, sizeof(T)))
+#define T_NEW(T, n) (T*) u->temp_alloc(scale_size(n, sizeof(T)))
// bytes and byte arrays
@@ -153,6 +155,8 @@ enum { false, true };
#define CHECK_NULL_(y,p) _CHECK_DO((p)==null, return y)
#define CHECK_NULL_0(p) _CHECK_DO((p)==null, return 0)
+#define CHECK_COUNT(t) if (t < 0){abort("bad value count");} CHECK
+
#define STR_TRUE "true"
#define STR_FALSE "false"
diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/main.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/main.cpp
index 789841d2251..104f38bfff9 100644
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/main.cpp
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/main.cpp
@@ -299,7 +299,7 @@ int unpacker::run(int argc, char **argv) {
case 'J': argp += 1; break; // skip ignored -Jxxx parameter
case 'V':
- fprintf(u.errstrm, "%s version %s\n", nbasename(argv[0]), sccsver);
+ fprintf(u.errstrm, VERSION_STRING, nbasename(argv[0]), sccsver);
exit(0);
case 'h':
diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp
index 90b9f72e4ee..a6f4ca0c2c8 100644
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -523,15 +523,39 @@ void unpacker::read_file_header() {
enum {
MAGIC_BYTES = 4,
AH_LENGTH_0 = 3, //minver, majver, options are outside of archive_size
+ AH_LENGTH_0_MAX = AH_LENGTH_0 + 1, // options might have 2 bytes
AH_LENGTH = 26, //maximum archive header length (w/ all fields)
// Length contributions from optional header fields:
AH_FILE_HEADER_LEN = 5, // sizehi/lo/next/modtime/files
+ AH_ARCHIVE_SIZE_LEN = 2, // sizehi/lo only; part of AH_FILE_HEADER_LEN
AH_CP_NUMBER_LEN = 4, // int/float/long/double
AH_SPECIAL_FORMAT_LEN = 2, // layouts/band-headers
AH_LENGTH_MIN = AH_LENGTH
-(AH_FILE_HEADER_LEN+AH_SPECIAL_FORMAT_LEN+AH_CP_NUMBER_LEN),
+ ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - (AH_LENGTH_0 + AH_ARCHIVE_SIZE_LEN),
FIRST_READ = MAGIC_BYTES + AH_LENGTH_MIN
};
+
+ assert(AH_LENGTH_MIN == 15); // # of UNSIGNED5 fields required after archive_magic
+ assert(ARCHIVE_SIZE_MIN == 10); // # of UNSIGNED5 fields required after archive_size
+ // An absolute minimum null archive is magic[4], {minver,majver,options}[3],
+ // archive_size[0], cp_counts[8], class_counts[4], for a total of 19 bytes.
+ // (Note that archive_size is optional; it may be 0..10 bytes in length.)
+ // The first read must capture everything up through the options field.
+ // This happens to work even if {minver,majver,options} is a pathological
+ // 15 bytes long. Legal pack files limit those three fields to 1+1+2 bytes.
+ assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0 * B_MAX);
+
+ // Up through archive_size, the largest possible archive header is
+ // magic[4], {minver,majver,options}[4], archive_size[10].
+ // (Note only the low 12 bits of options are allowed to be non-zero.)
+ // In order to parse archive_size, we need at least this many bytes
+ // in the first read. Of course, if archive_size_hi is more than
+ // a byte, we probably will fail to allocate the buffer, since it
+ // will be many gigabytes long. This is a practical, not an
+ // architectural limit to Pack200 archive sizes.
+ assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0_MAX + 2*B_MAX);
+
bool foreign_buf = (read_input_fn == null);
byte initbuf[(int)FIRST_READ + (int)C_SLOP + 200]; // 200 is for JAR I/O
if (foreign_buf) {
@@ -547,7 +571,7 @@ void unpacker::read_file_header() {
// There is no way to tell the caller that we used only part of them.
// Therefore, the caller must use only a bare minimum of read-ahead.
if (inbytes.len > FIRST_READ) {
- abort("too much pushback");
+ abort("too much read-ahead");
return;
}
input.set(initbuf, sizeof(initbuf));
@@ -557,7 +581,7 @@ void unpacker::read_file_header() {
rplimit += inbytes.len;
bytes_read += inbytes.len;
}
- // Read only 19 bytes, which is certain to contain #archive_size fields,
+ // Read only 19 bytes, which is certain to contain #archive_options fields,
// but is certain not to overflow past the archive_header.
input.b.len = FIRST_READ;
if (!ensure_input(FIRST_READ))
@@ -629,26 +653,25 @@ void unpacker::read_file_header() {
#undef ORBIT
if ((archive_options & ~OPTION_LIMIT) != 0) {
fprintf(errstrm, "Warning: Illegal archive options 0x%x\n",
- archive_options);
- // Do not abort. If the format really changes, version numbers will bump.
- //abort("illegal archive options");
+ archive_options);
+ abort("illegal archive options");
+ return;
}
if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
uint hi = hdr.getInt();
uint lo = hdr.getInt();
- archive_size = band::makeLong(hi, lo);
+ julong x = band::makeLong(hi, lo);
+ archive_size = (size_t) x;
+ if (archive_size != x) {
+ // Silly size specified; force overflow.
+ archive_size = PSIZE_MAX+1;
+ }
hdrVals += 2;
} else {
hdrValsSkipped += 2;
}
- if (archive_size != (size_t)archive_size) {
- // Silly size specified.
- abort("archive too large");
- return;
- }
-
// Now we can size the whole archive.
// Read everything else into a mega-buffer.
rp = hdr.rp;
@@ -662,9 +685,18 @@ void unpacker::read_file_header() {
abort("EOF reading fixed input buffer");
return;
}
- } else if (archive_size > 0) {
- input.set(U_NEW(byte, (size_t)(header_size_0 + archive_size + C_SLOP)),
- (size_t) header_size_0 + (size_t)archive_size);
+ } else if (archive_size != 0) {
+ if (archive_size < ARCHIVE_SIZE_MIN) {
+ abort("impossible archive size"); // bad input data
+ return;
+ }
+ if (archive_size < header_size_1) {
+ abort("too much read-ahead"); // somehow we pre-fetched too much?
+ return;
+ }
+ input.set(U_NEW(byte, add_size(header_size_0, archive_size, C_SLOP)),
+ (size_t) header_size_0 + archive_size);
+ CHECK;
assert(input.limit()[0] == 0);
// Move all the bytes we read initially into the real buffer.
input.b.copyFrom(initbuf, header_size);
@@ -673,17 +705,17 @@ void unpacker::read_file_header() {
} else {
// It's more complicated and painful.
// A zero archive_size means that we must read until EOF.
- assert(archive_size == 0);
input.init(CHUNK*2);
CHECK;
input.b.len = input.allocated;
rp = rplimit = input.base();
// Set up input buffer as if we already read the header:
input.b.copyFrom(initbuf, header_size);
+ CHECK;
rplimit += header_size;
while (ensure_input(input.limit() - rp)) {
size_t dataSoFar = input_remaining();
- size_t nextSize = dataSoFar + CHUNK;
+ size_t nextSize = add_size(dataSoFar, CHUNK);
input.ensureSize(nextSize);
CHECK;
input.b.len = input.allocated;
@@ -715,8 +747,10 @@ void unpacker::read_file_header() {
if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
archive_next_count = hdr.getInt();
+ CHECK_COUNT(archive_next_count);
archive_modtime = hdr.getInt();
file_count = hdr.getInt();
+ CHECK_COUNT(file_count);
hdrVals += 3;
} else {
hdrValsSkipped += 3;
@@ -724,7 +758,9 @@ void unpacker::read_file_header() {
if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0) {
band_headers_size = hdr.getInt();
+ CHECK_COUNT(band_headers_size);
attr_definition_count = hdr.getInt();
+ CHECK_COUNT(attr_definition_count);
hdrVals += 2;
} else {
hdrValsSkipped += 2;
@@ -744,13 +780,16 @@ void unpacker::read_file_header() {
}
}
cp_counts[k] = hdr.getInt();
+ CHECK_COUNT(cp_counts[k]);
hdrVals += 1;
}
ic_count = hdr.getInt();
+ CHECK_COUNT(ic_count);
default_class_minver = hdr.getInt();
default_class_majver = hdr.getInt();
class_count = hdr.getInt();
+ CHECK_COUNT(class_count);
hdrVals += 4;
// done with archive_header
@@ -807,7 +846,6 @@ void unpacker::read_file_header() {
bytes::of(band_headers.limit(), C_SLOP).clear(_meta_error);
}
-
void unpacker::finish() {
if (verbose >= 1) {
fprintf(errstrm,
@@ -973,12 +1011,12 @@ void unpacker::read_Utf8_values(entry* cpMap, int len) {
// First band: Read lengths of shared prefixes.
if (len > PREFIX_SKIP_2)
cp_Utf8_prefix.readData(len - PREFIX_SKIP_2);
- NOT_PRODUCT(else cp_Utf8_prefix.readData(0)); // for asserts
+ NOT_PRODUCT(else cp_Utf8_prefix.readData(0)); // for asserts
// Second band: Read lengths of unshared suffixes:
if (len > SUFFIX_SKIP_1)
cp_Utf8_suffix.readData(len - SUFFIX_SKIP_1);
- NOT_PRODUCT(else cp_Utf8_suffix.readData(0)); // for asserts
+ NOT_PRODUCT(else cp_Utf8_suffix.readData(0)); // for asserts
bytes* allsuffixes = T_NEW(bytes, len);
CHECK;
@@ -2117,6 +2155,7 @@ void unpacker::read_classes() {
field_descr.readData(field_count);
read_attrs(ATTR_CONTEXT_FIELD, field_count);
+ CHECK;
method_descr.readData(method_count);
read_attrs(ATTR_CONTEXT_METHOD, method_count);
@@ -2124,6 +2163,7 @@ void unpacker::read_classes() {
CHECK;
read_attrs(ATTR_CONTEXT_CLASS, class_count);
+ CHECK;
read_code_headers();
@@ -2150,10 +2190,12 @@ void unpacker::read_attrs(int attrc, int obj_count) {
assert(endsWith(xxx_flags_hi.name, "_flags_hi"));
if (haveLongFlags)
xxx_flags_hi.readData(obj_count);
+ CHECK;
band& xxx_flags_lo = ad.xxx_flags_lo();
assert(endsWith(xxx_flags_lo.name, "_flags_lo"));
xxx_flags_lo.readData(obj_count);
+ CHECK;
// pre-scan flags, counting occurrences of each index bit
julong indexMask = ad.flagIndexMask(); // which flag bits are index bits?
@@ -2176,11 +2218,13 @@ void unpacker::read_attrs(int attrc, int obj_count) {
assert(endsWith(xxx_attr_count.name, "_attr_count"));
// There is one count element for each 1<<16 bit set in flags:
xxx_attr_count.readData(ad.predefCount(X_ATTR_OVERFLOW));
+ CHECK;
band& xxx_attr_indexes = ad.xxx_attr_indexes();
assert(endsWith(xxx_attr_indexes.name, "_attr_indexes"));
int overflowIndexCount = xxx_attr_count.getIntTotal();
xxx_attr_indexes.readData(overflowIndexCount);
+ CHECK;
// pre-scan attr indexes, counting occurrences of each value
for (i = 0; i < overflowIndexCount; i++) {
idx = xxx_attr_indexes.getInt();
@@ -2211,6 +2255,7 @@ void unpacker::read_attrs(int attrc, int obj_count) {
}
}
ad.xxx_attr_calls().readData(backwardCounts);
+ CHECK;
// Read built-in bands.
// Mostly, these are hand-coded equivalents to readBandData().
@@ -2219,42 +2264,53 @@ void unpacker::read_attrs(int attrc, int obj_count) {
count = ad.predefCount(CLASS_ATTR_SourceFile);
class_SourceFile_RUN.readData(count);
+ CHECK;
count = ad.predefCount(CLASS_ATTR_EnclosingMethod);
class_EnclosingMethod_RC.readData(count);
class_EnclosingMethod_RDN.readData(count);
+ CHECK;
count = ad.predefCount(X_ATTR_Signature);
class_Signature_RS.readData(count);
+ CHECK;
ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
count = ad.predefCount(CLASS_ATTR_InnerClasses);
class_InnerClasses_N.readData(count);
+ CHECK;
+
count = class_InnerClasses_N.getIntTotal();
class_InnerClasses_RC.readData(count);
class_InnerClasses_F.readData(count);
+ CHECK;
// Drop remaining columns wherever flags are zero:
count -= class_InnerClasses_F.getIntCount(0);
class_InnerClasses_outer_RCN.readData(count);
class_InnerClasses_name_RUN.readData(count);
+ CHECK;
count = ad.predefCount(CLASS_ATTR_ClassFile_version);
class_ClassFile_version_minor_H.readData(count);
class_ClassFile_version_major_H.readData(count);
+ CHECK;
break;
case ATTR_CONTEXT_FIELD:
count = ad.predefCount(FIELD_ATTR_ConstantValue);
field_ConstantValue_KQ.readData(count);
+ CHECK;
count = ad.predefCount(X_ATTR_Signature);
field_Signature_RS.readData(count);
+ CHECK;
ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
+ CHECK;
break;
case ATTR_CONTEXT_METHOD:
@@ -2266,15 +2322,18 @@ void unpacker::read_attrs(int attrc, int obj_count) {
method_Exceptions_N.readData(count);
count = method_Exceptions_N.getIntTotal();
method_Exceptions_RC.readData(count);
+ CHECK;
count = ad.predefCount(X_ATTR_Signature);
method_Signature_RS.readData(count);
+ CHECK;
ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
ad.readBandData(METHOD_ATTR_RuntimeVisibleParameterAnnotations);
ad.readBandData(METHOD_ATTR_RuntimeInvisibleParameterAnnotations);
ad.readBandData(METHOD_ATTR_AnnotationDefault);
+ CHECK;
break;
case ATTR_CONTEXT_CODE:
@@ -2286,8 +2345,10 @@ void unpacker::read_attrs(int attrc, int obj_count) {
return;
}
code_StackMapTable_N.readData(count);
+ CHECK;
count = code_StackMapTable_N.getIntTotal();
code_StackMapTable_frame_T.readData(count);
+ CHECK;
// the rest of it depends in a complicated way on frame tags
{
int fat_frame_count = 0;
@@ -2321,18 +2382,23 @@ void unpacker::read_attrs(int attrc, int obj_count) {
// deal completely with fat frames:
offset_count += fat_frame_count;
code_StackMapTable_local_N.readData(fat_frame_count);
+ CHECK;
type_count += code_StackMapTable_local_N.getIntTotal();
code_StackMapTable_stack_N.readData(fat_frame_count);
type_count += code_StackMapTable_stack_N.getIntTotal();
+ CHECK;
// read the rest:
code_StackMapTable_offset.readData(offset_count);
code_StackMapTable_T.readData(type_count);
+ CHECK;
// (7) [RCH]
count = code_StackMapTable_T.getIntCount(7);
code_StackMapTable_RC.readData(count);
+ CHECK;
// (8) [PH]
count = code_StackMapTable_T.getIntCount(8);
code_StackMapTable_P.readData(count);
+ CHECK;
}
count = ad.predefCount(CODE_ATTR_LineNumberTable);
@@ -2654,6 +2720,7 @@ void unpacker::read_code_headers() {
code_max_na_locals.readData();
code_handler_count.readData();
totalHandlerCount += code_handler_count.getIntTotal();
+ CHECK;
// Read handler specifications.
// Cf. PackageReader.readCodeHandlers.
@@ -2661,8 +2728,10 @@ void unpacker::read_code_headers() {
code_handler_end_PO.readData(totalHandlerCount);
code_handler_catch_PO.readData(totalHandlerCount);
code_handler_class_RCN.readData(totalHandlerCount);
+ CHECK;
read_attrs(ATTR_CONTEXT_CODE, totalFlagsCount);
+ CHECK;
}
static inline bool is_in_range(uint n, uint min, uint max) {
diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.h b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.h
index 8bad674e085..4f5965ddfb1 100644
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.h
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.h
@@ -204,7 +204,7 @@ struct unpacker {
// archive header fields
int magic, minver, majver;
- julong archive_size;
+ size_t archive_size;
int archive_next_count, archive_options, archive_modtime;
int band_headers_size;
int file_count, attr_definition_count, ic_count, class_count;
diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/utils.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/utils.cpp
index 9566e541233..b812e739bba 100644
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/utils.cpp
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/utils.cpp
@@ -46,14 +46,13 @@
#include "unpack.h"
-void* must_malloc(int size) {
- int msize = size;
- assert(size >= 0);
+void* must_malloc(size_t size) {
+ size_t msize = size;
#ifdef USE_MTRACE
- if (msize < sizeof(int))
+ if (msize >= 0 && msize < sizeof(int))
msize = sizeof(int); // see 0xbaadf00d below
#endif
- void* ptr = malloc(msize);
+ void* ptr = (msize > PSIZE_MAX) ? null : malloc(msize);
if (ptr != null) {
memset(ptr, 0, size);
} else {
diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/utils.h b/jdk/src/share/native/com/sun/java/util/jar/pack/utils.h
index 2fc1728d8e7..a4dc2c88b65 100644
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/utils.h
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/utils.h
@@ -25,13 +25,31 @@
//Definitions of our util functions
-void* must_malloc(int size);
+void* must_malloc(size_t size);
#ifndef USE_MTRACE
#define mtrace(c, ptr, size)
#else
void mtrace(char c, void* ptr, size_t size);
#endif
+// overflow management
+#define OVERFLOW ((size_t)-1)
+#define PSIZE_MAX (OVERFLOW/2) /* normal size limit */
+
+inline size_t scale_size(size_t size, size_t scale) {
+ return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
+}
+
+inline size_t add_size(size_t size1, size_t size2) {
+ return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX)
+ ? OVERFLOW
+ : size1 + size2;
+}
+
+inline size_t add_size(size_t size1, size_t size2, int size3) {
+ return add_size(add_size(size1, size2), size3);
+}
+
// These may be expensive, because they have to go via Java TSD,
// if the optional u argument is missing.
struct unpacker;
diff --git a/jdk/src/share/native/java/util/zip/ZipEntry.c b/jdk/src/share/native/java/util/zip/ZipEntry.c
deleted file mode 100644
index 94cd68e1b12..00000000000
--- a/jdk/src/share/native/java/util/zip/ZipEntry.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 1998 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/*
- * Native method support for java.util.zip.ZipEntry
- */
-
-#include
-#include
-#include "jlong.h"
-#include "jvm.h"
-#include "jni.h"
-#include "jni_util.h"
-#include "zip_util.h"
-
-#include "java_util_zip_ZipEntry.h"
-
-#define DEFLATED 8
-#define STORED 0
-
-static jfieldID nameID;
-static jfieldID timeID;
-static jfieldID crcID;
-static jfieldID sizeID;
-static jfieldID csizeID;
-static jfieldID methodID;
-static jfieldID extraID;
-static jfieldID commentID;
-
-JNIEXPORT void JNICALL
-Java_java_util_zip_ZipEntry_initIDs(JNIEnv *env, jclass cls)
-{
- nameID = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");
- timeID = (*env)->GetFieldID(env, cls, "time", "J");
- crcID = (*env)->GetFieldID(env, cls, "crc", "J");
- sizeID = (*env)->GetFieldID(env, cls, "size", "J");
- csizeID = (*env)->GetFieldID(env, cls, "csize", "J");
- methodID = (*env)->GetFieldID(env, cls, "method", "I");
- extraID = (*env)->GetFieldID(env, cls, "extra", "[B");
- commentID = (*env)->GetFieldID(env, cls, "comment", "Ljava/lang/String;");
-}
-
-JNIEXPORT void JNICALL
-Java_java_util_zip_ZipEntry_initFields(JNIEnv *env, jobject obj, jlong zentry)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- jstring name = (*env)->GetObjectField(env, obj, nameID);
-
- if (name == 0) {
- name = (*env)->NewStringUTF(env, ze->name);
- if (name == 0) {
- return;
- }
- (*env)->SetObjectField(env, obj, nameID, name);
- }
- (*env)->SetLongField(env, obj, timeID, (jlong)ze->time & 0xffffffffUL);
- (*env)->SetLongField(env, obj, crcID, (jlong)ze->crc & 0xffffffffUL);
- (*env)->SetLongField(env, obj, sizeID, (jlong)ze->size);
- if (ze->csize == 0) {
- (*env)->SetLongField(env, obj, csizeID, (jlong)ze->size);
- (*env)->SetIntField(env, obj, methodID, STORED);
- } else {
- (*env)->SetLongField(env, obj, csizeID, (jlong)ze->csize);
- (*env)->SetIntField(env, obj, methodID, DEFLATED);
- }
- if (ze->extra != 0) {
- unsigned char *bp = (unsigned char *)&ze->extra[0];
- jsize len = (bp[0] | (bp[1] << 8));
- jbyteArray extra = (*env)->NewByteArray(env, len);
- if (extra == 0) {
- return;
- }
- (*env)->SetByteArrayRegion(env, extra, 0, len, &ze->extra[2]);
- (*env)->SetObjectField(env, obj, extraID, extra);
- }
- if (ze->comment != 0) {
- jstring comment = (*env)->NewStringUTF(env, ze->comment);
- if (comment == 0) {
- return;
- }
- (*env)->SetObjectField(env, obj, commentID, comment);
- }
-}
diff --git a/jdk/src/share/native/java/util/zip/ZipFile.c b/jdk/src/share/native/java/util/zip/ZipFile.c
index 0c20536b49a..d5cb1ecac8b 100644
--- a/jdk/src/share/native/java/util/zip/ZipFile.c
+++ b/jdk/src/share/native/java/util/zip/ZipFile.c
@@ -141,12 +141,11 @@ Java_java_util_zip_ZipFile_close(JNIEnv *env, jclass cls, jlong zfile)
JNIEXPORT jlong JNICALL
Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
- jstring name, jboolean addSlash)
+ jbyteArray name, jboolean addSlash)
{
#define MAXNAME 1024
jzfile *zip = jlong_to_ptr(zfile);
- jsize slen = (*env)->GetStringLength(env, name);
- jsize ulen = (*env)->GetStringUTFLength(env, name);
+ jsize ulen = (*env)->GetArrayLength(env, name);
char buf[MAXNAME+2], *path;
jzentry *ze;
@@ -159,7 +158,7 @@ Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
} else {
path = buf;
}
- (*env)->GetStringUTFRegion(env, name, 0, slen, path);
+ (*env)->GetByteArrayRegion(env, name, 0, ulen, (jbyte *)path);
path[ulen] = '\0';
if (addSlash == JNI_FALSE) {
ze = ZIP_GetEntry(zip, path, 0);
@@ -186,34 +185,87 @@ Java_java_util_zip_ZipFile_getNextEntry(JNIEnv *env, jclass cls, jlong zfile,
jint n)
{
jzentry *ze = ZIP_GetNextEntry(jlong_to_ptr(zfile), n);
-
return ptr_to_jlong(ze);
}
JNIEXPORT jint JNICALL
-Java_java_util_zip_ZipFile_getMethod(JNIEnv *env, jclass cls, jlong zentry)
+Java_java_util_zip_ZipFile_getEntryMethod(JNIEnv *env, jclass cls, jlong zentry)
{
jzentry *ze = jlong_to_ptr(zentry);
-
return ze->csize != 0 ? DEFLATED : STORED;
}
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getCSize(JNIEnv *env, jclass cls, jlong zentry)
+JNIEXPORT jint JNICALL
+Java_java_util_zip_ZipFile_getEntryFlag(JNIEnv *env, jclass cls, jlong zentry)
{
jzentry *ze = jlong_to_ptr(zentry);
+ return ze->flag;
+}
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_ZipFile_getEntryCSize(JNIEnv *env, jclass cls, jlong zentry)
+{
+ jzentry *ze = jlong_to_ptr(zentry);
return ze->csize != 0 ? ze->csize : ze->size;
}
JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getSize(JNIEnv *env, jclass cls, jlong zentry)
+Java_java_util_zip_ZipFile_getEntrySize(JNIEnv *env, jclass cls, jlong zentry)
{
jzentry *ze = jlong_to_ptr(zentry);
-
return ze->size;
}
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_ZipFile_getEntryTime(JNIEnv *env, jclass cls, jlong zentry)
+{
+ jzentry *ze = jlong_to_ptr(zentry);
+ return (jlong)ze->time & 0xffffffffUL;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_ZipFile_getEntryCrc(JNIEnv *env, jclass cls, jlong zentry)
+{
+ jzentry *ze = jlong_to_ptr(zentry);
+ return (jlong)ze->crc & 0xffffffffUL;
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_java_util_zip_ZipFile_getEntryBytes(JNIEnv *env, jclass cls, jlong zentry, jint type)
+{
+ jzentry *ze = jlong_to_ptr(zentry);
+ int len = 0;
+ jbyteArray jba = NULL;
+ switch (type) {
+ case java_util_zip_ZipFile_JZENTRY_NAME:
+ if (ze->name != 0) {
+ len = (int)strlen(ze->name);
+ if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
+ break;
+ (*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte *)ze->name);
+ }
+ break;
+ case java_util_zip_ZipFile_JZENTRY_EXTRA:
+ if (ze->extra != 0) {
+ unsigned char *bp = (unsigned char *)&ze->extra[0];
+ len = (bp[0] | (bp[1] << 8));
+ if (len <= 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
+ break;
+ (*env)->SetByteArrayRegion(env, jba, 0, len, &ze->extra[2]);
+ }
+ break;
+ case java_util_zip_ZipFile_JZENTRY_COMMENT:
+ if (ze->comment != 0) {
+ len = (int)strlen(ze->comment);
+ if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
+ break;
+ (*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte*)ze->comment);
+ }
+ break;
+ }
+ return jba;
+}
+
JNIEXPORT jint JNICALL
Java_java_util_zip_ZipFile_read(JNIEnv *env, jclass cls, jlong zfile,
jlong zentry, jlong pos, jbyteArray bytes,
diff --git a/jdk/src/share/native/java/util/zip/zip_util.c b/jdk/src/share/native/java/util/zip/zip_util.c
index 89f52ae3bcc..626d4118f75 100644
--- a/jdk/src/share/native/java/util/zip/zip_util.c
+++ b/jdk/src/share/native/java/util/zip/zip_util.c
@@ -512,7 +512,6 @@ readCEN(jzfile *zip, jint knownTotal)
/* Clear previous zip error */
zip->msg = NULL;
-
/* Get position of END header */
if ((endpos = findEND(zip, endbuf)) == -1)
return -1; /* no END header or system error */
@@ -520,7 +519,6 @@ readCEN(jzfile *zip, jint knownTotal)
if (endpos == 0) return 0; /* only END header present */
freeCEN(zip);
-
/* Get position and length of central directory */
cenlen = ENDSIZ(endbuf);
cenoff = ENDOFF(endbuf);
@@ -935,6 +933,7 @@ newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
ze->crc = CENCRC(cen);
locoff = CENOFF(cen);
ze->pos = -(zip->locpos + locoff);
+ ze->flag = CENFLG(cen);
if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
memcpy(ze->name, cen + CENHDR, nlen);
diff --git a/jdk/src/share/native/java/util/zip/zip_util.h b/jdk/src/share/native/java/util/zip/zip_util.h
index 7ad11715e5a..311a9fcd9de 100644
--- a/jdk/src/share/native/java/util/zip/zip_util.h
+++ b/jdk/src/share/native/java/util/zip/zip_util.h
@@ -168,6 +168,7 @@ typedef struct jzentry { /* Zip file entry */
char *comment; /* optional zip file comment */
jbyte *extra; /* optional extra data */
jlong pos; /* position of LOC header or entry data */
+ jint flag; /* general purpose flag */
} jzentry;
/*
diff --git a/jdk/src/share/native/sun/awt/giflib/dgif_lib.c b/jdk/src/share/native/sun/awt/giflib/dgif_lib.c
index be91d3e7811..f20372fe925 100644
--- a/jdk/src/share/native/sun/awt/giflib/dgif_lib.c
+++ b/jdk/src/share/native/sun/awt/giflib/dgif_lib.c
@@ -722,6 +722,10 @@ DGifSetupDecompress(GifFileType * GifFile) {
GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
READ(GifFile, &CodeSize, 1); /* Read Code size from file. */
+ if (CodeSize >= 12) {
+ /* Invalid initial code size: report failure */
+ return GIF_ERROR;
+ }
BitsPerPixel = CodeSize;
Private->Buf[0] = 0; /* Input Buffer empty. */
@@ -964,10 +968,13 @@ DGifDecompressInput(GifFileType * GifFile,
/* If code cannot fit into RunningBits bits, must raise its size. Note
* however that codes above 4095 are used for special signaling. */
- if (++Private->RunningCode > Private->MaxCode1 &&
- Private->RunningBits < LZ_BITS) {
- Private->MaxCode1 <<= 1;
- Private->RunningBits++;
+ if (++Private->RunningCode > Private->MaxCode1) {
+ if (Private->RunningBits < LZ_BITS) {
+ Private->MaxCode1 <<= 1;
+ Private->RunningBits++;
+ } else {
+ Private->RunningCode = Private->MaxCode1;
+ }
}
return GIF_OK;
}
diff --git a/jdk/src/share/native/sun/awt/image/gif/gifdecoder.c b/jdk/src/share/native/sun/awt/image/gif/gifdecoder.c
index 1429931f8c6..893007f1366 100644
--- a/jdk/src/share/native/sun/awt/image/gif/gifdecoder.c
+++ b/jdk/src/share/native/sun/awt/image/gif/gifdecoder.c
@@ -191,6 +191,11 @@ Java_sun_awt_image_GifImageDecoder_parseImage(JNIEnv *env,
int passht = passinc;
int len;
+ /* We have verified the initial code size on the java layer.
+ * Here we just check bounds for particular indexes. */
+ if (freeCode >= 4096 || maxCode >= 4096) {
+ return 0;
+ }
if (blockh == 0 || raslineh == 0
|| prefixh == 0 || suffixh == 0
|| outCodeh == 0)
diff --git a/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c b/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c
index 681f26290b8..157827fef29 100644
--- a/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c
+++ b/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c
@@ -216,6 +216,16 @@ printMedialibError(int status) {
#endif /* ! DEBUG */
+static int
+getMlibEdgeHint(jint edgeHint) {
+ switch (edgeHint) {
+ case java_awt_image_ConvolveOp_EDGE_NO_OP:
+ return MLIB_EDGE_DST_COPY_SRC;
+ case java_awt_image_ConvolveOp_EDGE_ZERO_FILL:
+ default:
+ return MLIB_EDGE_DST_FILL_ZERO;
+ }
+}
/***************************************************************************
* External Functions *
@@ -400,22 +410,10 @@ Java_sun_awt_image_ImagingLib_convolveBI(JNIEnv *env, jobject this,
}
}
- if (edgeHint == java_awt_image_ConvolveOp_EDGE_NO_OP) {
- int kw2 = kwidth>>1;
- int kh2 = kheight>>1;
- int bsize = mlib_ImageGetChannels(src)*
- (mlib_ImageGetType(src) == MLIB_BYTE ? 1 : 2);
-
- void *dstDataP = mlib_ImageGetData(dst);
- void *srcDataP = mlib_ImageGetData(src);
- /* REMIND: Copy a smaller area */
- memcpy(dstDataP, srcDataP, dst->width*dst->height*bsize);
- }
-
cmask = (1<channels)-1;
status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
(w-1)/2, (h-1)/2, scale, cmask,
- MLIB_EDGE_DST_NO_WRITE);
+ getMlibEdgeHint(edgeHint));
if (status != MLIB_SUCCESS) {
printMedialibError(status);
@@ -660,22 +658,10 @@ Java_sun_awt_image_ImagingLib_convolveRaster(JNIEnv *env, jobject this,
}
}
- if (edgeHint == java_awt_image_ConvolveOp_EDGE_NO_OP) {
- int kw2 = kwidth>>1;
- int kh2 = kheight>>1;
- int bsize = mlib_ImageGetChannels(src)*
- (mlib_ImageGetType(src) == MLIB_BYTE ? 1 : 2);
-
- void *dstDataP = mlib_ImageGetData(dst);
- void *srcDataP = mlib_ImageGetData(src);
- /* REMIND: Copy a smaller area */
- memcpy(dstDataP, srcDataP, dst->width*dst->height*bsize);
- }
-
cmask = (1<channels)-1;
status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
(w-1)/2, (h-1)/2, scale, cmask,
- MLIB_EDGE_DST_NO_WRITE);
+ getMlibEdgeHint(edgeHint));
if (status != MLIB_SUCCESS) {
printMedialibError(status);
diff --git a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.h b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.h
index 1c55702fe73..32f7d4e2e47 100644
--- a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.h
+++ b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.h
@@ -31,7 +31,7 @@
/* here come some very simple macros */
/* advance a pointer p by sizeof(type)*n bytes */
-#define INCPN(type,p,n) ((p) = (type*)(p)+n)
+#define INCPN(type,p,n) ((p) = (type*)(p)+(n))
/* advance a pointer by sizeof(type) */
#define INCP(type,p) INCPN(type,(p),1)
diff --git a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gif.c b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gif.c
index f6d9acb0c36..f1651ab1f49 100644
--- a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gif.c
+++ b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gif.c
@@ -62,6 +62,15 @@ SplashStreamGifInputFunc(GifFileType * gif, GifByteType * buf, int n)
return rc;
}
+/* These macro help to ensure that we only take part of frame that fits into
+ logical screen. */
+
+/* Ensure that p belongs to [pmin, pmax) interval. Returns fixed point (if fix is needed) */
+#define FIX_POINT(p, pmin, pmax) ( ((p) < (pmin)) ? (pmin) : (((p) > (pmax)) ? (pmax) : (p)))
+/* Ensures that line starting at point p does not exceed boundary pmax.
+ Returns fixed length (if fix is needed) */
+#define FIX_LENGTH(p, len, pmax) ( ((p) + (len)) > (pmax) ? ((pmax) - (p)) : (len))
+
int
SplashDecodeGif(Splash * splash, GifFileType * gif)
{
@@ -70,6 +79,7 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
byte_t *pBitmapBits, *pOldBitmapBits;
int i, j;
int imageIndex;
+ int cx, cy, cw, ch; /* clamped coordinates */
const int interlacedOffset[] = { 0, 4, 2, 1, 0 }; /* The way Interlaced image should. */
const int interlacedJumps[] = { 8, 8, 4, 2, 1 }; /* be read - offsets and jumps... */
@@ -79,14 +89,31 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
SplashCleanup(splash);
+ if (!SAFE_TO_ALLOC(gif->SWidth, splash->imageFormat.depthBytes)) {
+ return 0;
+ }
stride = gif->SWidth * splash->imageFormat.depthBytes;
if (splash->byteAlignment > 1)
stride =
(stride + splash->byteAlignment - 1) & ~(splash->byteAlignment - 1);
+ if (!SAFE_TO_ALLOC(gif->SHeight, stride)) {
+ return 0;
+ }
+
+ if (!SAFE_TO_ALLOC(gif->ImageCount, sizeof(SplashImage*))) {
+ return 0;
+ }
bufferSize = stride * gif->SHeight;
pBitmapBits = (byte_t *) malloc(bufferSize);
+ if (!pBitmapBits) {
+ return 0;
+ }
pOldBitmapBits = (byte_t *) malloc(bufferSize);
+ if (!pOldBitmapBits) {
+ free(pBitmapBits);
+ return 0;
+ }
memset(pBitmapBits, 0, bufferSize);
splash->width = gif->SWidth;
@@ -94,6 +121,11 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
splash->frameCount = gif->ImageCount;
splash->frames = (SplashImage *)
malloc(sizeof(SplashImage) * gif->ImageCount);
+ if (!splash->frames) {
+ free(pBitmapBits);
+ free(pOldBitmapBits);
+ return 0;
+ }
memset(splash->frames, 0, sizeof(SplashImage) * gif->ImageCount);
splash->loopCount = 1;
@@ -109,6 +141,11 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
int colorCount = 0;
rgbquad_t colorMapBuf[SPLASH_COLOR_MAP_SIZE];
+ cx = FIX_POINT(desc->Left, 0, gif->SWidth);
+ cy = FIX_POINT(desc->Top, 0, gif->SHeight);
+ cw = FIX_LENGTH(desc->Left, desc->Width, gif->SWidth);
+ ch = FIX_LENGTH(desc->Top, desc->Height, gif->SHeight);
+
if (colorMap) {
if (colorMap->ColorCount <= SPLASH_COLOR_MAP_SIZE) {
colorCount = colorMap->ColorCount;
@@ -195,13 +232,22 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
for (; pass < npass; ++pass) {
int jump = interlacedJumps[pass];
int ofs = interlacedOffset[pass];
- int numLines = (desc->Height + jump - 1 - ofs) / jump;
+ /* Number of source lines for current pass */
+ int numPassLines = (desc->Height + jump - ofs - 1) / jump;
+ /* Number of lines that fits to dest buffer */
+ int numLines = (ch + jump - ofs - 1) / jump;
initRect(&srcRect, 0, 0, desc->Width, numLines, 1,
desc->Width, pSrc, &srcFormat);
- initRect(&dstRect, desc->Left, desc->Top + ofs, desc->Width,
- numLines, jump, stride, pBitmapBits, &splash->imageFormat);
- pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
+
+ if (numLines > 0) {
+ initRect(&dstRect, cx, cy + ofs, cw,
+ numLines , jump, stride, pBitmapBits, &splash->imageFormat);
+
+ pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
+ }
+ // skip extra source data
+ pSrc += (numPassLines - numLines) * srcRect.stride;
}
}
@@ -209,6 +255,12 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
splash->frames[imageIndex].bitmapBits =
(rgbquad_t *) malloc(bufferSize);
+ if (!splash->frames[imageIndex].bitmapBits) {
+ free(pBitmapBits);
+ free(pOldBitmapBits);
+ /* Assuming that callee will take care of splash frames we have already allocated */
+ return 0;
+ }
memcpy(splash->frames[imageIndex].bitmapBits, pBitmapBits, bufferSize);
SplashInitFrameShape(splash, imageIndex);
@@ -224,27 +276,29 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
{
ImageRect dstRect;
rgbquad_t fillColor = 0; // 0 is transparent
- if (transparentColor < 0) {
+
+ if (transparentColor > 0) {
fillColor= MAKE_QUAD_GIF(
colorMap->Colors[gif->SBackGroundColor], 0xff);
}
- initRect(&dstRect, desc->Left, desc->Top,
- desc->Width, desc->Height, 1, stride,
- pBitmapBits, &splash->imageFormat);
+ initRect(&dstRect,
+ cx, cy, cw, ch,
+ 1, stride,
+ pBitmapBits, &splash->imageFormat);
fillRect(fillColor, &dstRect);
}
break;
case GIF_DISPOSE_RESTORE:
{
-
- int lineSize = desc->Width * splash->imageFormat.depthBytes;
-
- for (j = 0; j < desc->Height; j++) {
- int lineIndex = stride * (j + desc->Top) +
- desc->Left * splash->imageFormat.depthBytes;
-
- memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
- lineSize);
+ int lineSize = cw * splash->imageFormat.depthBytes;
+ if (lineSize > 0) {
+ int lineOffset = cx * splash->imageFormat.depthBytes;
+ int lineIndex = cy * stride + lineOffset;
+ for (j=0; j 0) && ((sz) > 0) && \
+ ((0xffffffffu / ((unsigned int)(c))) > (unsigned int)(sz)))
+
#define dbgprintf printf
#endif
diff --git a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_png.c b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_png.c
index f0926ec90dc..abc54dcb753 100644
--- a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_png.c
+++ b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_png.c
@@ -103,9 +103,17 @@ SplashDecodePng(Splash * splash, png_rw_ptr read_func, void *io_ptr)
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+ if (!SAFE_TO_ALLOC(rowbytes, height)) {
+ goto done;
+ }
+
if ((image_data = (unsigned char *) malloc(rowbytes * height)) == NULL) {
goto done;
}
+
+ if (!SAFE_TO_ALLOC(height, sizeof(png_bytep))) {
+ goto done;
+ }
if ((row_pointers = (png_bytepp) malloc(height * sizeof(png_bytep)))
== NULL) {
goto done;
@@ -121,13 +129,28 @@ SplashDecodePng(Splash * splash, png_rw_ptr read_func, void *io_ptr)
splash->width = width;
splash->height = height;
+ if (!SAFE_TO_ALLOC(splash->width, splash->imageFormat.depthBytes)) {
+ goto done;
+ }
stride = splash->width * splash->imageFormat.depthBytes;
+ if (!SAFE_TO_ALLOC(splash->height, stride)) {
+ goto done;
+ }
splash->frameCount = 1;
splash->frames = (SplashImage *)
malloc(sizeof(SplashImage) * splash->frameCount);
+
+ if (splash->frames == NULL) {
+ goto done;
+ }
+
splash->loopCount = 1;
splash->frames[0].bitmapBits = malloc(stride * splash->height);
+ if (splash->frames[0].bitmapBits == NULL) {
+ free(splash->frames);
+ goto done;
+ }
splash->frames[0].delay = 0;
/* FIXME: sort out the real format */
diff --git a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java
index ef668648d67..e08f460d919 100644
--- a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java
@@ -354,16 +354,9 @@ public class WindowsAsynchronousFileChannelImpl
}
}
- // invoke by FileFileImpl to release lock
@Override
- void release(FileLockImpl fli) throws IOException {
- try {
- begin();
- nd.release(fdObj, fli.position(), fli.size());
- removeFromFileLockTable(fli);
- } finally {
- end();
- }
+ protected void implRelease(FileLockImpl fli) throws IOException {
+ nd.release(fdObj, fli.position(), fli.size());
}
/**
diff --git a/jdk/src/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java b/jdk/src/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java
index 146d7c1632d..44dd25ab8cd 100644
--- a/jdk/src/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java
+++ b/jdk/src/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@ import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec;
import sun.security.jca.JCAUtil;
+import sun.security.rsa.RSAKeyFactory;
/**
* RSA keypair generator.
@@ -43,8 +44,8 @@ import sun.security.jca.JCAUtil;
public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// Supported by Microsoft Base, Strong and Enhanced Cryptographic Providers
- private static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384
- private static final int KEY_SIZE_MAX = 16384;
+ static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384
+ static final int KEY_SIZE_MAX = 16384;
private static final int KEY_SIZE_DEFAULT = 1024;
// size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX
@@ -59,7 +60,14 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// random is always ignored
public void initialize(int keySize, SecureRandom random) {
- checkKeySize(keySize);
+ try {
+ RSAKeyFactory.checkKeyLengths(keySize, null,
+ KEY_SIZE_MIN, KEY_SIZE_MAX);
+ } catch (InvalidKeyException e) {
+ throw new InvalidParameterException(e.getMessage());
+ }
+
+ this.keySize = keySize;
}
// second initialize method. See JCA doc
@@ -67,21 +75,31 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException {
+ int tmpSize;
if (params == null) {
- checkKeySize(KEY_SIZE_DEFAULT);
-
+ tmpSize = KEY_SIZE_DEFAULT;
} else if (params instanceof RSAKeyGenParameterSpec) {
if (((RSAKeyGenParameterSpec) params).getPublicExponent() != null) {
throw new InvalidAlgorithmParameterException
("Exponent parameter is not supported");
}
- checkKeySize(((RSAKeyGenParameterSpec) params).getKeysize());
+ tmpSize = ((RSAKeyGenParameterSpec) params).getKeysize();
} else {
throw new InvalidAlgorithmParameterException
("Params must be an instance of RSAKeyGenParameterSpec");
}
+
+ try {
+ RSAKeyFactory.checkKeyLengths(tmpSize, null,
+ KEY_SIZE_MIN, KEY_SIZE_MAX);
+ } catch (InvalidKeyException e) {
+ throw new InvalidAlgorithmParameterException(
+ "Invalid Key sizes", e);
+ }
+
+ this.keySize = tmpSize;
}
// generate the keypair. See JCA doc
@@ -95,18 +113,6 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
return new KeyPair(keys.getPublic(), keys.getPrivate());
}
- private void checkKeySize(int keySize) throws InvalidParameterException {
- if (keySize < KEY_SIZE_MIN) {
- throw new InvalidParameterException
- ("Key size must be at least " + KEY_SIZE_MIN + " bits");
- }
- if (keySize > KEY_SIZE_MAX) {
- throw new InvalidParameterException
- ("Key size must be " + KEY_SIZE_MAX + " bits or less");
- }
- this.keySize = keySize;
- }
-
private static native RSAKeyPair generateRSAKeyPair(int keySize,
String keyContainerName);
}
diff --git a/jdk/src/windows/classes/sun/security/mscapi/RSASignature.java b/jdk/src/windows/classes/sun/security/mscapi/RSASignature.java
index 606423d53a4..982e1836a7d 100644
--- a/jdk/src/windows/classes/sun/security/mscapi/RSASignature.java
+++ b/jdk/src/windows/classes/sun/security/mscapi/RSASignature.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,9 @@ import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureSpi;
import java.security.SignatureException;
+import java.math.BigInteger;
+
+import sun.security.rsa.RSAKeyFactory;
/**
* RSA signature implementation. Supports RSA signing using PKCS#1 v1.5 padding.
@@ -124,7 +127,16 @@ abstract class RSASignature extends java.security.SignatureSpi
// convert key to MSCAPI format
- byte[] modulusBytes = rsaKey.getModulus().toByteArray();
+ BigInteger modulus = rsaKey.getModulus();
+ BigInteger exponent = rsaKey.getPublicExponent();
+
+ // Check against the local and global values to make sure
+ // the sizes are ok. Round up to the nearest byte.
+ RSAKeyFactory.checkKeyLengths(((modulus.bitLength() + 7) & ~7),
+ exponent, -1, RSAKeyPairGenerator.KEY_SIZE_MAX);
+
+ byte[] modulusBytes = modulus.toByteArray();
+ byte[] exponentBytes = exponent.toByteArray();
// Adjust key length due to sign bit
int keyBitLength = (modulusBytes[0] == 0)
@@ -132,8 +144,7 @@ abstract class RSASignature extends java.security.SignatureSpi
: modulusBytes.length * 8;
byte[] keyBlob = generatePublicKeyBlob(
- keyBitLength, modulusBytes,
- rsaKey.getPublicExponent().toByteArray());
+ keyBitLength, modulusBytes, exponentBytes);
publicKey = importPublicKey(keyBlob, keyBitLength);
@@ -166,12 +177,11 @@ abstract class RSASignature extends java.security.SignatureSpi
}
privateKey = (sun.security.mscapi.RSAPrivateKey) key;
- // Determine byte length from bit length
- int keySize = (privateKey.bitLength() + 7) >> 3;
-
- if (keySize < 64)
- throw new InvalidKeyException(
- "RSA keys must be at least 512 bits long");
+ // Check against the local and global values to make sure
+ // the sizes are ok. Round up to nearest byte.
+ RSAKeyFactory.checkKeyLengths(((privateKey.bitLength() + 7) & ~7),
+ null, RSAKeyPairGenerator.KEY_SIZE_MIN,
+ RSAKeyPairGenerator.KEY_SIZE_MAX);
if (needsReset) {
messageDigest.reset();
diff --git a/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c b/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c
index a65ad90e24d..7b41d86fad1 100644
--- a/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c
+++ b/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c
@@ -414,7 +414,7 @@ Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this,
o.Offset = lowPos;
o.OffsetHigh = highPos;
result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o);
- if (result == 0) {
+ if (result == 0 && GetLastError() != ERROR_NOT_LOCKED) {
JNU_ThrowIOExceptionWithLastError(env, "Release failed");
}
}
diff --git a/jdk/src/windows/native/sun/security/krb5/NativeCreds.c b/jdk/src/windows/native/sun/security/krb5/NativeCreds.c
index e112b86e9c3..c910c62be4a 100644
--- a/jdk/src/windows/native/sun/security/krb5/NativeCreds.c
+++ b/jdk/src/windows/native/sun/security/krb5/NativeCreds.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Portions Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -73,6 +73,7 @@ jmethodID setRealmMethod = 0;
* Function prototypes for internal routines
*
*/
+BOOL native_debug = 0;
BOOL PackageConnectLookup(PHANDLE,PULONG);
@@ -113,208 +114,221 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
jclass cls;
JNIEnv *env;
+ jfieldID fldDEBUG;
if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {
return JNI_EVERSION; /* JNI version not supported */
}
+ cls = (*env)->FindClass(env,"sun/security/krb5/internal/Krb5");
+ if (cls == NULL) {
+ printf("LSA: Couldn't find Krb5\n");
+ return JNI_ERR;
+ }
+ fldDEBUG = (*env)->GetStaticFieldID(env, cls, "DEBUG", "Z");
+ if (fldDEBUG == NULL) {
+ printf("LSA: Krb5 has no DEBUG field\n");
+ return JNI_ERR;
+ }
+ native_debug = (*env)->GetStaticBooleanField(env, cls, fldDEBUG);
+
cls = (*env)->FindClass(env,"sun/security/krb5/internal/Ticket");
if (cls == NULL) {
- printf("Couldn't find Ticket\n");
+ printf("LSA: Couldn't find Ticket\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Found Ticket\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Found Ticket\n");
+ }
ticketClass = (*env)->NewWeakGlobalRef(env,cls);
if (ticketClass == NULL) {
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Made NewWeakGlobalRef\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Made NewWeakGlobalRef\n");
+ }
cls = (*env)->FindClass(env, "sun/security/krb5/PrincipalName");
if (cls == NULL) {
- printf("Couldn't find PrincipalName\n");
+ printf("LSA: Couldn't find PrincipalName\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Found PrincipalName\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Found PrincipalName\n");
+ }
principalNameClass = (*env)->NewWeakGlobalRef(env,cls);
if (principalNameClass == NULL) {
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Made NewWeakGlobalRef\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Made NewWeakGlobalRef\n");
+ }
cls = (*env)->FindClass(env,"sun/security/util/DerValue");
if (cls == NULL) {
- printf("Couldn't find DerValue\n");
+ printf("LSA: Couldn't find DerValue\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Found DerValue\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Found DerValue\n");
+ }
derValueClass = (*env)->NewWeakGlobalRef(env,cls);
if (derValueClass == NULL) {
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Made NewWeakGlobalRef\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Made NewWeakGlobalRef\n");
+ }
cls = (*env)->FindClass(env,"sun/security/krb5/EncryptionKey");
if (cls == NULL) {
- printf("Couldn't find EncryptionKey\n");
+ printf("LSA: Couldn't find EncryptionKey\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Found EncryptionKey\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Found EncryptionKey\n");
+ }
encryptionKeyClass = (*env)->NewWeakGlobalRef(env,cls);
if (encryptionKeyClass == NULL) {
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Made NewWeakGlobalRef\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Made NewWeakGlobalRef\n");
+ }
cls = (*env)->FindClass(env,"sun/security/krb5/internal/TicketFlags");
if (cls == NULL) {
- printf("Couldn't find TicketFlags\n");
+ printf("LSA: Couldn't find TicketFlags\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Found TicketFlags\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Found TicketFlags\n");
+ }
ticketFlagsClass = (*env)->NewWeakGlobalRef(env,cls);
if (ticketFlagsClass == NULL) {
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Made NewWeakGlobalRef\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Made NewWeakGlobalRef\n");
+ }
cls = (*env)->FindClass(env,"sun/security/krb5/internal/KerberosTime");
if (cls == NULL) {
- printf("Couldn't find KerberosTime\n");
+ printf("LSA: Couldn't find KerberosTime\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Found KerberosTime\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Found KerberosTime\n");
+ }
kerberosTimeClass = (*env)->NewWeakGlobalRef(env,cls);
if (kerberosTimeClass == NULL) {
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Made NewWeakGlobalRef\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Made NewWeakGlobalRef\n");
+ }
cls = (*env)->FindClass(env,"java/lang/String");
if (cls == NULL) {
- printf("Couldn't find String\n");
+ printf("LSA: Couldn't find String\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Found String\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Found String\n");
+ }
javaLangStringClass = (*env)->NewWeakGlobalRef(env,cls);
if (javaLangStringClass == NULL) {
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Made NewWeakGlobalRef\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Made NewWeakGlobalRef\n");
+ }
derValueConstructor = (*env)->GetMethodID(env, derValueClass,
"", "([B)V");
if (derValueConstructor == 0) {
- printf("Couldn't find DerValue constructor\n");
+ printf("LSA: Couldn't find DerValue constructor\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Found DerValue constructor\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Found DerValue constructor\n");
+ }
ticketConstructor = (*env)->GetMethodID(env, ticketClass,
"", "(Lsun/security/util/DerValue;)V");
if (ticketConstructor == 0) {
- printf("Couldn't find Ticket constructor\n");
+ printf("LSA: Couldn't find Ticket constructor\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Found Ticket constructor\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Found Ticket constructor\n");
+ }
principalNameConstructor = (*env)->GetMethodID(env, principalNameClass,
"", "([Ljava/lang/String;)V");
if (principalNameConstructor == 0) {
- printf("Couldn't find PrincipalName constructor\n");
+ printf("LSA: Couldn't find PrincipalName constructor\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Found PrincipalName constructor\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Found PrincipalName constructor\n");
+ }
encryptionKeyConstructor = (*env)->GetMethodID(env, encryptionKeyClass,
"", "(I[B)V");
if (encryptionKeyConstructor == 0) {
- printf("Couldn't find EncryptionKey constructor\n");
+ printf("LSA: Couldn't find EncryptionKey constructor\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Found EncryptionKey constructor\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Found EncryptionKey constructor\n");
+ }
ticketFlagsConstructor = (*env)->GetMethodID(env, ticketFlagsClass,
"", "(I[B)V");
if (ticketFlagsConstructor == 0) {
- printf("Couldn't find TicketFlags constructor\n");
+ printf("LSA: Couldn't find TicketFlags constructor\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Found TicketFlags constructor\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Found TicketFlags constructor\n");
+ }
kerberosTimeConstructor = (*env)->GetMethodID(env, kerberosTimeClass,
"", "(Ljava/lang/String;)V");
if (kerberosTimeConstructor == 0) {
- printf("Couldn't find KerberosTime constructor\n");
+ printf("LSA: Couldn't find KerberosTime constructor\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Found KerberosTime constructor\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Found KerberosTime constructor\n");
+ }
// load the setRealm method in PrincipalName
setRealmMethod = (*env)->GetMethodID(env, principalNameClass,
"setRealm", "(Ljava/lang/String;)V");
if (setRealmMethod == 0) {
- printf("Couldn't find setRealm in PrincipalName\n");
+ printf("LSA: Couldn't find setRealm in PrincipalName\n");
return JNI_ERR;
}
- #ifdef DEBUG
- printf("Finished OnLoad processing\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Finished OnLoad processing\n");
+ }
return JNI_VERSION_1_2;
}
@@ -389,16 +403,25 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
if (krbcredsConstructor == 0) {
krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "",
- "(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V");
+ "(Lsun/security/krb5/internal/Ticket;"
+ "Lsun/security/krb5/PrincipalName;"
+ "Lsun/security/krb5/PrincipalName;"
+ "Lsun/security/krb5/EncryptionKey;"
+ "Lsun/security/krb5/internal/TicketFlags;"
+ "Lsun/security/krb5/internal/KerberosTime;"
+ "Lsun/security/krb5/internal/KerberosTime;"
+ "Lsun/security/krb5/internal/KerberosTime;"
+ "Lsun/security/krb5/internal/KerberosTime;"
+ "Lsun/security/krb5/internal/HostAddresses;)V");
if (krbcredsConstructor == 0) {
- printf("Couldn't find sun.security.krb5.Credentials constructor\n");
+ printf("LSA: Couldn't find sun.security.krb5.Credentials constructor\n");
break;
}
}
- #ifdef DEBUG
- printf("Found KrbCreds constructor\n");
- #endif
+ if (native_debug) {
+ printf("LSA: Found KrbCreds constructor\n");
+ }
//
// Get the logon handle and package ID from the
@@ -407,9 +430,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
if (!PackageConnectLookup(&LogonHandle, &PackageId))
break;
- #ifdef DEBUG
- printf("Got handle to Kerberos package\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Got handle to Kerberos package\n");
+ }
// Get the MS TGT from cache
CacheRequest.MessageType = KerbRetrieveTicketMessage;
@@ -426,9 +449,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
&SubStatus
);
- #ifdef DEBUG
- printf("Response size is %d\n", rspSize);
- #endif
+ if (native_debug) {
+ printf("LSA: Response size is %d\n", rspSize);
+ }
if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {
if (!LSA_SUCCESS(Status)) {
@@ -467,9 +490,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
}
if (ignore_cache) {
- #ifdef DEBUG
- printf("MS TGT in cache is invalid/not supported; request new ticket\n");
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: MS TGT in cache is invalid/not supported; request new ticket\n");
+ }
// use domain to request Ticket
Status = ConstructTicketRequest(msticket->TargetDomainName,
@@ -493,9 +516,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
&SubStatus
);
- #ifdef DEBUG
- printf("Response size is %d\n", responseSize);
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: Response size is %d\n", responseSize);
+ }
if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {
if (!LSA_SUCCESS(Status)) {
@@ -788,7 +811,9 @@ ShowLastError(
static WCHAR szMsgBuf[MAX_MSG_SIZE];
DWORD dwRes;
- printf("Error calling function %s: %lu\n", szAPI, dwError);
+ if (native_debug) {
+ printf("LSA: Error calling function %s: %lu\n", szAPI, dwError);
+ }
dwRes = FormatMessage (
FORMAT_MESSAGE_FROM_SYSTEM,
@@ -798,11 +823,13 @@ ShowLastError(
szMsgBuf,
MAX_MSG_SIZE,
NULL);
- if (0 == dwRes) {
- printf("FormatMessage failed with %d\n", GetLastError());
- // ExitProcess(EXIT_FAILURE);
- } else {
- printf("%S",szMsgBuf);
+ if (native_debug) {
+ if (0 == dwRes) {
+ printf("LSA: FormatMessage failed with %d\n", GetLastError());
+ // ExitProcess(EXIT_FAILURE);
+ } else {
+ printf("LSA: %S",szMsgBuf);
+ }
}
}
@@ -896,17 +923,19 @@ jobject BuildPrincipal(JNIEnv *env, PKERB_EXTERNAL_NAME principalName,
((domainName.Length)*sizeof(WCHAR) + sizeof(UNICODE_NULL)));
wcsncpy(realm, domainName.Buffer, domainName.Length/sizeof(WCHAR));
- #ifdef DEBUG
- printf("Principal domain is %S\n", realm);
- printf("Name type is %x\n", principalName->NameType);
- printf("Name count is %x\n", principalName->NameCount);
- #endif
+ if (native_debug) {
+ printf("LSA: Principal domain is %S\n", realm);
+ printf("LSA: Name type is %x\n", principalName->NameType);
+ printf("LSA: Name count is %x\n", principalName->NameCount);
+ }
nameCount = principalName->NameCount;
stringArray = (*env)->NewObjectArray(env, nameCount,
javaLangStringClass, NULL);
if (stringArray == NULL) {
- printf("Can't allocate String array for Principal\n");
+ if (native_debug) {
+ printf("LSA: Can't allocate String array for Principal\n");
+ }
LocalFree(realm);
return principal;
}
@@ -941,6 +970,17 @@ jobject BuildEncryptionKey(JNIEnv *env, PKERB_CRYPTO_KEY cryptoKey) {
// First, need to build a byte array
jbyteArray ary;
jobject encryptionKey = NULL;
+ unsigned int i;
+
+ for (i=0; iLength; i++) {
+ if (cryptoKey->Value[i]) break;
+ }
+ if (i == cryptoKey->Length) {
+ if (native_debug) {
+ printf("LSA: Session key all zero. Stop.\n");
+ }
+ return NULL;
+ }
ary = (*env)->NewByteArray(env,cryptoKey->Length);
(*env)->SetByteArrayRegion(env, ary, (jsize) 0, cryptoKey->Length,
@@ -1005,9 +1045,9 @@ jobject BuildKerberosTime(JNIEnv *env, PLARGE_INTEGER kerbtime) {
hour,
minute,
second );
- #ifdef DEBUG
- printf("%S\n", (wchar_t *)timeString);
- #endif /* DEBUG */
+ if (native_debug) {
+ printf("LSA: %S\n", (wchar_t *)timeString);
+ }
stringTime = (*env)->NewString(env, timeString,
(sizeof(timeString)/sizeof(WCHAR))-1);
if (stringTime != NULL) { // everything's OK so far
diff --git a/jdk/test/java/awt/FontClass/CreateFont/A.ttf b/jdk/test/java/awt/FontClass/CreateFont/A.ttf
new file mode 100644
index 00000000000..f80f5c3d569
Binary files /dev/null and b/jdk/test/java/awt/FontClass/CreateFont/A.ttf differ
diff --git a/jdk/test/java/awt/FontClass/CreateFont/BigFont.java b/jdk/test/java/awt/FontClass/CreateFont/BigFont.java
new file mode 100644
index 00000000000..c14802485bc
--- /dev/null
+++ b/jdk/test/java/awt/FontClass/CreateFont/BigFont.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.applet.*;
+import java.awt.*;
+import java.io.*;
+import java.net.*;
+
+public class BigFont extends Applet {
+
+ static private class SizedInputStream extends InputStream {
+
+ int size;
+ int cnt = 0;
+
+ SizedInputStream(int size) {
+ this.size = size;
+ }
+
+ public int read() {
+ if (cnt < size) {
+ cnt++;
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+
+ public int getCurrentSize() {
+ return cnt;
+ }
+ }
+
+ String id;
+ String fileName;
+
+ public void init() {
+ id = getParameter("number");
+ fileName = getParameter("font");
+
+ System.out.println("Applet " + id + " "+
+ Thread.currentThread().getThreadGroup());
+ // Larger than size for a single font.
+ int fontSize = 64 * 1000 * 1000;
+ SizedInputStream sis = new SizedInputStream(fontSize);
+ try {
+ Font font = Font.createFont(Font.TRUETYPE_FONT, sis);
+ } catch (Throwable t) {
+ if (t instanceof FontFormatException ||
+ fontSize <= sis.getCurrentSize())
+ {
+ System.out.println(sis.getCurrentSize());
+ System.out.println(t);
+ throw new RuntimeException("Allowed file to be too large.");
+ }
+ }
+ // The following part of the test was verified manually but
+ // is impractical to enable because it requires a fairly large
+ // valid font to be part of the test, and we can't easily include
+ // that, nor dependably reference one from the applet environment.
+ /*
+ if (fileName == null) {
+ return;
+ }
+ int size = getFileSize(fileName);
+ if (size == 0) {
+ return;
+ }
+ int fontCnt = 1000 * 1000 * 1000 / size;
+ loadMany(size, fontCnt, fileName);
+ System.gc(); System.gc();
+ fontCnt = fontCnt / 2;
+ System.out.println("Applet " + id + " load more.");
+ loadMany(size, fontCnt, fileName);
+ */
+ System.out.println("Applet " + id + " finished.");
+ }
+
+ int getFileSize(String fileName) {
+ try {
+ URL url = new URL(getCodeBase(), fileName);
+ InputStream inStream = url.openStream();
+ BufferedInputStream fontStream = new BufferedInputStream(inStream);
+ int size = 0;
+ while (fontStream.read() != -1) {
+ size++;
+ }
+ fontStream.close();
+ return size;
+ } catch (IOException e) {
+ return 0;
+ }
+
+ }
+ void loadMany(int oneFont, int fontCnt, String fileName) {
+ System.out.println("fontcnt= " + fontCnt);
+ Font[] fonts = new Font[fontCnt];
+ int totalSize = 0;
+ boolean gotException = false;
+ for (int i=0; i
+
+
+
+ Test Font Creation Limits
+
+
+
+
+
+
+
+
+
diff --git a/jdk/test/java/awt/FontClass/CreateFont/fileaccess/FontFile.java b/jdk/test/java/awt/FontClass/CreateFont/fileaccess/FontFile.java
new file mode 100644
index 00000000000..44419748903
--- /dev/null
+++ b/jdk/test/java/awt/FontClass/CreateFont/fileaccess/FontFile.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6652929
+ * @summary verify handling of File.getPath()
+ */
+
+import java.awt.*;
+import java.io.*;
+
+public class FontFile {
+ public static void main(String[] args) throws Exception {
+ String sep = System.getProperty("file.separator");
+ String fname = ".." + sep + "A.ttf";
+ String dir = System.getProperty("test.src");
+ if (dir != null) {
+ fname = dir + sep + fname;
+ }
+ final String name = fname;
+ System.out.println("Will try to access " + name);
+ if (!(new File(name)).canRead()) {
+ System.out.println("File not available : can't run test");
+ return;
+ }
+ System.out.println("File is available. Verify no access under SM");
+
+ System.setSecurityManager(new SecurityManager());
+
+
+ // Check cannot read file.
+ try {
+ new FileInputStream(name);
+ throw new Error("Something wrong with test environment");
+ } catch (SecurityException exc) {
+ // Good.
+ }
+
+ try {
+ Font font = Font.createFont(Font.TRUETYPE_FONT,
+ new File("nosuchfile") {
+ private boolean read;
+ @Override public String getPath() {
+ if (read) {
+ return name;
+ } else {
+ read = true;
+ return "somefile";
+ }
+ }
+ @Override public boolean canRead() {
+ return true;
+ }
+ }
+ );
+ System.err.println(font.getFontName());
+ throw new RuntimeException("No expected exception");
+ } catch (IOException e) {
+ System.err.println("Test passed.");
+ }
+ }
+}
diff --git a/jdk/test/java/awt/image/ConvolveOp/EdgeNoOpCrash.java b/jdk/test/java/awt/image/ConvolveOp/EdgeNoOpCrash.java
new file mode 100644
index 00000000000..5e1d2eb3f66
--- /dev/null
+++ b/jdk/test/java/awt/image/ConvolveOp/EdgeNoOpCrash.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6726779
+ * @summary Test verifies that ConvolveOp with the EDGE_NO_OP edge condition
+ * does not cause JVM crash if size of source raster elements is
+ * greather than size of the destination raster element.
+ *
+ * @run main EdgeNoOpCrash
+ */
+import java.awt.Point;
+import java.awt.image.ConvolveOp;
+import java.awt.image.DataBuffer;
+import java.awt.image.ImagingOpException;
+import java.awt.image.Kernel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.util.Arrays;
+
+public class EdgeNoOpCrash {
+ private static final int w = 3000;
+ private static final int h = 200;
+
+ public static void main(String[] args) {
+ crashTest();
+ }
+
+ private static void crashTest() {
+ Raster src = createSrcRaster();
+ WritableRaster dst = createDstRaster();
+ ConvolveOp op = createConvolveOp(ConvolveOp.EDGE_NO_OP);
+ try {
+ op.filter(src, dst);
+ } catch (ImagingOpException e) {
+ /*
+ * The test pair of source and destination rasters
+ * may cause failure of the medialib convolution routine,
+ * so this exception is expected.
+ *
+ * The JVM crash is the only manifestation of this
+ * test failure.
+ */
+ }
+ System.out.println("Test PASSED.");
+ }
+
+ private static Raster createSrcRaster() {
+ WritableRaster r = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT,
+ w, h, 4, new Point(0, 0));
+
+ return r;
+ }
+
+ private static WritableRaster createDstRaster() {
+ WritableRaster r = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+ w, h, 4, new Point(0, 0));
+
+ return r;
+ }
+
+ private static ConvolveOp createConvolveOp(int edgeHint) {
+ final int kw = 3;
+ final int kh = 3;
+ float[] kdata = new float[kw * kh];
+ float v = 1f / kdata.length;
+ Arrays.fill(kdata, v);
+
+ Kernel k = new Kernel(kw, kh, kdata);
+ ConvolveOp op = new ConvolveOp(k, edgeHint, null);
+
+ return op;
+ }
+}
\ No newline at end of file
diff --git a/jdk/test/java/nio/Buffer/Basic-X.java b/jdk/test/java/nio/Buffer/Basic-X.java
index d4e1a2762f1..6612771def4 100644
--- a/jdk/test/java/nio/Buffer/Basic-X.java
+++ b/jdk/test/java/nio/Buffer/Basic-X.java
@@ -365,8 +365,11 @@ public class Basic$Type$
b.position(2);
ck(b, b.charAt(1), 'd');
- CharBuffer c = (CharBuffer)b.subSequence(1, 4);
- ck(b, b.subSequence(1, 4).toString().equals("def"));
+ CharBuffer c = b.subSequence(1, 4);
+ ck(c, c.capacity(), b.capacity());
+ ck(c, c.position(), b.position()+1);
+ ck(c, c.limit(), b.position()+4);
+ ck(c, b.subSequence(1, 4).toString().equals("def"));
// 4938424
b.position(4);
@@ -722,6 +725,8 @@ public class Basic$Type$
ck(b, start, b.position());
ck(b, end, b.limit());
ck(b, s.length(), b.capacity());
+ b.position(6);
+ ck(b, b.subSequence(0,3).toString().equals("ghi"));
// The index, relative to the position, must be non-negative and
// smaller than remaining().
diff --git a/jdk/test/java/nio/Buffer/Basic.java b/jdk/test/java/nio/Buffer/Basic.java
index c0c420f8495..b8ed89bb30d 100644
--- a/jdk/test/java/nio/Buffer/Basic.java
+++ b/jdk/test/java/nio/Buffer/Basic.java
@@ -25,7 +25,7 @@
* @summary Unit test for buffers
* @bug 4413135 4414911 4416536 4416562 4418782 4471053 4472779 4490253 4523725
* 4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 6231529
- * 6221101 6234263 6535542 6591971 6593946
+ * 6221101 6234263 6535542 6591971 6593946 6795561
* @author Mark Reinhold
*/
diff --git a/jdk/test/java/nio/Buffer/BasicByte.java b/jdk/test/java/nio/Buffer/BasicByte.java
index 0f5ac6f6e0a..7e259a1416d 100644
--- a/jdk/test/java/nio/Buffer/BasicByte.java
+++ b/jdk/test/java/nio/Buffer/BasicByte.java
@@ -371,6 +371,9 @@ public class BasicByte
+
+
+
@@ -783,6 +786,8 @@ public class BasicByte
+
+
diff --git a/jdk/test/java/nio/Buffer/BasicChar.java b/jdk/test/java/nio/Buffer/BasicChar.java
index 28eb49fb560..a0df9fcf3a9 100644
--- a/jdk/test/java/nio/Buffer/BasicChar.java
+++ b/jdk/test/java/nio/Buffer/BasicChar.java
@@ -365,8 +365,11 @@ public class BasicChar
b.position(2);
ck(b, b.charAt(1), 'd');
- CharBuffer c = (CharBuffer)b.subSequence(1, 4);
- ck(b, b.subSequence(1, 4).toString().equals("def"));
+ CharBuffer c = b.subSequence(1, 4);
+ ck(c, c.capacity(), b.capacity());
+ ck(c, c.position(), b.position()+1);
+ ck(c, c.limit(), b.position()+4);
+ ck(c, b.subSequence(1, 4).toString().equals("def"));
// 4938424
b.position(4);
@@ -722,6 +725,8 @@ public class BasicChar
ck(b, start, b.position());
ck(b, end, b.limit());
ck(b, s.length(), b.capacity());
+ b.position(6);
+ ck(b, b.subSequence(0,3).toString().equals("ghi"));
// The index, relative to the position, must be non-negative and
// smaller than remaining().
diff --git a/jdk/test/java/nio/Buffer/BasicDouble.java b/jdk/test/java/nio/Buffer/BasicDouble.java
index b2a1be65ad7..a627d0e9194 100644
--- a/jdk/test/java/nio/Buffer/BasicDouble.java
+++ b/jdk/test/java/nio/Buffer/BasicDouble.java
@@ -371,6 +371,9 @@ public class BasicDouble
+
+
+
@@ -783,6 +786,8 @@ public class BasicDouble
+
+
diff --git a/jdk/test/java/nio/Buffer/BasicFloat.java b/jdk/test/java/nio/Buffer/BasicFloat.java
index b6b5ea0dbdf..730dcbeac95 100644
--- a/jdk/test/java/nio/Buffer/BasicFloat.java
+++ b/jdk/test/java/nio/Buffer/BasicFloat.java
@@ -371,6 +371,9 @@ public class BasicFloat
+
+
+
@@ -783,6 +786,8 @@ public class BasicFloat
+
+
diff --git a/jdk/test/java/nio/Buffer/BasicInt.java b/jdk/test/java/nio/Buffer/BasicInt.java
index 938ada29571..b20e4bb1056 100644
--- a/jdk/test/java/nio/Buffer/BasicInt.java
+++ b/jdk/test/java/nio/Buffer/BasicInt.java
@@ -371,6 +371,9 @@ public class BasicInt
+
+
+
@@ -783,6 +786,8 @@ public class BasicInt
+
+
diff --git a/jdk/test/java/nio/Buffer/BasicLong.java b/jdk/test/java/nio/Buffer/BasicLong.java
index 17537a71ffc..0d4c568e1e3 100644
--- a/jdk/test/java/nio/Buffer/BasicLong.java
+++ b/jdk/test/java/nio/Buffer/BasicLong.java
@@ -371,6 +371,9 @@ public class BasicLong
+
+
+
@@ -783,6 +786,8 @@ public class BasicLong
+
+
diff --git a/jdk/test/java/nio/Buffer/BasicShort.java b/jdk/test/java/nio/Buffer/BasicShort.java
index dc9c7db3803..58e5a3e6d68 100644
--- a/jdk/test/java/nio/Buffer/BasicShort.java
+++ b/jdk/test/java/nio/Buffer/BasicShort.java
@@ -371,6 +371,9 @@ public class BasicShort
+
+
+
@@ -783,6 +786,8 @@ public class BasicShort
+
+
diff --git a/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java
index 5ffb42c0b8b..ea9a5415923 100644
--- a/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4607272
+ * @bug 4607272 6822643
* @summary Unit test for AsynchronousFileChannel
*/
@@ -51,7 +51,6 @@ public class Basic {
// run tests
testUsingCompletionHandlers(ch);
testUsingWaitOnResult(ch);
- testLocking(ch);
testInterruptHandlerThread(ch);
// close channel and invoke test that expects channel to be closed
@@ -59,6 +58,7 @@ public class Basic {
testClosedChannel(ch);
// these tests open the file themselves
+ testLocking(blah.toPath());
testCustomThreadPool(blah.toPath());
testAsynchronousClose(blah.toPath());
testCancel(blah.toPath());
@@ -160,47 +160,54 @@ public class Basic {
}
// exercise lock methods
- static void testLocking(AsynchronousFileChannel ch)
- throws IOException
- {
+ static void testLocking(Path file) throws IOException {
System.out.println("testLocking");
- // test 1 - acquire lock and check that tryLock throws
- // OverlappingFileLockException
+ AsynchronousFileChannel ch = AsynchronousFileChannel
+ .open(file, READ, WRITE);
FileLock fl;
try {
- fl = ch.lock().get();
- } catch (ExecutionException x) {
- throw new RuntimeException(x);
- } catch (InterruptedException x) {
- throw new RuntimeException("Should not be interrupted");
- }
- if (!fl.acquiredBy().equals(ch))
- throw new RuntimeException("FileLock#acquiredBy returned incorrect channel");
- try {
- ch.tryLock();
- throw new RuntimeException("OverlappingFileLockException expected");
- } catch (OverlappingFileLockException x) {
- }
- fl.release();
+ // test 1 - acquire lock and check that tryLock throws
+ // OverlappingFileLockException
+ try {
+ fl = ch.lock().get();
+ } catch (ExecutionException x) {
+ throw new RuntimeException(x);
+ } catch (InterruptedException x) {
+ throw new RuntimeException("Should not be interrupted");
+ }
+ if (!fl.acquiredBy().equals(ch))
+ throw new RuntimeException("FileLock#acquiredBy returned incorrect channel");
+ try {
+ ch.tryLock();
+ throw new RuntimeException("OverlappingFileLockException expected");
+ } catch (OverlappingFileLockException x) {
+ }
+ fl.release();
- // test 2 - acquire try and check that lock throws OverlappingFileLockException
- fl = ch.tryLock();
- if (fl == null)
- throw new RuntimeException("Unable to acquire lock");
- try {
- ch.lock(null, new CompletionHandler () {
- public void completed(FileLock result, Void att) {
- }
- public void failed(Throwable exc, Void att) {
- }
- public void cancelled(Void att) {
- }
- });
- throw new RuntimeException("OverlappingFileLockException expected");
- } catch (OverlappingFileLockException x) {
+ // test 2 - acquire try and check that lock throws OverlappingFileLockException
+ fl = ch.tryLock();
+ if (fl == null)
+ throw new RuntimeException("Unable to acquire lock");
+ try {
+ ch.lock(null, new CompletionHandler () {
+ public void completed(FileLock result, Void att) {
+ }
+ public void failed(Throwable exc, Void att) {
+ }
+ public void cancelled(Void att) {
+ }
+ });
+ throw new RuntimeException("OverlappingFileLockException expected");
+ } catch (OverlappingFileLockException x) {
+ }
+ } finally {
+ ch.close();
}
- fl.release();
+
+ // test 3 - channel is closed so FileLock should no longer be valid
+ if (fl.isValid())
+ throw new RuntimeException("FileLock expected to be invalid");
}
// interrupt should not close channel
diff --git a/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java b/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java
index 38c0f7d0c6e..f8b55cc44f8 100644
--- a/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java
@@ -23,7 +23,7 @@
/* @test
- * @bug 4607272
+ * @bug 4607272 6814948
* @summary Unit test for AsynchronousFileChannel#lock method
*/
diff --git a/jdk/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java b/jdk/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java
new file mode 100644
index 00000000000..c7ed16a9204
--- /dev/null
+++ b/jdk/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 6543863
+ * @summary Try to cause a deadlock between (Asynchronous)FileChannel.close
+ * and FileLock.release
+ */
+
+import java.io.*;
+import java.nio.file.Path;
+import static java.nio.file.StandardOpenOption.*;
+import java.nio.channels.*;
+import java.util.concurrent.*;
+
+public class ReleaseOnCloseDeadlock {
+ private static final int LOCK_COUNT = 1024;
+
+ public static void main(String[] args) throws IOException {
+ File blah = File.createTempFile("blah", null);
+ blah.deleteOnExit();
+ for (int i=0; i<100; i++) {
+ test(blah.toPath());
+ }
+ }
+
+ static void test(Path file) throws IOException {
+ FileLock[] locks = new FileLock[LOCK_COUNT];
+
+ FileChannel fc = FileChannel.open(file, READ, WRITE);
+ for (int i=0; i zes = zf.entries();
+ ZipEntry e = (ZipEntry)zes.nextElement();
+ if (! name.equals(e.getName()) ||
+ ! comment.equals(e.getComment()))
+ throw new RuntimeException("ZipFile: name/comment doesn't match!");
+ InputStream is = zf.getInputStream(e);
+ if (is == null)
+ throw new RuntimeException("ZipFile: getIS failed!");
+ byte[] bBuf = new byte[bb.length << 1];
+ int n = 0;
+ int nn =0;
+ while ((nn = is.read(bBuf, n, bBuf.length-n)) != -1) {
+ n += nn;
+ }
+ if (n != bb.length ||
+ !Arrays.equals(bb, Arrays.copyOf(bBuf, n))) {
+ throw new RuntimeException("ZipFile content doesn't match!");
+ }
+ zf.close();
+ }
+
+ static void test(String csn, String name, String comment)
+ throws Exception
+ {
+ byte[] bb = "This is the conent of the zipfile".getBytes("ISO-8859-1");
+ Charset cs = Charset.forName(csn);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ZipOutputStream zos = new ZipOutputStream(baos, cs);
+
+ ZipEntry e = new ZipEntry(name);
+ e.setComment(comment);
+ zos.putNextEntry(e);
+ zos.write(bb, 0, bb.length);
+ zos.closeEntry();
+ zos.close();
+ ByteArrayInputStream bis = new ByteArrayInputStream(baos.toByteArray());
+ testZipInputStream(bis, cs, name, comment, bb);
+
+ if ("utf-8".equals(csn)) {
+ // EFS should be set
+ bis.reset();
+ testZipInputStream(bis, Charset.forName("MS932"), name, comment, bb);
+ }
+
+ File f = new File(new File(System.getProperty("test.dir", ".")),
+ "zfcoding.zip");
+ FileOutputStream fos = new FileOutputStream(f);
+ baos.writeTo(fos);
+ fos.close();
+ testZipFile(f, cs, name, comment, bb);
+ if ("utf-8".equals(csn)) {
+ testZipFile(f, Charset.forName("MS932"), name, comment, bb);
+ }
+ f.delete();
+ }
+}
diff --git a/jdk/test/java/util/zip/zip.java b/jdk/test/java/util/zip/zip.java
new file mode 100644
index 00000000000..33eccf9496d
--- /dev/null
+++ b/jdk/test/java/util/zip/zip.java
@@ -0,0 +1,743 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.util.*;
+import java.util.zip.*;
+import java.text.MessageFormat;
+
+/**
+ * A stripped-down version of Jar tool with a "-encoding" option to
+ * support non-UTF8 encoidng for entry name and comment.
+ */
+public class zip {
+ String program;
+ PrintStream out, err;
+ String fname;
+ String zname = "";
+ String[] files;
+ Charset cs = Charset.forName("UTF-8");
+
+ Map entryMap = new HashMap();
+ Set entries = new LinkedHashSet();
+ List paths = new ArrayList();
+
+ CRC32 crc32 = new CRC32();
+ /*
+ * cflag: create
+ * uflag: update
+ * xflag: xtract
+ * tflag: table
+ * vflag: verbose
+ * flag0: no zip compression (store only)
+ */
+ boolean cflag, uflag, xflag, tflag, vflag, flag0;
+
+ private static ResourceBundle rsrc;
+ static {
+ try {
+ // just use the jar message
+ rsrc = ResourceBundle.getBundle("sun.tools.jar.resources.jar");
+ } catch (MissingResourceException e) {
+ throw new Error("Fatal: Resource for jar is missing");
+ }
+ }
+
+ public zip(PrintStream out, PrintStream err, String program) {
+ this.out = out;
+ this.err = err;
+ this.program = program;
+ }
+
+ private boolean ok;
+
+ public synchronized boolean run(String args[]) {
+ ok = true;
+ if (!parseArgs(args)) {
+ return false;
+ }
+ try {
+ if (cflag || uflag) {
+ if (fname != null) {
+ zname = fname.replace(File.separatorChar, '/');
+ if (zname.startsWith("./")) {
+ zname = zname.substring(2);
+ }
+ }
+ }
+ if (cflag) {
+ OutputStream out;
+ if (fname != null) {
+ out = new FileOutputStream(fname);
+ } else {
+ out = new FileOutputStream(FileDescriptor.out);
+ if (vflag) {
+ vflag = false;
+ }
+ }
+ expand(null, files, false);
+ create(new BufferedOutputStream(out, 4096));
+ out.close();
+ } else if (uflag) {
+ File inputFile = null, tmpFile = null;
+ FileInputStream in;
+ FileOutputStream out;
+ if (fname != null) {
+ inputFile = new File(fname);
+ String path = inputFile.getParent();
+ tmpFile = File.createTempFile("tmp", null,
+ new File((path == null) ? "." : path));
+ in = new FileInputStream(inputFile);
+ out = new FileOutputStream(tmpFile);
+ } else {
+ in = new FileInputStream(FileDescriptor.in);
+ out = new FileOutputStream(FileDescriptor.out);
+ vflag = false;
+ }
+ expand(null, files, true);
+ boolean updateOk = update(in, new BufferedOutputStream(out));
+ if (ok) {
+ ok = updateOk;
+ }
+ in.close();
+ out.close();
+ if (fname != null) {
+ inputFile.delete();
+ if (!tmpFile.renameTo(inputFile)) {
+ tmpFile.delete();
+ throw new IOException(getMsg("error.write.file"));
+ }
+ tmpFile.delete();
+ }
+ } else if (tflag) {
+ replaceFSC(files);
+ if (fname != null) {
+ list(fname, files);
+ } else {
+ InputStream in = new FileInputStream(FileDescriptor.in);
+ try{
+ list(new BufferedInputStream(in), files);
+ } finally {
+ in.close();
+ }
+ }
+ } else if (xflag) {
+ replaceFSC(files);
+ if (fname != null && files != null) {
+ extract(fname, files);
+ } else {
+ InputStream in = (fname == null)
+ ? new FileInputStream(FileDescriptor.in)
+ : new FileInputStream(fname);
+ try {
+ extract(new BufferedInputStream(in), files);
+ } finally {
+ in.close();
+ }
+ }
+ }
+ } catch (IOException e) {
+ fatalError(e);
+ ok = false;
+ } catch (Error ee) {
+ ee.printStackTrace();
+ ok = false;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ ok = false;
+ }
+ out.flush();
+ err.flush();
+ return ok;
+ }
+
+
+ boolean parseArgs(String args[]) {
+ try {
+ args = parse(args);
+ } catch (FileNotFoundException e) {
+ fatalError(formatMsg("error.cant.open", e.getMessage()));
+ return false;
+ } catch (IOException e) {
+ fatalError(e);
+ return false;
+ }
+ int count = 1;
+ try {
+ String flags = args[0];
+ if (flags.startsWith("-")) {
+ flags = flags.substring(1);
+ }
+ for (int i = 0; i < flags.length(); i++) {
+ switch (flags.charAt(i)) {
+ case 'c':
+ if (xflag || tflag || uflag) {
+ usageError();
+ return false;
+ }
+ cflag = true;
+ break;
+ case 'u':
+ if (cflag || xflag || tflag) {
+ usageError();
+ return false;
+ }
+ uflag = true;
+ break;
+ case 'x':
+ if (cflag || uflag || tflag) {
+ usageError();
+ return false;
+ }
+ xflag = true;
+ break;
+ case 't':
+ if (cflag || uflag || xflag) {
+ usageError();
+ return false;
+ }
+ tflag = true;
+ break;
+ case 'v':
+ vflag = true;
+ break;
+ case 'f':
+ fname = args[count++];
+ break;
+ case '0':
+ flag0 = true;
+ break;
+ default:
+ error(formatMsg("error.illegal.option",
+ String.valueOf(flags.charAt(i))));
+ usageError();
+ return false;
+ }
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ usageError();
+ return false;
+ }
+ if (!cflag && !tflag && !xflag && !uflag) {
+ error(getMsg("error.bad.option"));
+ usageError();
+ return false;
+ }
+ /* parse file arguments */
+ int n = args.length - count;
+ if (n > 0) {
+ int k = 0;
+ String[] nameBuf = new String[n];
+ try {
+ for (int i = count; i < args.length; i++) {
+ if (args[i].equals("-encoding")) {
+ cs = Charset.forName(args[++i]);
+ } else if (args[i].equals("-C")) {
+ /* change the directory */
+ String dir = args[++i];
+ dir = (dir.endsWith(File.separator) ?
+ dir : (dir + File.separator));
+ dir = dir.replace(File.separatorChar, '/');
+ while (dir.indexOf("//") > -1) {
+ dir = dir.replace("//", "/");
+ }
+ paths.add(dir.replace(File.separatorChar, '/'));
+ nameBuf[k++] = dir + args[++i];
+ } else {
+ nameBuf[k++] = args[i];
+ }
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ e.printStackTrace();
+ usageError();
+ return false;
+ }
+ if (k != 0) {
+ files = new String[k];
+ System.arraycopy(nameBuf, 0, files, 0, k);
+ }
+ } else if (cflag || uflag) {
+ error(getMsg("error.bad.uflag"));
+ usageError();
+ return false;
+ }
+ return true;
+ }
+
+ void expand(File dir, String[] files, boolean isUpdate) {
+ if (files == null) {
+ return;
+ }
+ for (int i = 0; i < files.length; i++) {
+ File f;
+ if (dir == null) {
+ f = new File(files[i]);
+ } else {
+ f = new File(dir, files[i]);
+ }
+ if (f.isFile()) {
+ if (entries.add(f)) {
+ if (isUpdate)
+ entryMap.put(entryName(f.getPath()), f);
+ }
+ } else if (f.isDirectory()) {
+ if (entries.add(f)) {
+ if (isUpdate) {
+ String dirPath = f.getPath();
+ dirPath = (dirPath.endsWith(File.separator)) ? dirPath :
+ (dirPath + File.separator);
+ entryMap.put(entryName(dirPath), f);
+ }
+ expand(f, f.list(), isUpdate);
+ }
+ } else {
+ error(formatMsg("error.nosuch.fileordir", String.valueOf(f)));
+ ok = false;
+ }
+ }
+ }
+
+ void create(OutputStream out) throws IOException
+ {
+ ZipOutputStream zos = new ZipOutputStream(out, cs);
+ if (flag0) {
+ zos.setMethod(ZipOutputStream.STORED);
+ }
+ for (File file: entries) {
+ addFile(zos, file);
+ }
+ zos.close();
+ }
+
+ boolean update(InputStream in, OutputStream out) throws IOException
+ {
+ ZipInputStream zis = new ZipInputStream(in, cs);
+ ZipOutputStream zos = new ZipOutputStream(out, cs);
+ ZipEntry e = null;
+ byte[] buf = new byte[1024];
+ int n = 0;
+ boolean updateOk = true;
+
+ // put the old entries first, replace if necessary
+ while ((e = zis.getNextEntry()) != null) {
+ String name = e.getName();
+ if (!entryMap.containsKey(name)) { // copy the old stuff
+ // do our own compression
+ ZipEntry e2 = new ZipEntry(name);
+ e2.setMethod(e.getMethod());
+ e2.setTime(e.getTime());
+ e2.setComment(e.getComment());
+ e2.setExtra(e.getExtra());
+ if (e.getMethod() == ZipEntry.STORED) {
+ e2.setSize(e.getSize());
+ e2.setCrc(e.getCrc());
+ }
+ zos.putNextEntry(e2);
+ while ((n = zis.read(buf, 0, buf.length)) != -1) {
+ zos.write(buf, 0, n);
+ }
+ } else { // replace with the new files
+ File f = entryMap.get(name);
+ addFile(zos, f);
+ entryMap.remove(name);
+ entries.remove(f);
+ }
+ }
+
+ // add the remaining new files
+ for (File f: entries) {
+ addFile(zos, f);
+ }
+ zis.close();
+ zos.close();
+ return updateOk;
+ }
+
+ private String entryName(String name) {
+ name = name.replace(File.separatorChar, '/');
+ String matchPath = "";
+ for (String path : paths) {
+ if (name.startsWith(path) && (path.length() > matchPath.length())) {
+ matchPath = path;
+ }
+ }
+ name = name.substring(matchPath.length());
+
+ if (name.startsWith("/")) {
+ name = name.substring(1);
+ } else if (name.startsWith("./")) {
+ name = name.substring(2);
+ }
+ return name;
+ }
+
+ void addFile(ZipOutputStream zos, File file) throws IOException {
+ String name = file.getPath();
+ boolean isDir = file.isDirectory();
+ if (isDir) {
+ name = name.endsWith(File.separator) ? name :
+ (name + File.separator);
+ }
+ name = entryName(name);
+
+ if (name.equals("") || name.equals(".") || name.equals(zname)) {
+ return;
+ }
+
+ long size = isDir ? 0 : file.length();
+
+ if (vflag) {
+ out.print(formatMsg("out.adding", name));
+ }
+ ZipEntry e = new ZipEntry(name);
+ e.setTime(file.lastModified());
+ if (size == 0) {
+ e.setMethod(ZipEntry.STORED);
+ e.setSize(0);
+ e.setCrc(0);
+ } else if (flag0) {
+ e.setSize(size);
+ e.setMethod(ZipEntry.STORED);
+ crc32File(e, file);
+ }
+ zos.putNextEntry(e);
+ if (!isDir) {
+ byte[] buf = new byte[8192];
+ int len;
+ InputStream is = new BufferedInputStream(new FileInputStream(file));
+ while ((len = is.read(buf, 0, buf.length)) != -1) {
+ zos.write(buf, 0, len);
+ }
+ is.close();
+ }
+ zos.closeEntry();
+ /* report how much compression occurred. */
+ if (vflag) {
+ size = e.getSize();
+ long csize = e.getCompressedSize();
+ out.print(formatMsg2("out.size", String.valueOf(size),
+ String.valueOf(csize)));
+ if (e.getMethod() == ZipEntry.DEFLATED) {
+ long ratio = 0;
+ if (size != 0) {
+ ratio = ((size - csize) * 100) / size;
+ }
+ output(formatMsg("out.deflated", String.valueOf(ratio)));
+ } else {
+ output(getMsg("out.stored"));
+ }
+ }
+ }
+
+ private void crc32File(ZipEntry e, File f) throws IOException {
+ InputStream is = new BufferedInputStream(new FileInputStream(f));
+ byte[] buf = new byte[8192];
+ crc32.reset();
+ int r = 0;
+ int nread = 0;
+ long len = f.length();
+ while ((r = is.read(buf)) != -1) {
+ nread += r;
+ crc32.update(buf, 0, r);
+ }
+ is.close();
+ if (nread != (int) len) {
+ throw new ZipException(formatMsg(
+ "error.incorrect.length", f.getPath()));
+ }
+ e.setCrc(crc32.getValue());
+ }
+
+ void replaceFSC(String files[]) {
+ if (files != null) {
+ for (String file : files) {
+ file = file.replace(File.separatorChar, '/');
+ }
+ }
+ }
+
+ Set newDirSet() {
+ return new HashSet() {
+ public boolean add(ZipEntry e) {
+ return (e == null || super.add(e));
+ }};
+ }
+
+ void updateLastModifiedTime(Set zes) throws IOException {
+ for (ZipEntry ze : zes) {
+ long lastModified = ze.getTime();
+ if (lastModified != -1) {
+ File f = new File(ze.getName().replace('/', File.separatorChar));
+ f.setLastModified(lastModified);
+ }
+ }
+ }
+
+ void extract(InputStream in, String files[]) throws IOException {
+ ZipInputStream zis = new ZipInputStream(in, cs);
+ ZipEntry e;
+ Set dirs = newDirSet();
+ while ((e = zis.getNextEntry()) != null) {
+ if (files == null) {
+ dirs.add(extractFile(zis, e));
+ } else {
+ String name = e.getName();
+ for (String file : files) {
+ if (name.startsWith(file)) {
+ dirs.add(extractFile(zis, e));
+ break;
+ }
+ }
+ }
+ }
+ updateLastModifiedTime(dirs);
+ }
+
+ void extract(String fname, String files[]) throws IOException {
+ ZipFile zf = new ZipFile(fname, cs);
+ Set dirs = newDirSet();
+ Enumeration extends ZipEntry> zes = zf.entries();
+ while (zes.hasMoreElements()) {
+ ZipEntry e = zes.nextElement();
+ InputStream is;
+ if (files == null) {
+ dirs.add(extractFile(zf.getInputStream(e), e));
+ } else {
+ String name = e.getName();
+ for (String file : files) {
+ if (name.startsWith(file)) {
+ dirs.add(extractFile(zf.getInputStream(e), e));
+ break;
+ }
+ }
+ }
+ }
+ zf.close();
+ updateLastModifiedTime(dirs);
+ }
+
+ ZipEntry extractFile(InputStream is, ZipEntry e) throws IOException {
+ ZipEntry rc = null;
+ String name = e.getName();
+ File f = new File(e.getName().replace('/', File.separatorChar));
+ if (e.isDirectory()) {
+ if (f.exists()) {
+ if (!f.isDirectory()) {
+ throw new IOException(formatMsg("error.create.dir",
+ f.getPath()));
+ }
+ } else {
+ if (!f.mkdirs()) {
+ throw new IOException(formatMsg("error.create.dir",
+ f.getPath()));
+ } else {
+ rc = e;
+ }
+ }
+ if (vflag) {
+ output(formatMsg("out.create", name));
+ }
+ } else {
+ if (f.getParent() != null) {
+ File d = new File(f.getParent());
+ if (!d.exists() && !d.mkdirs() || !d.isDirectory()) {
+ throw new IOException(formatMsg(
+ "error.create.dir", d.getPath()));
+ }
+ }
+ OutputStream os = new FileOutputStream(f);
+ byte[] b = new byte[8192];
+ int len;
+ try {
+ while ((len = is.read(b, 0, b.length)) != -1) {
+ os.write(b, 0, len);
+ }
+ } finally {
+ if (is instanceof ZipInputStream)
+ ((ZipInputStream)is).closeEntry();
+ else
+ is.close();
+ os.close();
+ }
+ if (vflag) {
+ if (e.getMethod() == ZipEntry.DEFLATED) {
+ output(formatMsg("out.inflated", name));
+ } else {
+ output(formatMsg("out.extracted", name));
+ }
+ }
+ }
+ long lastModified = e.getTime();
+ if (lastModified != -1) {
+ f.setLastModified(lastModified);
+ }
+ return rc;
+ }
+
+ void list(InputStream in, String files[]) throws IOException {
+ ZipInputStream zis = new ZipInputStream(in, cs);
+ ZipEntry e;
+ while ((e = zis.getNextEntry()) != null) {
+ zis.closeEntry();
+ printEntry(e, files);
+ }
+ }
+
+ void list(String fname, String files[]) throws IOException {
+ ZipFile zf = new ZipFile(fname, cs);
+ Enumeration extends ZipEntry> zes = zf.entries();
+ while (zes.hasMoreElements()) {
+ printEntry(zes.nextElement(), files);
+ }
+ zf.close();
+ }
+
+ void printEntry(ZipEntry e, String[] files) throws IOException {
+ if (files == null) {
+ printEntry(e);
+ } else {
+ String name = e.getName();
+ for (String file : files) {
+ if (name.startsWith(file)) {
+ printEntry(e);
+ return;
+ }
+ }
+ }
+ }
+
+ void printEntry(ZipEntry e) throws IOException {
+ if (vflag) {
+ StringBuilder sb = new StringBuilder();
+ String s = Long.toString(e.getSize());
+ for (int i = 6 - s.length(); i > 0; --i) {
+ sb.append(' ');
+ }
+ sb.append(s).append(' ').append(new Date(e.getTime()).toString());
+ sb.append(' ').append(e.getName());
+ output(sb.toString());
+ } else {
+ output(e.getName());
+ }
+ }
+
+ void usageError() {
+ error(
+ "Usage: zip {ctxu}[vf0] [zip-file] [-encoding encname][-C dir] files ...\n" +
+ "Options:\n" +
+ " -c create new archive\n" +
+ " -t list table of contents for archive\n" +
+ " -x extract named (or all) files from archive\n" +
+ " -u update existing archive\n" +
+ " -v generate verbose output on standard output\n" +
+ " -f specify archive file name\n" +
+ " -0 store only; use no ZIP compression\n" +
+ " -C change to the specified directory and include the following file\n" +
+ "If any file is a directory then it is processed recursively.\n");
+ }
+
+ void fatalError(Exception e) {
+ e.printStackTrace();
+ }
+
+
+ void fatalError(String s) {
+ error(program + ": " + s);
+ }
+
+
+ protected void output(String s) {
+ out.println(s);
+ }
+
+ protected void error(String s) {
+ err.println(s);
+ }
+
+ private String getMsg(String key) {
+ try {
+ return (rsrc.getString(key));
+ } catch (MissingResourceException e) {
+ throw new Error("Error in message file");
+ }
+ }
+
+ private String formatMsg(String key, String arg) {
+ String msg = getMsg(key);
+ String[] args = new String[1];
+ args[0] = arg;
+ return MessageFormat.format(msg, (Object[]) args);
+ }
+
+ private String formatMsg2(String key, String arg, String arg1) {
+ String msg = getMsg(key);
+ String[] args = new String[2];
+ args[0] = arg;
+ args[1] = arg1;
+ return MessageFormat.format(msg, (Object[]) args);
+ }
+
+ public static String[] parse(String[] args) throws IOException
+ {
+ ArrayList newArgs = new ArrayList(args.length);
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i];
+ if (arg.length() > 1 && arg.charAt(0) == '@') {
+ arg = arg.substring(1);
+ if (arg.charAt(0) == '@') {
+ newArgs.add(arg);
+ } else {
+ loadCmdFile(arg, newArgs);
+ }
+ } else {
+ newArgs.add(arg);
+ }
+ }
+ return newArgs.toArray(new String[newArgs.size()]);
+ }
+
+ private static void loadCmdFile(String name, List args) throws IOException
+ {
+ Reader r = new BufferedReader(new FileReader(name));
+ StreamTokenizer st = new StreamTokenizer(r);
+ st.resetSyntax();
+ st.wordChars(' ', 255);
+ st.whitespaceChars(0, ' ');
+ st.commentChar('#');
+ st.quoteChar('"');
+ st.quoteChar('\'');
+ while (st.nextToken() != st.TT_EOF) {
+ args.add(st.sval);
+ }
+ r.close();
+ }
+
+ public static void main(String args[]) {
+ zip z = new zip(System.out, System.err, "zip");
+ System.exit(z.run(args) ? 0 : 1);
+ }
+}
+
diff --git a/jdk/test/javax/print/attribute/MediaMappingsTest.java b/jdk/test/javax/print/attribute/MediaMappingsTest.java
new file mode 100644
index 00000000000..16110d8a49e
--- /dev/null
+++ b/jdk/test/javax/print/attribute/MediaMappingsTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6652463
+ * @summary Verify media size-> media mappings can't be altered
+ * @run main MediaMappingsTest
+*/
+
+import javax.print.attribute.standard.MediaSize;
+import javax.print.attribute.standard.MediaSizeName;
+
+public class MediaMappingsTest {
+
+ public static void main(String args[]) {
+ MediaSize sizeA = MediaSize.getMediaSizeForName(MediaSizeName.A);
+ new MediaSize(1.0f, 2.0f, MediaSize.MM, MediaSizeName.A);
+ if (!sizeA.equals(MediaSize.getMediaSizeForName(MediaSizeName.A))) {
+ throw new RuntimeException("mapping changed");
+ }
+ MediaSize sizeB = MediaSize.getMediaSizeForName(MediaSizeName.B);
+ new MediaSize(1, 2, MediaSize.MM, MediaSizeName.B);
+ if (!sizeB.equals(MediaSize.getMediaSizeForName(MediaSizeName.B))) {
+ throw new RuntimeException("mapping changed");
+ }
+ }
+}
diff --git a/jdk/test/sun/security/krb5/ConfigWithQuotations.java b/jdk/test/sun/security/krb5/ConfigWithQuotations.java
new file mode 100644
index 00000000000..c55e3cbb8dd
--- /dev/null
+++ b/jdk/test/sun/security/krb5/ConfigWithQuotations.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @test
+ * @bug 6714845
+ * @summary Quotes in Kerberos configuration file are included in the values
+ */
+
+import sun.security.krb5.Config;
+
+public class ConfigWithQuotations {
+ public static void main(String[] args) throws Exception {
+ // This config file is generated using Kerberos.app on a Mac
+ System.setProperty("java.security.krb5.conf",
+ System.getProperty("test.src", ".") +"/edu.mit.Kerberos");
+ Config config = Config.getInstance();
+
+ System.out.println(config);
+
+ if (!config.getDefaultRealm().equals("MAC.LOCAL")) {
+ throw new Exception("Realm error");
+ }
+ if (!config.getKDCList("MAC.LOCAL").equals("kdc.mac.local:88")) {
+ throw new Exception("KDC error");
+ }
+ }
+}
diff --git a/jdk/test/sun/security/krb5/edu.mit.Kerberos b/jdk/test/sun/security/krb5/edu.mit.Kerberos
new file mode 100644
index 00000000000..94d76a6e58c
--- /dev/null
+++ b/jdk/test/sun/security/krb5/edu.mit.Kerberos
@@ -0,0 +1,15 @@
+[domain_realm]
+
+[libdefaults]
+ default_realm = "MAC.LOCAL"
+ dns_fallback = "no"
+
+[logging]
+ admin_server = "FILE:/var/log/krb5kdc/kadmin.log"
+ kdc = "FILE:/var/log/krb5kdc/kdc.log"
+
+[realms]
+ MAC.LOCAL = {
+ kdc = "kdc.mac.local:88"
+ }
+
diff --git a/jdk/test/sun/security/util/Oid/OidFormat.java b/jdk/test/sun/security/util/Oid/OidFormat.java
index 9de4a757ea7..10b7fdd9ee5 100644
--- a/jdk/test/sun/security/util/Oid/OidFormat.java
+++ b/jdk/test/sun/security/util/Oid/OidFormat.java
@@ -63,9 +63,22 @@ public class OidFormat {
"1.2.3", "1.2.3445",
"1.3.6.1.4.1.42.2.17",
// 4811968: ASN.1 cannot handle huge OID components
- //"2.16.764.1.3101555394.1.0.100.2.1",
- //"1.2.2147483647.4",
- //"1.2.268435456.4",
+ "2.16.764.1.3101555394.1.0.100.2.1",
+ "2.2726957624935694386592435", // as huge as possible
+ "1.2.777777777777777777",
+ "1.2.888888888888888888.111111111111111.2222222222222.33333333333333333.44444444444444",
+ "1.2." +
+ "1111111111111111111111111111111111111111111111111111111111111." +
+ "2222222222222222222222222222222222222222222222222222222222222222." +
+ "333333333333333333333333333333333333333333333333333333333333333." +
+ "4444444444444444444444444444444444444444444444444444444." +
+ "55555555555555555555555555555555555555555555555555555555555555555555555." +
+ "666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666." +
+ "77777777777777777777777777777777777777777777777777777777777777777777777777." +
+ "8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888." +
+ "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999",
+ "1.2.2147483647.4",
+ "1.2.268435456.4",
};
for (String s: goodOids) {
diff --git a/jdk/test/sun/security/util/Oid/S11N.sh b/jdk/test/sun/security/util/Oid/S11N.sh
new file mode 100644
index 00000000000..77341e8a91b
--- /dev/null
+++ b/jdk/test/sun/security/util/Oid/S11N.sh
@@ -0,0 +1,164 @@
+#
+# Copyright 2004-2005 Sun Microsystems, Inc. All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+# @test
+# @bug 4811968
+# @summary Serialization compatibility with old versions
+# @author Weijun Wang
+#
+# set a few environment variables so that the shell-script can run stand-alone
+# in the source directory
+
+if [ "${TESTSRC}" = "" ] ; then
+ TESTSRC="."
+fi
+if [ "${TESTCLASSES}" = "" ] ; then
+ TESTCLASSES="."
+fi
+if [ "${TESTJAVA}" = "" ] ; then
+ echo "TESTJAVA not set. Test cannot execute."
+ echo "FAILED!!!"
+ exit 1
+fi
+
+# set platform-dependent variables
+PF=""
+
+OS=`uname -s`
+case "$OS" in
+ SunOS )
+ FS="/"
+ ARCH=`isainfo`
+ case "$ARCH" in
+ sparc* )
+ PF="solaris-sparc"
+ ;;
+ i[3-6]86 )
+ PF="solaris-i586"
+ ;;
+ amd64* )
+ PF="solaris-amd64"
+ ;;
+ * )
+ echo "Unsupported System: Solaris ${ARCH}"
+ exit 0;
+ ;;
+ esac
+ ;;
+ Linux )
+ ARCH=`uname -m`
+ FS="/"
+ case "$ARCH" in
+ i[3-6]86 )
+ PF="linux-i586"
+ ;;
+ amd64* )
+ PF="linux-amd64"
+ ;;
+ * )
+ echo "Unsupported System: Linux ${ARCH}"
+ exit 0;
+ ;;
+ esac
+ ;;
+ Windows* )
+ FS="\\"
+ PF="windows-i586"
+
+ # 'uname -m' does not give us enough information -
+ # should rely on $PROCESSOR_IDENTIFIER (as is done in Defs-windows.gmk),
+ # but JTREG does not pass this env variable when executing a shell script.
+ #
+ # execute test program - rely on it to exit if platform unsupported
+
+ ;;
+ * )
+ echo "Unsupported System: ${OS}"
+ exit 0;
+ ;;
+esac
+
+# the test code
+
+${TESTJAVA}${FS}bin${FS}javac -source 1.3 -target 1.3 -d . ${TESTSRC}${FS}SerialTest.java || exit 10
+
+OLDJAVA="
+ /java/re/j2se/1.6.0/latest/binaries/${PF}
+ /java/re/j2se/1.5.0/latest/binaries/${PF}
+ /java/re/j2se/1.4.2/latest/binaries/${PF}
+"
+
+SMALL="
+ 0.0
+ 1.1
+ 2.2
+ 1.2.3456
+ 1.2.2147483647.4
+ 1.2.268435456.4
+"
+
+HUGE="
+ 2.16.764.1.3101555394.1.0.100.2.1
+ 1.2.2147483648.4
+ 2.3.4444444444444444444444
+ 1.2.888888888888888888.111111111111111.2222222222222.33333333333333333.44444444444444
+"
+
+for oid in ${SMALL}; do
+ echo ${oid}
+ # new ->
+ ${TESTJAVA}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial || exit 1
+ # -> new
+ ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 2
+ for oldj in ${OLDJAVA}; do
+ if [ -d ${oldj} ]; then
+ echo ${oldj}
+ # -> old
+ ${oldj}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 3
+ # old ->
+ ${oldj}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial.old || exit 4
+ # -> new
+ ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial.old || exit 5
+ fi
+ done
+done
+
+for oid in ${HUGE}; do
+ echo ${oid}
+ # new ->
+ ${TESTJAVA}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial || exit 1
+ # -> new
+ ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 2
+ for oldj in ${OLDJAVA}; do
+ if [ -d ${oldj} ]; then
+ echo ${oldj}
+ # -> old
+ ${oldj}${FS}bin${FS}java SerialTest badin < tmp.oid.serial || exit 3
+ fi
+ done
+done
+
+rm -f tmp.oid.serial
+rm -f tmp.oid.serial.old
+rm -f SerialTest.class
+
+exit 0
diff --git a/jdk/test/sun/security/util/Oid/SerialTest.java b/jdk/test/sun/security/util/Oid/SerialTest.java
new file mode 100644
index 00000000000..2c8516eaa6a
--- /dev/null
+++ b/jdk/test/sun/security/util/Oid/SerialTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * read S11.sh
+ */
+import java.io.*;
+import sun.security.util.*;
+
+/**
+ * Test OID serialization between versions
+ *
+ * java SerialTest out oid // write a OID into System.out
+ * java SerialTest in oid // read from System.in and compare it with oid
+ * java SerialTest badin // make sure *cannot* read from System.in
+ */
+class SerialTest {
+ public static void main(String[] args) throws Exception {
+ if (args[0].equals("out"))
+ out(args[1]);
+ else if (args[0].equals("in"))
+ in(args[1]);
+ else
+ badin();
+ }
+
+ static void in(String oid) throws Exception {
+ ObjectIdentifier o = (ObjectIdentifier) (new ObjectInputStream(System.in).readObject());
+ if (!o.toString().equals(oid))
+ throw new Exception("Read Fail " + o + ", not " + oid);
+ }
+
+ static void badin() throws Exception {
+ boolean pass = true;
+ try {
+ new ObjectInputStream(System.in).readObject();
+ } catch (Exception e) {
+ pass = false;
+ }
+ if (pass) throw new Exception("Should fail but not");
+ }
+
+ static void out(String oid) throws Exception {
+ new ObjectOutputStream(System.out).writeObject(new ObjectIdentifier(oid));
+ }
+}
diff --git a/jdk/test/tools/launcher/MultipleJRE.sh b/jdk/test/tools/launcher/MultipleJRE.sh
index b3e1cf764ed..a6dfaaa5253 100644
--- a/jdk/test/tools/launcher/MultipleJRE.sh
+++ b/jdk/test/tools/launcher/MultipleJRE.sh
@@ -1,14 +1,14 @@
# @test MultipleJRE.sh
-# @bug 4811102 4953711 4955505 4956301 4991229 4998210 5018605 6387069
+# @bug 4811102 4953711 4955505 4956301 4991229 4998210 5018605 6387069 6733959
# @build PrintVersion
# @build UglyPrintVersion
+# @build ZipMeUp
# @run shell MultipleJRE.sh
# @summary Verify Multiple JRE version support
# @author Joseph E. Kowalski
-
#
-# Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
+# Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -49,10 +49,25 @@ then
exit 1
fi
+JAVAEXE="$TESTJAVA/bin/java"
JAVA="$TESTJAVA/bin/java -classpath $TESTCLASSES"
JAR="$TESTJAVA/bin/jar"
OS=`uname -s`;
+#
+# Tests whether we are on windows (true) or not.
+#
+IsWindows() {
+ case "$OS" in
+ Windows* | CYGWIN* )
+ printf "true"
+ ;;
+ * )
+ printf "false"
+ ;;
+ esac
+}
+
#
# Shell routine to test for the proper rejection of syntactically incorrect
# version specifications.
@@ -139,7 +154,6 @@ CreateUglyJar() {
$PACKAGE/UglyPrintVersion.class
}
-
#
# Constructs a jar file with a fair number of "zip directory" entries and
# the MANIFEST.MF entry at or near the end of that directory to validate
@@ -262,6 +276,29 @@ LaunchVM() {
fi
}
+# Tests very long Main-Class attribute in the jar
+TestLongMainClass() {
+ JVER=$1
+ if [ "$JVER" = "mklink" ]; then
+ JVER=XX
+ JDKXX=jdk/j2re$JVER
+ rm -rf jdk
+ mkdir jdk
+ ln -s $TESTJAVA $JDKXX
+ JAVA_VERSION_PATH="`pwd`/jdk"
+ export JAVA_VERSION_PATH
+ fi
+ $JAVAEXE -cp $TESTCLASSES ZipMeUp UglyBetty.jar 4097
+ message="`$JAVAEXE -version:$JVER -jar UglyBetty.jar 2>&1`"
+ echo $message | grep "Error: main-class: attribute exceeds system limits" > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ printf "Long manifest test did not get expected error"
+ exit 1
+ fi
+ unset JAVA_VERSION_PATH
+ rm -rf jdk
+}
+
#
# Main test sequence starts here
#
@@ -280,14 +317,11 @@ CreateJar "" ""
LaunchVM "" "${RELEASE}"
CreateJar "" "0"
LaunchVM "" "${RELEASE}"
-case "$OS" in
- Windows* | CYGWIN* )
- MAXIMUM_PATH=255;
- ;;
- *)
- MAXIMUM_PATH=1024;
- ;;
-esac
+if [ `IsWindows` = "true" ]; then
+ MAXIMUM_PATH=255;
+else
+ MAXIMUM_PATH=1024;
+fi
PATH_LENGTH=`printf "%s" "$UGLYCLASS" | wc -c`
if [ ${PATH_LENGTH} -lt ${MAXIMUM_PATH} ]; then
@@ -346,7 +380,6 @@ if [ -x /usr/bin/zipnote ]; then
LaunchVM "" "${RELEASE}"
fi
-
#
# Throw some syntactically challenged (illegal) version specifiers at
# the interface. Failure (of the launcher) is success for the test.
@@ -357,15 +390,28 @@ TestSyntax "1.2.3-" # Ends with a separator
TestSyntax "1.2+.3" # Embedded modifier
TestSyntax "1.2.4+&1.2*&1++" # Long and invalid
+# On windows we see if there is another jre installed, usually
+# there is, then we test using that, otherwise links are created
+# to get through to SelectVersion.
+if [ `IsWindows` = "false" ]; then
+ TestLongMainClass "mklink"
+else
+ $JAVAEXE -version:1.0+
+ if [ $? -eq 0 ]; then
+ TestLongMainClass "1.0+"
+ else
+ printf "Warning: TestLongMainClass skipped as there is no"
+ printf "viable MJRE installed.\n"
+ fi
+fi
+
#
# Because scribbling in the registry can be rather destructive, only a
# subset of the tests are run on Windows.
#
-case "$OS" in
- Windows* | CYGWIN* )
- exit 0;
- ;;
-esac
+if [ `IsWindows` = "true" ]; then
+ exit 0;
+fi
#
# Additional version specifiers containing spaces. (Sigh, unable to
diff --git a/jdk/test/tools/launcher/ZipMeUp.java b/jdk/test/tools/launcher/ZipMeUp.java
new file mode 100644
index 00000000000..84d3f186e7e
--- /dev/null
+++ b/jdk/test/tools/launcher/ZipMeUp.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * A simple class to create our erring Jar with a very long Main-Class
+ * attribute in the manifest.
+ */
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.zip.CRC32;
+import java.util.zip.CheckedOutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+public class ZipMeUp {
+
+ static final CRC32 crc = new CRC32();
+
+ private static String SOME_KLASS = ".Some";
+
+ static byte[] getManifestAsBytes(int nchars) throws IOException {
+ crc.reset();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ CheckedOutputStream cos = new CheckedOutputStream(baos, crc);
+ PrintStream ps = new PrintStream(cos);
+ ps.println("Manifest-Version: 1.0");
+ ps.print("Main-Class: ");
+ for (int i = 0 ; i < nchars - SOME_KLASS.length() ; i++) {
+ ps.print(i%10);
+ }
+ ps.println(SOME_KLASS);
+ cos.flush();
+ cos.close();
+ ps.close();
+ return baos.toByteArray();
+ }
+
+ /**
+ * The arguments are: filename_to_create length
+ * @param args
+ * @throws java.lang.Exception
+ */
+ public static void main(String...args) throws Exception {
+ FileOutputStream fos = new FileOutputStream(args[0]);
+ ZipOutputStream zos = new ZipOutputStream(fos);
+ byte[] manifest = getManifestAsBytes(Integer.parseInt(args[1]));
+ ZipEntry ze = new ZipEntry("META-INF/MANIFEST.MF");
+ ze.setMethod(ZipEntry.STORED);
+ ze.setSize(manifest.length);
+ ze.setCompressedSize(manifest.length);
+ ze.setCrc(crc.getValue());
+ ze.setTime(System.currentTimeMillis());
+ zos.putNextEntry(ze);
+ zos.write(manifest);
+ zos.flush();
+
+ // add a zero length class
+ ze = new ZipEntry(SOME_KLASS + ".class");
+ ze.setMethod(ZipEntry.STORED);
+ ze.setSize(0);
+ ze.setCompressedSize(0);
+ ze.setCrc(0);
+ ze.setTime(System.currentTimeMillis());
+ zos.putNextEntry(ze);
+ zos.flush();
+ zos.closeEntry();
+ zos.close();
+ System.exit(0);
+ }
+}