Mercurial > hg > release > icedtea7-forest-2.6 > jdk
changeset 9672:4cf1f648f7fd
Merge jdk7u201-b00
line wrap: on
line diff
--- a/.hgtags Mon Oct 22 04:45:27 2018 +0100 +++ b/.hgtags Mon Oct 22 06:23:01 2018 +0100 @@ -685,3 +685,4 @@ 4e72f3b0b16cbacaab59921ed5dc909179f855cd jdk7u191-b01 dceb42b605da53a4dbb87342c58fb7c9a82987f1 jdk7u191-b02 25542ea9adead21edc0041685d6930fdd8c7a53b icedtea-2.6.15 +2c8fc8aa5524b3bfc95364d97c8ee1a42899d358 jdk7u201-b00
--- a/make/sun/net/Makefile Mon Oct 22 04:45:27 2018 +0100 +++ b/make/sun/net/Makefile Mon Oct 22 06:23:01 2018 +0100 @@ -27,6 +27,7 @@ PACKAGE = sun.net PRODUCT = sun SUBDIRS_MAKEFLAGS += JAVAC_MAX_WARNINGS=true +SUBDIRS_MAKEFLAGS += JAVAC_LINT_OPTIONS=-Xlint:all,-deprecation,-path include $(BUILDDIR)/common/Defs.gmk SUBDIRS = others spi
--- a/src/share/classes/com/sun/jndi/ldap/Connection.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/com/sun/jndi/ldap/Connection.java Mon Oct 22 06:23:01 2018 +0100 @@ -386,17 +386,17 @@ // then reset the timeout. if (socket instanceof SSLSocket) { SSLSocket sslSocket = (SSLSocket) socket; - int socketTimeout = sslSocket.getSoTimeout(); if (!IS_HOSTNAME_VERIFICATION_DISABLED) { SSLParameters param = sslSocket.getSSLParameters(); param.setEndpointIdentificationAlgorithm("LDAPS"); sslSocket.setSSLParameters(param); } if (connectTimeout > 0) { + int socketTimeout = sslSocket.getSoTimeout(); sslSocket.setSoTimeout(connectTimeout); // reuse full timeout value + sslSocket.startHandshake(); + sslSocket.setSoTimeout(socketTimeout); } - sslSocket.startHandshake(); - sslSocket.setSoTimeout(socketTimeout); } return socket; }
--- a/src/share/classes/com/sun/media/sound/DLSSoundbank.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/com/sun/media/sound/DLSSoundbank.java Mon Oct 22 06:23:01 2018 +0100 @@ -548,7 +548,7 @@ long count = riff.readUnsignedInt(); if (size - 8 != 0) - riff.skipBytes(size - 8); + riff.skip(size - 8); for (int i = 0; i < count; i++) { DLSModulator modulator = new DLSModulator(); @@ -568,7 +568,7 @@ long count = riff.readUnsignedInt(); if (size - 8 != 0) - riff.skipBytes(size - 8); + riff.skip(size - 8); for (int i = 0; i < count; i++) { DLSModulator modulator = new DLSModulator(); @@ -661,7 +661,7 @@ long loops = riff.readInt(); if (size > 20) - riff.skipBytes(size - 20); + riff.skip(size - 20); for (int i = 0; i < loops; i++) { DLSSampleLoop loop = new DLSSampleLoop(); @@ -671,7 +671,7 @@ loop.length = riff.readUnsignedInt(); sampleOptions.loops.add(loop); if (size2 > 16) - riff.skipBytes(size2 - 16); + riff.skip(size2 - 16); } }
--- a/src/share/classes/com/sun/media/sound/RIFFReader.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/com/sun/media/sound/RIFFReader.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, Oracle and/or its affiliates. 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 @@ -39,21 +39,20 @@ private long filepointer = 0; private final String fourcc; private String riff_type = null; - private long ckSize = 0; + private long ckSize = Integer.MAX_VALUE; private InputStream stream; - private long avail; + private long avail = Integer.MAX_VALUE; private RIFFReader lastiterator = null; public RIFFReader(InputStream stream) throws IOException { - if (stream instanceof RIFFReader) - root = ((RIFFReader)stream).root; - else + if (stream instanceof RIFFReader) { + root = ((RIFFReader) stream).root; + } else { root = this; + } this.stream = stream; - avail = Integer.MAX_VALUE; - ckSize = Integer.MAX_VALUE; // Check for RIFF null paddings, int b; @@ -76,10 +75,12 @@ readFully(fourcc, 1, 3); this.fourcc = new String(fourcc, "ascii"); ckSize = readUnsignedInt(); - - avail = this.ckSize; + avail = ckSize; if (getFormat().equals("RIFF") || getFormat().equals("LIST")) { + if (avail > Integer.MAX_VALUE) { + throw new RIFFInvalidDataException("Chunk size too big"); + } byte[] format = new byte[4]; readFully(format); this.riff_type = new String(format, "ascii"); @@ -118,19 +119,23 @@ } public int read() throws IOException { - if (avail == 0) + if (avail == 0) { return -1; + } int b = stream.read(); - if (b == -1) + if (b == -1) { + avail = 0; return -1; + } avail--; filepointer++; return b; } public int read(byte[] b, int offset, int len) throws IOException { - if (avail == 0) + if (avail == 0) { return -1; + } if (len > avail) { int rlen = stream.read(b, offset, (int)avail); if (rlen != -1) @@ -139,8 +144,10 @@ return rlen; } else { int ret = stream.read(b, offset, len); - if (ret == -1) + if (ret == -1) { + avail = 0; return -1; + } avail -= ret; filepointer += ret; return ret; @@ -165,53 +172,52 @@ } } - public final long skipBytes(long n) throws IOException { - if (n < 0) + @Override + public long skip(final long n) throws IOException { + if (n <= 0 || avail == 0) { return 0; - long skipped = 0; - while (skipped != n) { - long s = skip(n - skipped); - if (s < 0) - break; - if (s == 0) + } + // will not skip more than + long remaining = Math.min(n, avail); + while (remaining > 0) { + // Some input streams like FileInputStream can return more bytes, + // when EOF is reached. + long ret = Math.min(stream.skip(remaining), remaining); + if (ret == 0) { + // EOF or not? we need to check. Thread.yield(); - skipped += s; + if (stream.read() == -1) { + avail = 0; + break; + } + ret = 1; + } + remaining -= ret; + avail -= ret; + filepointer += ret; } - return skipped; + return n - remaining; } - public long skip(long n) throws IOException { - if (avail == 0) - return -1; - if (n > avail) { - long len = stream.skip(avail); - if (len != -1) - filepointer += len; - avail = 0; - return len; - } else { - long ret = stream.skip(n); - if (ret == -1) - return -1; - avail -= ret; - filepointer += ret; - return ret; - } - } - + @Override public int available() { return (int)avail; } public void finish() throws IOException { if (avail != 0) { - skipBytes(avail); + skip(avail); } } // Read ASCII chars from stream - public String readString(int len) throws IOException { - byte[] buff = new byte[len]; + public String readString(final int len) throws IOException { + final byte[] buff; + try { + buff = new byte[len]; + } catch (final OutOfMemoryError oom) { + throw new IOException("Length too big", oom); + } readFully(buff); for (int i = 0; i < buff.length; i++) { if (buff[i] == 0) { @@ -323,6 +329,7 @@ return ch1 + (ch2 << 8) | (ch3 << 16) | (ch4 << 24); } + @Override public void close() throws IOException { finish(); if (this == root)
--- a/src/share/classes/com/sun/media/sound/SF2Soundbank.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/com/sun/media/sound/SF2Soundbank.java Mon Oct 22 06:23:01 2018 +0100 @@ -276,6 +276,9 @@ count--; } + if (presets_bagNdx.isEmpty()) { + throw new RIFFInvalidDataException(); + } int offset = presets_bagNdx.get(0); // Offset should be 0 (but just case) for (int i = 0; i < offset; i++) { @@ -360,6 +363,9 @@ count--; } + if (instruments_bagNdx.isEmpty()) { + throw new RIFFInvalidDataException(); + } int offset = instruments_bagNdx.get(0); // Offset should be 0 (but just case) for (int i = 0; i < offset; i++) { @@ -401,6 +407,9 @@ modulator.amount = chunk.readShort(); modulator.amountSourceOperator = chunk.readUnsignedShort(); modulator.transportOperator = chunk.readUnsignedShort(); + if (i < 0 || i >= instruments_splits_gen.size()) { + throw new RIFFInvalidDataException(); + } SF2LayerRegion split = instruments_splits_gen.get(i); if (split != null) split.modulators.add(modulator); @@ -424,7 +433,8 @@ sample.name = chunk.readString(20); long start = chunk.readUnsignedInt(); long end = chunk.readUnsignedInt(); - sample.data = sampleData.subbuffer(start * 2, end * 2, true); + if (sampleData != null) + sample.data = sampleData.subbuffer(start * 2, end * 2, true); if (sampleData24 != null) sample.data24 = sampleData24.subbuffer(start, end, true); /* @@ -462,6 +472,9 @@ int sampleid = split.generators.get( SF2LayerRegion.GENERATOR_SAMPLEID); split.generators.remove(SF2LayerRegion.GENERATOR_SAMPLEID); + if (sampleid < 0 || sampleid >= samples.size()) { + throw new RIFFInvalidDataException(); + } split.sample = samples.get(sampleid); } else { globalsplit = split; @@ -488,6 +501,9 @@ int instrumentid = split.generators.get( SF2InstrumentRegion.GENERATOR_INSTRUMENT); split.generators.remove(SF2LayerRegion.GENERATOR_INSTRUMENT); + if (instrumentid < 0 || instrumentid >= layers.size()) { + throw new RIFFInvalidDataException(); + } split.layer = layers.get(instrumentid); } else { globalsplit = split;
--- a/src/share/classes/com/sun/naming/internal/VersionHelper12.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/com/sun/naming/internal/VersionHelper12.java Mon Oct 22 06:23:01 2018 +0100 @@ -62,6 +62,25 @@ } /** + * Determines whether classes may be loaded from an arbitrary URL code base. + */ + private static final String TRUST_URL_CODEBASE_PROPERTY = + "com.sun.jndi.ldap.object.trustURLCodebase"; + private static final String trustURLCodebase = + AccessController.doPrivileged( + new PrivilegedAction<String>() { + public String run() { + try { + return System.getProperty(TRUST_URL_CODEBASE_PROPERTY, + "false"); + } catch (SecurityException e) { + return "false"; + } + } + } + ); + + /** * Package private. * * This internal method is used with Thread Context Class Loader (TCCL), @@ -79,12 +98,15 @@ */ public Class<?> loadClass(String className, String codebase) throws ClassNotFoundException, MalformedURLException { + if ("true".equalsIgnoreCase(trustURLCodebase)) { + ClassLoader parent = getContextClassLoader(); + ClassLoader cl = + URLClassLoader.newInstance(getUrlArray(codebase), parent); - ClassLoader parent = getContextClassLoader(); - ClassLoader cl = - URLClassLoader.newInstance(getUrlArray(codebase), parent); - - return loadClass(className, cl); + return loadClass(className, cl); + } else { + return null; + } } String getJndiProperty(final int i) {
--- a/src/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java Mon Oct 22 06:23:01 2018 +0100 @@ -31,7 +31,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Iterator; -import sun.misc.Service; +import java.util.ServiceLoader; import sun.misc.ServiceConfigurationError; import sun.security.action.GetPropertyAction; import com.sun.net.httpserver.*; @@ -94,9 +94,10 @@ } private static boolean loadProviderAsService() { - @SuppressWarnings("unchecked") - Iterator<HttpServerProvider> i = Service.providers(HttpServerProvider.class, - ClassLoader.getSystemClassLoader()); + Iterator<HttpServerProvider> i = + ServiceLoader.load(HttpServerProvider.class, + ClassLoader.getSystemClassLoader()) + .iterator(); for (;;) { try { if (!i.hasNext())
--- a/src/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties Mon Oct 22 06:23:01 2018 +0100 @@ -26,7 +26,7 @@ # CacheRowSetImpl exceptions cachedrowsetimpl.populate = Ung\u00FCltiges ResultSet-Objekt zum Auff\u00FCllen der Methode angegeben cachedrowsetimpl.invalidp = Ung\u00FCltiger Persistence-Provider generiert -cachedrowsetimpl.nullhash = CachedRowSetImpl-Instanz kann nicht instanziiert werden. Null-Hash-Tabelle f\u00FCr Constructor angegeben +cachedrowsetimpl.nullhash = CachedRowSetImpl-Instanz kann nicht instanziiert werden. Null-Hashtabelle f\u00FCr Constructor angegeben cachedrowsetimpl.invalidop = Ung\u00FCltiger Vorgang beim Zeileneinf\u00FCgen cachedrowsetimpl.accfailed = acceptChanges nicht erfolgreich cachedrowsetimpl.invalidcp = Ung\u00FCltige Cursorposition @@ -80,7 +80,7 @@ cachedrowsetimpl.featnotsupp = Feature nicht unterst\u00FCtzt # WebRowSetImpl exceptions -webrowsetimpl.nullhash = WebRowSetImpl-Instanz kann nicht instanziiert werden. Null-Hash-Tabelle f\u00FCr Constructor angegeben +webrowsetimpl.nullhash = WebRowSetImpl-Instanz kann nicht instanziiert werden. Null-Hashtabelle f\u00FCr Constructor angegeben webrowsetimpl.invalidwr = Ung\u00FCltiger Writer webrowsetimpl.invalidrd = Ung\u00FCltiger Reader
--- a/src/share/classes/java/net/InetAddress.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/java/net/InetAddress.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2018, Oracle and/or its affiliates. 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 @@ -32,10 +32,12 @@ import java.util.LinkedList; import java.util.List; import java.util.ArrayList; +import java.util.ServiceLoader; import java.security.AccessController; import java.io.ObjectStreamException; import java.io.ObjectStreamField; import java.io.IOException; +import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectInputStream.GetField; import java.io.ObjectOutputStream; @@ -43,7 +45,6 @@ import sun.security.action.*; import sun.net.InetAddressCachePolicy; import sun.net.util.IPAddressUtil; -import sun.misc.Service; import sun.net.spi.nameservice.*; /** @@ -932,10 +933,11 @@ nameService = java.security.AccessController.doPrivileged( new java.security.PrivilegedExceptionAction<NameService>() { public NameService run() { - Iterator itr = Service.providers(NameServiceDescriptor.class); + Iterator<NameServiceDescriptor> itr = + ServiceLoader.load(NameServiceDescriptor.class) + .iterator(); while (itr.hasNext()) { - NameServiceDescriptor nsd - = (NameServiceDescriptor)itr.next(); + NameServiceDescriptor nsd = itr.next(); if (providerName. equalsIgnoreCase(nsd.getType()+"," +nsd.getProviderName())) { @@ -1595,8 +1597,11 @@ } GetField gf = s.readFields(); String host = (String)gf.get("hostName", null); - int address= gf.get("address", 0); - int family= gf.get("family", 0); + int address = gf.get("address", 0); + int family = gf.get("family", 0); + if (family != IPv4 && family != IPv6) { + throw new InvalidObjectException("invalid address family type: " + family); + } InetAddressHolder h = new InetAddressHolder(host, address, family); UNSAFE.putObject(this, FIELDS_OFFSET, h); }
--- a/src/share/classes/java/net/NetworkInterface.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/java/net/NetworkInterface.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2018, Oracle and/or its affiliates. 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 @@ -312,8 +312,20 @@ if (addr == null) { throw new NullPointerException(); } - if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) { - throw new IllegalArgumentException ("invalid address type"); + if (addr instanceof Inet4Address) { + Inet4Address inet4Address = (Inet4Address) addr; + if (inet4Address.holder.family != InetAddress.IPv4) { + throw new IllegalArgumentException("invalid family type: " + + inet4Address.holder.family); + } + } else if (addr instanceof Inet6Address) { + Inet6Address inet6Address = (Inet6Address) addr; + if (inet6Address.holder.family != InetAddress.IPv6) { + throw new IllegalArgumentException("invalid family type: " + + inet6Address.holder.family); + } + } else { + throw new IllegalArgumentException("invalid address type: " + addr); } return getByInetAddress0(addr); }
--- a/src/share/classes/java/net/ServerSocket.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/java/net/ServerSocket.java Mon Oct 22 06:23:01 2018 +0100 @@ -267,10 +267,9 @@ AccessController.doPrivileged( new PrivilegedExceptionAction<Void>() { public Void run() throws NoSuchMethodException { - Class[] cl = new Class[2]; - cl[0] = SocketAddress.class; - cl[1] = Integer.TYPE; - impl.getClass().getDeclaredMethod("connect", cl); + impl.getClass().getDeclaredMethod("connect", + SocketAddress.class, + int.class); return null; } });
--- a/src/share/classes/java/net/URLClassLoader.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/java/net/URLClassLoader.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. 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 @@ -41,6 +41,7 @@ import java.security.Permission; import java.security.PermissionCollection; import sun.misc.Resource; +import sun.misc.SharedSecrets; import sun.misc.URLClassPath; import sun.net.www.ParseUtil; import sun.security.util.SecurityConstants; @@ -461,13 +462,13 @@ protected Package definePackage(String name, Manifest man, URL url) throws IllegalArgumentException { - String path = name.replace('.', '/').concat("/"); String specTitle = null, specVersion = null, specVendor = null; String implTitle = null, implVersion = null, implVendor = null; String sealed = null; URL sealBase = null; - Attributes attr = man.getAttributes(path); + Attributes attr = SharedSecrets.javaUtilJarAccess() + .getTrustedAttributes(man, name.replace('.', '/').concat("/")); if (attr != null) { specTitle = attr.getValue(Name.SPECIFICATION_TITLE); specVersion = attr.getValue(Name.SPECIFICATION_VERSION); @@ -511,10 +512,12 @@ /* * Returns true if the specified package name is sealed according to the * given manifest. + * + * @throws SecurityException if the package name is untrusted in the manifest */ private boolean isSealed(String name, Manifest man) { - String path = name.replace('.', '/').concat("/"); - Attributes attr = man.getAttributes(path); + Attributes attr = SharedSecrets.javaUtilJarAccess() + .getTrustedAttributes(man, name.replace('.', '/').concat("/")); String sealed = null; if (attr != null) { sealed = attr.getValue(Name.SEALED);
--- a/src/share/classes/java/security/Security.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/java/security/Security.java Mon Oct 22 06:23:01 2018 +0100 @@ -814,7 +814,7 @@ public Void run() { try { /* Get the class via the bootstrap class loader. */ - Class cl = Class.forName( + Class<?> cl = Class.forName( "java.lang.SecurityManager", false, null); Field f = null; boolean accessible = false;
--- a/src/share/classes/java/util/jar/JarFile.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/java/util/jar/JarFile.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. 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 @@ -178,14 +178,14 @@ if (manEntry != null) { if (verify) { byte[] b = getBytes(manEntry); - man = new Manifest(new ByteArrayInputStream(b)); if (!jvInitialized) { jv = new JarVerifier(b); } + man = new Manifest(jv, new ByteArrayInputStream(b)); } else { man = new Manifest(super.getInputStream(manEntry)); } - manRef = new SoftReference(man); + manRef = new SoftReference<>(man); } } return man; @@ -235,13 +235,13 @@ * Returns an enumeration of the zip file entries. */ public Enumeration<JarEntry> entries() { - final Enumeration enum_ = super.entries(); + final Enumeration<? extends ZipEntry> enum_ = super.entries(); return new Enumeration<JarEntry>() { public boolean hasMoreElements() { return enum_.hasMoreElements(); } public JarFileEntry nextElement() { - ZipEntry ze = (ZipEntry)enum_.nextElement(); + ZipEntry ze = enum_.nextElement(); return new JarFileEntry(ze); } }; @@ -551,7 +551,7 @@ return false; } - private synchronized void ensureInitialization() { + synchronized void ensureInitialization() { try { maybeInstantiateVerifier(); } catch (IOException e) { @@ -612,7 +612,7 @@ } // screen out entries which are never signed - final Enumeration enum_ = super.entries(); + final Enumeration<? extends ZipEntry> enum_ = super.entries(); return new Enumeration<JarEntry>() { ZipEntry entry; @@ -622,7 +622,7 @@ return true; } while (enum_.hasMoreElements()) { - ZipEntry ze = (ZipEntry) enum_.nextElement(); + ZipEntry ze = enum_.nextElement(); if (JarVerifier.isSigningRelated(ze.getName())) { continue; } @@ -653,7 +653,7 @@ * JAR file has no signed content. Is there a non-signing * code source? */ - Enumeration unsigned = unsignedEntryNames(); + Enumeration<String> unsigned = unsignedEntryNames(); if (unsigned.hasMoreElements()) { return new CodeSource[]{JarVerifier.getUnsignedCS(url)}; } else { @@ -662,7 +662,7 @@ } private Enumeration<String> unsignedEntryNames() { - final Enumeration entries = entries(); + final Enumeration<JarEntry> entries = entries(); return new Enumeration<String>() { String name; @@ -677,7 +677,7 @@ } while (entries.hasMoreElements()) { String value; - ZipEntry e = (ZipEntry) entries.nextElement(); + ZipEntry e = entries.nextElement(); value = e.getName(); if (e.isDirectory() || JarVerifier.isSigningRelated(value)) { continue; @@ -730,11 +730,11 @@ } } - List getManifestDigests() { + List<Object> getManifestDigests() { ensureInitialization(); if (jv != null) { return jv.getManifestDigests(); } - return new ArrayList(); + return new ArrayList<Object>(); } }
--- a/src/share/classes/java/util/jar/JarVerifier.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/java/util/jar/JarVerifier.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. 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 @@ -91,7 +91,7 @@ private Object csdomain = new Object(); /** collect -DIGEST-MANIFEST values for blacklist */ - private List manifestDigests; + private List<Object> manifestDigests; public JarVerifier(byte rawBytes[]) { manifestRawBytes = rawBytes; @@ -100,7 +100,7 @@ sigFileData = new Hashtable<>(11); pendingBlocks = new ArrayList<>(); baos = new ByteArrayOutputStream(); - manifestDigests = new ArrayList(); + manifestDigests = new ArrayList<>(); } /** @@ -871,11 +871,31 @@ eagerValidation = eager; } - public synchronized List getManifestDigests() { + public synchronized List<Object> getManifestDigests() { return Collections.unmodifiableList(manifestDigests); } static CodeSource getUnsignedCS(URL url) { return new VerifierCodeSource(null, url, (java.security.cert.Certificate[]) null); } + + /** + * Returns whether the name is trusted. Used by + * {@link Manifest#getTrustedAttributes(String)}. + */ + boolean isTrustedManifestEntry(String name) { + // How many signers? MANIFEST.MF is always verified + CodeSigner[] forMan = verifiedSigners.get(JarFile.MANIFEST_NAME); + if (forMan == null) { + return true; + } + // Check sigFileSigners first, because we are mainly dealing with + // non-file entries which will stay in sigFileSigners forever. + CodeSigner[] forName = sigFileSigners.get(name); + if (forName == null) { + forName = verifiedSigners.get(name); + } + // Returns trusted if all signers sign the entry + return forName != null && forName.length == forMan.length; + } }
--- a/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. 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 @@ -57,7 +57,15 @@ jar.setEagerValidation(eager); } - public List getManifestDigests(JarFile jar) { + public List<Object> getManifestDigests(JarFile jar) { return jar.getManifestDigests(); } + + public Attributes getTrustedAttributes(Manifest man, String name) { + return man.getTrustedAttributes(name); + } + + public void ensureInitialization(JarFile jar) { + jar.ensureInitialization(); + } }
--- a/src/share/classes/java/util/jar/Manifest.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/java/util/jar/Manifest.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. 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 @@ -48,15 +48,19 @@ */ public class Manifest implements Cloneable { // manifest main attributes - private Attributes attr = new Attributes(); + private final Attributes attr = new Attributes(); // manifest entries - private Map entries = new HashMap(); + private final Map<String, Attributes> entries = new HashMap<>(); + + // associated JarVerifier, not null when called by JarFile::getManifest. + private final JarVerifier jv; /** * Constructs a new, empty Manifest. */ public Manifest() { + jv = null; } /** @@ -66,7 +70,16 @@ * @throws IOException if an I/O error has occurred */ public Manifest(InputStream is) throws IOException { + this(null, is); + } + + /** + * Constructs a new Manifest from the specified input stream + * and associates it with a JarVerifier. + */ + Manifest(JarVerifier jv, InputStream is) throws IOException { read(is); + this.jv = jv; } /** @@ -77,6 +90,7 @@ public Manifest(Manifest man) { attr.putAll(man.getMainAttributes()); entries.putAll(man.getEntries()); + jv = man.jv; } /** @@ -127,6 +141,27 @@ } /** + * Returns the Attributes for the specified entry name, if trusted. + * + * @param name entry name + * @return returns the same result as {@link #getAttributes(String)} + * @throws SecurityException if the associated jar is signed but this entry + * has been modified after signing (i.e. the section in the manifest + * does not exist in SF files of all signers). + */ + Attributes getTrustedAttributes(String name) { + // Note: Before the verification of MANIFEST.MF/.SF/.RSA files is done, + // jv.isTrustedManifestEntry() isn't able to detect MANIFEST.MF change. + // Users of this method should call SharedSecrets.javaUtilJarAccess() + // .ensureInitialization() first. + Attributes result = getAttributes(name); + if (result != null && jv != null && ! jv.isTrustedManifestEntry(name)) { + throw new SecurityException("Untrusted manifest entry: " + name); + } + return result; + } + + /** * Clears the main Attributes as well as the entries in this Manifest. */ public void clear() { @@ -148,11 +183,11 @@ // Write out the main attributes for the manifest attr.writeMain(dos); // Now write out the pre-entry attributes - Iterator it = entries.entrySet().iterator(); + Iterator<Map.Entry<String, Attributes>> it = entries.entrySet().iterator(); while (it.hasNext()) { - Map.Entry e = (Map.Entry)it.next(); + Map.Entry<String, Attributes> e = it.next(); StringBuffer buffer = new StringBuffer("Name: "); - String value = (String)e.getKey(); + String value = e.getKey(); if (value != null) { byte[] vb = value.getBytes("UTF8"); value = new String(vb, 0, 0, vb.length); @@ -161,7 +196,7 @@ buffer.append("\r\n"); make72Safe(buffer); dos.writeBytes(buffer.toString()); - ((Attributes)e.getValue()).write(dos); + e.getValue().write(dos); } dos.flush(); }
--- a/src/share/classes/java/util/logging/LogManager.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/java/util/logging/LogManager.java Mon Oct 22 06:23:01 2018 +0100 @@ -185,10 +185,10 @@ cname = System.getProperty("java.util.logging.manager"); if (cname != null) { try { - Class clz = ClassLoader.getSystemClassLoader().loadClass(cname); + Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname); manager = (LogManager) clz.newInstance(); } catch (ClassNotFoundException ex) { - Class clz = Thread.currentThread().getContextClassLoader().loadClass(cname); + Class<?> clz = Thread.currentThread().getContextClassLoader().loadClass(cname); manager = (LogManager) clz.newInstance(); } } @@ -212,10 +212,10 @@ // Adding the global Logger. Doing so in the Logger.<clinit> // would deadlock with the LogManager.<clinit>. - Logger.global.setLogManager(manager); + Logger.getGlobal().setLogManager(manager); // Make sure the global logger will be registered in the // global manager's default contexts. - manager.addLogger(Logger.global); + manager.addLogger(Logger.getGlobal()); manager.systemContext.addLocalLogger(Logger.global, false); manager.userContext.addLocalLogger(Logger.global, false); @@ -805,8 +805,8 @@ for (int i = 0; i < names.length; i++) { String word = names[i]; try { - Class clz = ClassLoader.getSystemClassLoader().loadClass(word); - Handler hdl = (Handler) clz.newInstance(); + Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word); + Handler hdl = (Handler) clz.newInstance(); // Check if there is a property defining the // this handler's level. String levs = getProperty(word + ".level"); @@ -1114,11 +1114,11 @@ // responsibility to initialize the logging configuration, by // calling readConfiguration(InputStream) with a suitable stream. try { - Class clz = ClassLoader.getSystemClassLoader().loadClass(cname); + Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname); clz.newInstance(); return; } catch (ClassNotFoundException ex) { - Class clz = Thread.currentThread().getContextClassLoader().loadClass(cname); + Class<?> clz = Thread.currentThread().getContextClassLoader().loadClass(cname); clz.newInstance(); return; } @@ -1259,7 +1259,7 @@ for (int i = 0; i < names.length; i++) { String word = names[i]; try { - Class clz = ClassLoader.getSystemClassLoader().loadClass(word); + Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word); clz.newInstance(); } catch (Exception ex) { System.err.println("Can't load config class \"" + word + "\""); @@ -1354,7 +1354,7 @@ String val = getProperty(name); try { if (val != null) { - Class clz = ClassLoader.getSystemClassLoader().loadClass(val); + Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(val); return (Filter) clz.newInstance(); } } catch (Exception ex) { @@ -1375,7 +1375,7 @@ String val = getProperty(name); try { if (val != null) { - Class clz = ClassLoader.getSystemClassLoader().loadClass(val); + Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(val); return (Formatter) clz.newInstance(); } } catch (Exception ex) {
--- a/src/share/classes/java/util/prefs/Preferences.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/java/util/prefs/Preferences.java Mon Oct 22 06:23:01 2018 +0100 @@ -422,7 +422,7 @@ * @throws IllegalArgumentException if the package has node preferences * node associated with it. */ - private static String nodeName(Class c) { + private static String nodeName(Class<?> c) { if (c.isArray()) throw new IllegalArgumentException( "Arrays have no associated preferences node.");
--- a/src/share/classes/java/util/prefs/XmlSupport.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/java/util/prefs/XmlSupport.java Mon Oct 22 06:23:01 2018 +0100 @@ -106,7 +106,7 @@ xmlRoot.setAttribute("type", (p.isUserNode() ? "user" : "system")); // Get bottom-up list of nodes from p to root, excluding root - List ancestors = new ArrayList(); + List<Preferences> ancestors = new ArrayList<>(); for (Preferences kid = p, dad = kid.parent(); dad != null; kid = dad, dad = kid.parent()) { @@ -116,7 +116,7 @@ for (int i=ancestors.size()-1; i >= 0; i--) { e.appendChild(doc.createElement("map")); e = (Element) e.appendChild(doc.createElement("node")); - e.setAttribute("name", ((Preferences)ancestors.get(i)).name()); + e.setAttribute("name", ancestors.get(i).name()); } putPreferencesInXml(e, doc, p, subTree); @@ -339,17 +339,17 @@ * @throws IOException if writing to the specified output stream * results in an <tt>IOException</tt>. */ - static void exportMap(OutputStream os, Map map) throws IOException { + static void exportMap(OutputStream os, Map<String, String> map) throws IOException { Document doc = createPrefsDoc("map"); Element xmlMap = doc.getDocumentElement( ) ; xmlMap.setAttribute("MAP_XML_VERSION", MAP_XML_VERSION); - for (Iterator i = map.entrySet().iterator(); i.hasNext(); ) { - Map.Entry e = (Map.Entry) i.next(); + for (Iterator<Map.Entry<String, String>> i = map.entrySet().iterator(); i.hasNext(); ) { + Map.Entry<String, String> e = i.next(); Element xe = (Element) xmlMap.appendChild(doc.createElement("entry")); - xe.setAttribute("key", (String) e.getKey()); - xe.setAttribute("value", (String) e.getValue()); + xe.setAttribute("key", e.getKey()); + xe.setAttribute("value", e.getValue()); } writeDoc(doc, os); @@ -368,7 +368,7 @@ * @throws InvalidPreferencesFormatException Data on input stream does not * constitute a valid XML document with the mandated document type. */ - static void importMap(InputStream is, Map m) + static void importMap(InputStream is, Map<String, String> m) throws IOException, InvalidPreferencesFormatException { try {
--- a/src/share/classes/java/util/zip/ZipEntry.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/java/util/zip/ZipEntry.java Mon Oct 22 06:23:01 2018 +0100 @@ -281,6 +281,7 @@ * Converts DOS time to Java time (number of milliseconds since epoch). */ private static long dosToJavaTime(long dtime) { + @SuppressWarnings("deprecation") // Use of date constructor. Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80), (int)(((dtime >> 21) & 0x0f) - 1), (int)((dtime >> 16) & 0x1f), @@ -293,6 +294,7 @@ /* * Converts Java time to DOS time. */ + @SuppressWarnings("deprecation") // Use of date methods private static long javaToDosTime(long time) { Date d = new Date(time); int year = d.getYear() + 1900;
--- a/src/share/classes/javax/crypto/Cipher.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/javax/crypto/Cipher.java Mon Oct 22 06:23:01 2018 +0100 @@ -2498,7 +2498,7 @@ // Input sanity check if ((src == null) || (offset < 0) || (len < 0) - || ((len + offset) > src.length)) { + || (len > (src.length - offset))) { throw new IllegalArgumentException("Bad arguments"); }
--- a/src/share/classes/javax/crypto/CipherInputStream.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/javax/crypto/CipherInputStream.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. 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 @@ -50,6 +50,13 @@ * that are not thrown by its ancestor classes. In particular, the * <code>skip</code> method skips, and the <code>available</code> * method counts only data that have been processed by the encapsulated Cipher. + * This class may catch BadPaddingException and other exceptions thrown by + * failed integrity checks during decryption. These exceptions are not + * re-thrown, so the client may not be informed that integrity checks + * failed. Because of this behavior, this class may not be suitable + * for use with decryption in an authenticated mode of operation (e.g. GCM). + * Applications that require authenticated encryption can use the Cipher API + * directly as an alternative to using this class. * * <p> It is crucial for a programmer using this class not to use * methods that are not defined or overriden in this class (such as a
--- a/src/share/classes/javax/crypto/spec/GCMParameterSpec.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/javax/crypto/spec/GCMParameterSpec.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, Oracle and/or its affiliates. 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 @@ -120,7 +120,7 @@ // Input sanity check if ((src == null) ||(len < 0) || (offset < 0) - || ((len + offset) > src.length)) { + || (len > (src.length - offset))) { throw new IllegalArgumentException("Invalid buffer arguments"); }
--- a/src/share/classes/javax/script/ScriptEngineManager.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/javax/script/ScriptEngineManager.java Mon Oct 22 06:23:01 2018 +0100 @@ -97,7 +97,7 @@ } private List<ScriptEngineFactory> initEngines(final ClassLoader loader) { - Iterator itr = null; + Iterator<ScriptEngineFactory> itr = null; try { if (loader != null) { itr = Service.providers(ScriptEngineFactory.class, loader); @@ -120,7 +120,7 @@ try { while (itr.hasNext()) { try { - ScriptEngineFactory fact = (ScriptEngineFactory) itr.next(); + ScriptEngineFactory fact = itr.next(); facList.add(fact); } catch (ServiceConfigurationError err) { System.err.println("ScriptEngineManager providers.next(): "
--- a/src/share/classes/sun/misc/BASE64Decoder.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/misc/BASE64Decoder.java Mon Oct 22 06:23:01 2018 +0100 @@ -102,6 +102,7 @@ /** * Decode one BASE64 atom into 1, 2, or 3 bytes of data. */ + @SuppressWarnings("fallthrough") protected void decodeAtom(PushbackInputStream inStream, OutputStream outStream, int rem) throws java.io.IOException {
--- a/src/share/classes/sun/misc/ExtensionDependency.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/misc/ExtensionDependency.java Mon Oct 22 06:23:01 2018 +0100 @@ -70,7 +70,7 @@ public class ExtensionDependency { /* Callbak interfaces to delegate installation of missing extensions */ - private static Vector providers; + private static Vector<ExtensionInstallationProvider> providers; /** * <p> @@ -83,7 +83,7 @@ (ExtensionInstallationProvider eip) { if (providers == null) { - providers = new Vector(); + providers = new Vector<>(); } providers.add(eip); } @@ -93,7 +93,7 @@ * Unregister a previously installed installation provider * </p> */ - public synchronized static void removeExtensionInstallationProvider + public synchronized static void removeExtensionInstallationProvider (ExtensionInstallationProvider eip) { providers.remove(eip); @@ -348,14 +348,16 @@ ExtensionInfo instInfo) throws ExtensionInstallationException { - - Vector currentProviders; + Vector<ExtensionInstallationProvider> currentProviders; synchronized(providers) { - currentProviders = (Vector) providers.clone(); + @SuppressWarnings("unchecked") + Vector<ExtensionInstallationProvider> tmp = + (Vector<ExtensionInstallationProvider>) providers.clone(); + currentProviders = tmp; } - for (Enumeration e=currentProviders.elements();e.hasMoreElements();) { - ExtensionInstallationProvider eip = - (ExtensionInstallationProvider) e.nextElement(); + for (Enumeration<ExtensionInstallationProvider> e = currentProviders.elements(); + e.hasMoreElements();) { + ExtensionInstallationProvider eip = e.nextElement(); if (eip!=null) { // delegate the installation to the provider
--- a/src/share/classes/sun/misc/JarIndex.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/misc/JarIndex.java Mon Oct 22 06:23:01 2018 +0100 @@ -50,13 +50,13 @@ * The hash map that maintains mappings from * package/classe/resource to jar file list(s) */ - private HashMap indexMap; + private HashMap<String,LinkedList<String>> indexMap; /** * The hash map that maintains mappings from * jar file to package/class/resource lists */ - private HashMap jarMap; + private HashMap<String,LinkedList<String>> jarMap; /* * An ordered list of jar file names. @@ -81,8 +81,8 @@ * Constructs a new, empty jar index. */ public JarIndex() { - indexMap = new HashMap(); - jarMap = new HashMap(); + indexMap = new HashMap<>(); + jarMap = new HashMap<>(); } /** @@ -153,10 +153,11 @@ * Add the key, value pair to the hashmap, the value will * be put in a linked list which is created if necessary. */ - private void addToList(String key, String value, HashMap t) { - LinkedList list = (LinkedList)t.get(key); + private void addToList(String key, String value, + HashMap<String,LinkedList<String>> t) { + LinkedList<String> list = t.get(key); if (list == null) { - list = new LinkedList(); + list = new LinkedList<>(); list.add(value); t.put(key, list); } else if (!list.contains(value)) { @@ -169,13 +170,13 @@ * * @param fileName the key of the mapping */ - public LinkedList get(String fileName) { - LinkedList jarFiles = null; - if ((jarFiles = (LinkedList)indexMap.get(fileName)) == null) { + public LinkedList<String> get(String fileName) { + LinkedList<String> jarFiles = null; + if ((jarFiles = indexMap.get(fileName)) == null) { /* try the package name again */ int pos; if((pos = fileName.lastIndexOf("/")) != -1) { - jarFiles = (LinkedList)indexMap.get(fileName.substring(0, pos)); + jarFiles = indexMap.get(fileName.substring(0, pos)); } } return jarFiles; @@ -238,9 +239,9 @@ ZipFile zrf = new ZipFile(currentJar.replace ('/', File.separatorChar)); - Enumeration entries = zrf.entries(); + Enumeration<? extends ZipEntry> entries = zrf.entries(); while(entries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) entries.nextElement(); + ZipEntry entry = entries.nextElement(); String fileName = entry.getName(); // Skip the META-INF directory, the index, and manifest. @@ -285,11 +286,11 @@ /* print out the jar file name */ String jar = jarFiles[i]; bw.write(jar + "\n"); - LinkedList jarlist = (LinkedList)jarMap.get(jar); + LinkedList<String> jarlist = jarMap.get(jar); if (jarlist != null) { - Iterator listitr = jarlist.iterator(); + Iterator<String> listitr = jarlist.iterator(); while(listitr.hasNext()) { - bw.write((String)(listitr.next()) + "\n"); + bw.write(listitr.next() + "\n"); } } bw.write("\n"); @@ -312,7 +313,7 @@ String currentJar = null; /* an ordered list of jar file names */ - Vector jars = new Vector(); + Vector<String> jars = new Vector<>(); /* read until we see a .jar line */ while((line = br.readLine()) != null && !line.endsWith(".jar")); @@ -331,7 +332,7 @@ } } - jarFiles = (String[])jars.toArray(new String[jars.size()]); + jarFiles = jars.toArray(new String[jars.size()]); } /** @@ -345,14 +346,14 @@ * */ public void merge(JarIndex toIndex, String path) { - Iterator itr = indexMap.entrySet().iterator(); + Iterator<Map.Entry<String,LinkedList<String>>> itr = indexMap.entrySet().iterator(); while(itr.hasNext()) { - Map.Entry e = (Map.Entry)itr.next(); - String packageName = (String)e.getKey(); - LinkedList from_list = (LinkedList)e.getValue(); - Iterator listItr = from_list.iterator(); + Map.Entry<String,LinkedList<String>> e = itr.next(); + String packageName = e.getKey(); + LinkedList<String> from_list = e.getValue(); + Iterator<String> listItr = from_list.iterator(); while(listItr.hasNext()) { - String jarName = (String)listItr.next(); + String jarName = listItr.next(); if (path != null) { jarName = path.concat(jarName); }
--- a/src/share/classes/sun/misc/JavaUtilJarAccess.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/misc/JavaUtilJarAccess.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. 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 @@ -30,8 +30,10 @@ import java.security.CodeSource; import java.util.Enumeration; import java.util.List; +import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.jar.Manifest; public interface JavaUtilJarAccess { public boolean jarFileHasClassPathAttribute(JarFile jar) throws IOException; @@ -40,5 +42,7 @@ public Enumeration<String> entryNames(JarFile jar, CodeSource[] cs); public Enumeration<JarEntry> entries2(JarFile jar); public void setEagerValidation(JarFile jar, boolean eager); - public List getManifestDigests(JarFile jar); + public List<Object> getManifestDigests(JarFile jar); + public Attributes getTrustedAttributes(Manifest man, String name); + public void ensureInitialization(JarFile jar); }
--- a/src/share/classes/sun/misc/ProxyGenerator.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/misc/ProxyGenerator.java Mon Oct 22 06:23:01 2018 +0100 @@ -361,7 +361,7 @@ try { hashCodeMethod = Object.class.getMethod("hashCode"); equalsMethod = - Object.class.getMethod("equals", new Class[] { Object.class }); + Object.class.getMethod("equals", new Class<?>[] { Object.class }); toStringMethod = Object.class.getMethod("toString"); } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.getMessage()); @@ -569,11 +569,11 @@ * passed to the invocation handler's "invoke" method for a given * set of duplicate methods. */ - private void addProxyMethod(Method m, Class fromClass) { + private void addProxyMethod(Method m, Class<?> fromClass) { String name = m.getName(); - Class[] parameterTypes = m.getParameterTypes(); - Class returnType = m.getReturnType(); - Class[] exceptionTypes = m.getExceptionTypes(); + Class<?>[] parameterTypes = m.getParameterTypes(); + Class<?> returnType = m.getReturnType(); + Class<?>[] exceptionTypes = m.getExceptionTypes(); String sig = name + getParameterDescriptors(parameterTypes); List<ProxyMethod> sigmethods = proxyMethods.get(sig); @@ -591,7 +591,7 @@ exceptionTypes, pm.exceptionTypes, legalExceptions); collectCompatibleTypes( pm.exceptionTypes, exceptionTypes, legalExceptions); - pm.exceptionTypes = new Class[legalExceptions.size()]; + pm.exceptionTypes = new Class<?>[legalExceptions.size()]; pm.exceptionTypes = legalExceptions.toArray(pm.exceptionTypes); return; @@ -858,15 +858,15 @@ private class ProxyMethod { public String methodName; - public Class[] parameterTypes; - public Class returnType; - public Class[] exceptionTypes; - public Class fromClass; + public Class<?>[] parameterTypes; + public Class<?> returnType; + public Class<?>[] exceptionTypes; + public Class<?> fromClass; public String methodFieldName; - private ProxyMethod(String methodName, Class[] parameterTypes, - Class returnType, Class[] exceptionTypes, - Class fromClass) + private ProxyMethod(String methodName, Class<?>[] parameterTypes, + Class<?> returnType, Class<?>[] exceptionTypes, + Class<?> fromClass) { this.methodName = methodName; this.parameterTypes = parameterTypes; @@ -1011,7 +1011,7 @@ * invocation handler's "invoke" method. The code is written * to the supplied stream. */ - private void codeWrapArgument(Class type, int slot, + private void codeWrapArgument(Class<?> type, int slot, DataOutputStream out) throws IOException { @@ -1052,7 +1052,7 @@ * Object) to its correct type. The code is written to the * supplied stream. */ - private void codeUnwrapReturnValue(Class type, DataOutputStream out) + private void codeUnwrapReturnValue(Class<?> type, DataOutputStream out) throws IOException { if (type.isPrimitive()) { @@ -1401,7 +1401,7 @@ * the supplied stream. Note that the code generated by this method * may caused the checked ClassNotFoundException to be thrown. */ - private void codeClassForName(Class cl, DataOutputStream out) + private void codeClassForName(Class<?> cl, DataOutputStream out) throws IOException { code_ldc(cp.getString(cl.getName()), out); @@ -1432,8 +1432,8 @@ * Return the "method descriptor" string for a method with the given * parameter types and return type. See JVMS section 4.3.3. */ - private static String getMethodDescriptor(Class[] parameterTypes, - Class returnType) + private static String getMethodDescriptor(Class<?>[] parameterTypes, + Class<?> returnType) { return getParameterDescriptors(parameterTypes) + ((returnType == void.class) ? "V" : getFieldType(returnType)); @@ -1446,7 +1446,7 @@ * string is useful for constructing string keys for methods without * regard to their return type. */ - private static String getParameterDescriptors(Class[] parameterTypes) { + private static String getParameterDescriptors(Class<?>[] parameterTypes) { StringBuilder desc = new StringBuilder("("); for (int i = 0; i < parameterTypes.length; i++) { desc.append(getFieldType(parameterTypes[i])); @@ -1460,7 +1460,7 @@ * a field descriptor, a parameter descriptor, or a return descriptor * other than "void". See JVMS section 4.3.2. */ - private static String getFieldType(Class type) { + private static String getFieldType(Class<?> type) { if (type.isPrimitive()) { return PrimitiveTypeInfo.get(type).baseTypeString; } else if (type.isArray()) { @@ -1482,7 +1482,7 @@ * method with the given name and parameter types. */ private static String getFriendlyMethodSignature(String name, - Class[] parameterTypes) + Class<?>[] parameterTypes) { StringBuilder sig = new StringBuilder(name); sig.append('('); @@ -1490,7 +1490,7 @@ if (i > 0) { sig.append(','); } - Class parameterType = parameterTypes[i]; + Class<?> parameterType = parameterTypes[i]; int dimensions = 0; while (parameterType.isArray()) { parameterType = parameterType.getComponentType(); @@ -1514,7 +1514,7 @@ * this abstract notion of a "word" in section 3.4, but that definition * was removed for the second edition. */ - private static int getWordsPerType(Class type) { + private static int getWordsPerType(Class<?> type) { if (type == long.class || type == double.class) { return 2; } else { @@ -1642,8 +1642,7 @@ /** descriptor of same method */ public String unwrapMethodDesc; - private static Map<Class,PrimitiveTypeInfo> table = - new HashMap<Class,PrimitiveTypeInfo>(); + private static Map<Class<?>,PrimitiveTypeInfo> table = new HashMap<>(); static { add(byte.class, Byte.class); add(char.class, Character.class); @@ -1655,12 +1654,12 @@ add(boolean.class, Boolean.class); } - private static void add(Class primitiveClass, Class wrapperClass) { + private static void add(Class<?> primitiveClass, Class<?> wrapperClass) { table.put(primitiveClass, new PrimitiveTypeInfo(primitiveClass, wrapperClass)); } - private PrimitiveTypeInfo(Class primitiveClass, Class wrapperClass) { + private PrimitiveTypeInfo(Class<?> primitiveClass, Class<?> wrapperClass) { assert primitiveClass.isPrimitive(); baseTypeString = @@ -1673,7 +1672,7 @@ unwrapMethodDesc = "()" + baseTypeString; } - public static PrimitiveTypeInfo get(Class cl) { + public static PrimitiveTypeInfo get(Class<?> cl) { return table.get(cl); } } @@ -1704,7 +1703,7 @@ * and for assigning the next index value. Note that element 0 * of this list corresponds to constant pool index 1. */ - private List<Entry> pool = new ArrayList<Entry>(32); + private List<Entry> pool = new ArrayList<>(32); /** * maps constant pool data of all types to constant pool indexes. @@ -1712,7 +1711,7 @@ * This map is used to look up the index of an existing entry for * values of all types. */ - private Map<Object,Short> map = new HashMap<Object,Short>(16); + private Map<Object,Short> map = new HashMap<>(16); /** true if no new constant pool entries may be added */ private boolean readOnly = false;
--- a/src/share/classes/sun/misc/Service.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/misc/Service.java Mon Oct 22 06:23:01 2018 +0100 @@ -125,13 +125,13 @@ * @since 1.3 */ -public final class Service { +public final class Service<S> { private static final String prefix = "META-INF/services/"; private Service() { } - private static void fail(Class service, String msg, Throwable cause) + private static void fail(Class<?> service, String msg, Throwable cause) throws ServiceConfigurationError { ServiceConfigurationError sce @@ -140,13 +140,13 @@ throw sce; } - private static void fail(Class service, String msg) + private static void fail(Class<?> service, String msg) throws ServiceConfigurationError { throw new ServiceConfigurationError(service.getName() + ": " + msg); } - private static void fail(Class service, URL u, int line, String msg) + private static void fail(Class<?> service, URL u, int line, String msg) throws ServiceConfigurationError { fail(service, u + ":" + line + ": " + msg); @@ -157,8 +157,8 @@ * on the line to both the names list and the returned set iff the name is * not already a member of the returned set. */ - private static int parseLine(Class service, URL u, BufferedReader r, int lc, - List names, Set returned) + private static int parseLine(Class<?> service, URL u, BufferedReader r, int lc, + List<String> names, Set<String> returned) throws IOException, ServiceConfigurationError { String ln = r.readLine(); @@ -211,12 +211,12 @@ * If an I/O error occurs while reading from the given URL, or * if a configuration-file format error is detected */ - private static Iterator parse(Class service, URL u, Set returned) + private static Iterator<String> parse(Class<?> service, URL u, Set<String> returned) throws ServiceConfigurationError { InputStream in = null; BufferedReader r = null; - ArrayList names = new ArrayList(); + ArrayList<String> names = new ArrayList<>(); try { in = u.openStream(); r = new BufferedReader(new InputStreamReader(in, "utf-8")); @@ -239,16 +239,16 @@ /** * Private inner class implementing fully-lazy provider lookup */ - private static class LazyIterator implements Iterator { + private static class LazyIterator<S> implements Iterator<S> { - Class service; + Class<S> service; ClassLoader loader; - Enumeration configs = null; - Iterator pending = null; - Set returned = new TreeSet(); + Enumeration<URL> configs = null; + Iterator<String> pending = null; + Set<String> returned = new TreeSet<>(); String nextName = null; - private LazyIterator(Class service, ClassLoader loader) { + private LazyIterator(Class<S> service, ClassLoader loader) { this.service = service; this.loader = loader; } @@ -272,13 +272,13 @@ if (!configs.hasMoreElements()) { return false; } - pending = parse(service, (URL)configs.nextElement(), returned); + pending = parse(service, configs.nextElement(), returned); } - nextName = (String)pending.next(); + nextName = pending.next(); return true; } - public Object next() throws ServiceConfigurationError { + public S next() throws ServiceConfigurationError { if (!hasNext()) { throw new NoSuchElementException(); } @@ -350,10 +350,10 @@ * @see #providers(java.lang.Class) * @see #installedProviders(java.lang.Class) */ - public static Iterator providers(Class service, ClassLoader loader) + public static <S> Iterator<S> providers(Class<S> service, ClassLoader loader) throws ServiceConfigurationError { - return new LazyIterator(service, loader); + return new LazyIterator<S>(service, loader); } @@ -382,7 +382,7 @@ * * @see #providers(java.lang.Class, java.lang.ClassLoader) */ - public static Iterator providers(Class service) + public static <S> Iterator<S> providers(Class<S> service) throws ServiceConfigurationError { ClassLoader cl = Thread.currentThread().getContextClassLoader(); @@ -419,7 +419,7 @@ * * @see #providers(java.lang.Class, java.lang.ClassLoader) */ - public static Iterator installedProviders(Class service) + public static <S> Iterator<S> installedProviders(Class<S> service) throws ServiceConfigurationError { ClassLoader cl = ClassLoader.getSystemClassLoader();
--- a/src/share/classes/sun/misc/Signal.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/misc/Signal.java Mon Oct 22 06:23:01 2018 +0100 @@ -72,8 +72,8 @@ * @since 1.2 */ public final class Signal { - private static Hashtable handlers = new Hashtable(4); - private static Hashtable signals = new Hashtable(4); + private static Hashtable<Signal,SignalHandler> handlers = new Hashtable<>(4); + private static Hashtable<Integer,Signal> signals = new Hashtable<>(4); private int number; private String name; @@ -166,9 +166,9 @@ throw new IllegalArgumentException ("Signal already used by VM or OS: " + sig); } - signals.put(new Integer(sig.number), sig); + signals.put(sig.number, sig); synchronized (handlers) { - SignalHandler oldHandler = (SignalHandler)handlers.get(sig); + SignalHandler oldHandler = handlers.get(sig); handlers.remove(sig); if (newH == 2) { handlers.put(sig, handler); @@ -200,8 +200,8 @@ /* Called by the VM to execute Java signal handlers. */ private static void dispatch(final int number) { - final Signal sig = (Signal)signals.get(new Integer(number)); - final SignalHandler handler = (SignalHandler)handlers.get(sig); + final Signal sig = signals.get(number); + final SignalHandler handler = handlers.get(sig); Runnable runnable = new Runnable () { public void run() {
--- a/src/share/classes/sun/misc/URLClassPath.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/misc/URLClassPath.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. 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 @@ -37,6 +37,7 @@ import java.util.jar.Attributes.Name; import java.net.JarURLConnection; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.net.HttpURLConnection; @@ -53,6 +54,7 @@ import java.security.cert.Certificate; import sun.misc.FileURLMapper; import sun.net.util.URLUtil; +import sun.security.action.GetPropertyAction; /** * This class is used to maintain a search path of URLs for loading classes @@ -66,19 +68,28 @@ private static final boolean DEBUG; private static final boolean DISABLE_JAR_CHECKING; private static final boolean DISABLE_ACC_CHECKING; + private static final boolean DISABLE_CP_URL_CHECK; + private static final boolean DEBUG_CP_URL_CHECK; static { JAVA_VERSION = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("java.version")); + new GetPropertyAction("java.version")); DEBUG = (java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.debug")) != null); + new GetPropertyAction("sun.misc.URLClassPath.debug")) != null); String p = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.disableJarChecking")); + new GetPropertyAction("sun.misc.URLClassPath.disableJarChecking")); DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false; p = AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("jdk.net.URLClassPath.disableRestrictedPermissions")); + new GetPropertyAction("jdk.net.URLClassPath.disableRestrictedPermissions")); DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false; + + // This property will be removed in a later release + p = AccessController.doPrivileged( + new GetPropertyAction("jdk.net.URLClassPath.disableClassPathURLCheck", "true")); + + DISABLE_CP_URL_CHECK = p != null ? p.equals("true") || p.isEmpty() : false; + DEBUG_CP_URL_CHECK = "debug".equals(p); } /* The original search path of URLs. */ @@ -812,8 +823,10 @@ { return jar.getInputStream(entry); } public int getContentLength() { return (int)entry.getSize(); } - public Manifest getManifest() throws IOException - { return jar.getManifest(); }; + public Manifest getManifest() throws IOException { + SharedSecrets.javaUtilJarAccess().ensureInitialization(jar); + return jar.getManifest(); + } public Certificate[] getCertificates() { return entry.getCertificates(); }; public CodeSigner[] getCodeSigners() @@ -1052,11 +1065,51 @@ int i = 0; while (st.hasMoreTokens()) { String path = st.nextToken(); - urls[i] = new URL(base, path); - i++; + URL url = DISABLE_CP_URL_CHECK ? new URL(base, path) : safeResolve(base, path); + if (url != null) { + urls[i] = url; + i++; + } + } + if (i == 0) { + urls = null; + } else if (i != urls.length) { + // Truncate nulls from end of array + urls = Arrays.copyOf(urls, i); } return urls; } + + /* + * Return a URL for the given path resolved against the base URL, or + * null if the resulting URL is invalid. + */ + static URL safeResolve(URL base, String path) { + String child = path.replace(File.separatorChar, '/'); + try { + if (!URI.create(child).isAbsolute()) { + URL url = new URL(base, child); + if (base.getProtocol().equalsIgnoreCase("file")) { + return url; + } else { + String bp = base.getPath(); + String urlp = url.getPath(); + int pos = bp.lastIndexOf('/'); + if (pos == -1) { + pos = bp.length() - 1; + } + if (urlp.regionMatches(0, bp, 0, pos + 1) + && urlp.indexOf("..", pos) == -1) { + return url; + } + } + } + } catch (MalformedURLException | IllegalArgumentException e) {} + if (DEBUG_CP_URL_CHECK) { + System.err.println("Class-Path entry: \"" + path + "\" ignored in JAR file " + base); + } + return null; + } } /*
--- a/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2018, Oracle and/or its affiliates. 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 @@ -2456,6 +2456,8 @@ // doesn't know about proxy. useProxyResponseCode = true; } else { + final URL prevURL = url; + // maintain previous headers, just change the name // of the file we're getting url = locUrl; @@ -2484,6 +2486,14 @@ poster = null; if (!checkReuseConnection()) connect(); + + if (!sameDestination(prevURL, url)) { + // Ensures pre-redirect user-set cookie will not be reset. + // CookieHandler, if any, will be queried to determine + // cookies for redirected URL, if any. + userCookies = null; + userCookies2 = null; + } } else { if (!checkReuseConnection()) connect(); @@ -2506,11 +2516,52 @@ } requests.set("Host", host); } + + if (!sameDestination(prevURL, url)) { + // Redirecting to a different destination will drop any + // security-sensitive headers, regardless of whether + // they are user-set or not. CookieHandler, if any, will be + // queried to determine cookies for redirected URL, if any. + userCookies = null; + userCookies2 = null; + requests.remove("Cookie"); + requests.remove("Cookie2"); + requests.remove("Authorization"); + + // check for preemptive authorization + AuthenticationInfo sauth = + AuthenticationInfo.getServerAuth(url); + if (sauth != null && sauth.supportsPreemptiveAuthorization() ) { + // Sets "Authorization" + requests.setIfNotSet(sauth.getHeaderName(), sauth.getHeaderValue(url,method)); + currentServerCredentials = sauth; + } + } } } return true; } + /* Returns true iff the given URLs have the same host and effective port. */ + private static boolean sameDestination(URL firstURL, URL secondURL) { + assert firstURL.getProtocol().equalsIgnoreCase(secondURL.getProtocol()): + "protocols not equal: " + firstURL + " - " + secondURL; + + if (!firstURL.getHost().equalsIgnoreCase(secondURL.getHost())) + return false; + + int firstPort = firstURL.getPort(); + if (firstPort == -1) + firstPort = firstURL.getDefaultPort(); + int secondPort = secondURL.getPort(); + if (secondPort == -1) + secondPort = secondURL.getDefaultPort(); + if (firstPort != secondPort) + return false; + + return true; + } + /* dummy byte buffer for reading off socket prior to closing */ byte[] cdata = new byte [128];
--- a/src/share/classes/sun/nio/ch/Util.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/nio/ch/Util.java Mon Oct 22 06:23:01 2018 +0100 @@ -363,10 +363,10 @@ try { Class<?> cl = Class.forName("java.nio.DirectByteBuffer"); Constructor ctor = cl.getDeclaredConstructor( - new Class[] { int.class, - long.class, - FileDescriptor.class, - Runnable.class }); + new Class<?>[] { int.class, + long.class, + FileDescriptor.class, + Runnable.class }); ctor.setAccessible(true); directByteBufferConstructor = ctor; } catch (ClassNotFoundException x) { @@ -413,10 +413,10 @@ try { Class<?> cl = Class.forName("java.nio.DirectByteBufferR"); Constructor ctor = cl.getDeclaredConstructor( - new Class[] { int.class, - long.class, - FileDescriptor.class, - Runnable.class }); + new Class<?>[] { int.class, + long.class, + FileDescriptor.class, + Runnable.class }); ctor.setAccessible(true); directByteBufferRConstructor = ctor; } catch (ClassNotFoundException x) {
--- a/src/share/classes/sun/rmi/registry/resources/rmiregistry_it.properties Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/rmi/registry/resources/rmiregistry_it.properties Mon Oct 22 06:23:01 2018 +0100 @@ -1,6 +1,6 @@ # # -# Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2018, Oracle and/or its affiliates. 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 @@ -24,5 +24,5 @@ # questions. # -rmiregistry.usage=Uso: {0} <opzioni> <porta>\n\ndove <opzioni> include:\n -J<flag fase di esecuzione> Passa l''argomento all''interprete java +rmiregistry.usage=Uso: {0} <opzioni> <porta>\n\ndove <opzioni> include:\n -J<flag runtime> Passa l''argomento all''interprete java rmiregistry.port.badnumber=l''argomento della porta, {0}, non \u00E8 un numero.
--- a/src/share/classes/sun/rmi/server/resources/rmid_it.properties Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/rmi/server/resources/rmid_it.properties Mon Oct 22 06:23:01 2018 +0100 @@ -1,6 +1,6 @@ # # -# Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 2018, Oracle and/or its affiliates. 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 @@ -75,7 +75,7 @@ # "rmid", "-port", "-log", "-stop", "-C" and "-J" should not be translated, # because they are syntax -rmid.usage=Uso: {0} <opzioni>\n\ndove <opzioni> include:\n -port <porta> Specifica la porta usata da rmid\n -log <directory> Specifica la directory in cui rmid scrive il log\n -stop Arresta l''invocazione corrente di rmid (per la porta specificata)\n -C<flag fase di esecuzione> Passa l''argomento a ciascun processo figlio (gruppo di attivazione)\n -J<flag fase di esecuzione> Passa l''argomento all''interprete java\n +rmid.usage=Uso: {0} <opzioni>\n\ndove <opzioni> include:\n -port <porta> Specifica la porta usata da rmid\n -log <directory> Specifica la directory in cui rmid scrive il log\n -stop Arresta l''invocazione corrente di rmid (per la porta specificata)\n -C<flag runtime> Passa l''argomento a ciascun processo figlio (gruppo di attivazione)\n -J<flag runtime> Passa l''argomento all''interprete java\n # This means "The currently running activation daemon has been shut down, # and is about to exit". rmid.daemon.shutdown=daemon di attivazione terminato
--- a/src/share/classes/sun/security/ssl/ClientHandshaker.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/ssl/ClientHandshaker.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2018, Oracle and/or its affiliates. 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 @@ -188,19 +188,24 @@ * in the constructor. */ void processMessage(byte type, int messageLen) throws IOException { - if (state >= type - && (type != HandshakeMessage.ht_hello_request)) { - throw new SSLProtocolException( - "Handshake message sequence violation, " + type); - } + + // check the handshake state + List<Byte> ignoredOptStates = handshakeState.check(type); switch (type) { case HandshakeMessage.ht_hello_request: - this.serverHelloRequest(new HelloRequest(input)); + HelloRequest helloRequest = new HelloRequest(input); + handshakeState.update(helloRequest, resumingSession); + this.serverHelloRequest(helloRequest); break; case HandshakeMessage.ht_server_hello: - this.serverHello(new ServerHello(input, messageLen)); + ServerHello serverHello = new ServerHello(input, messageLen); + this.serverHello(serverHello); + + // This handshake state update needs the resumingSession value + // set by serverHello(). + handshakeState.update(serverHello, resumingSession); break; case HandshakeMessage.ht_certificate: @@ -210,7 +215,9 @@ "unexpected server cert chain"); // NOTREACHED } - this.serverCertificate(new CertificateMsg(input)); + CertificateMsg certificateMsg = new CertificateMsg(input); + handshakeState.update(certificateMsg, resumingSession); + this.serverCertificate(certificateMsg); serverKey = session.getPeerCertificates()[0].getPublicKey(); break; @@ -246,15 +253,20 @@ } try { - this.serverKeyExchange(new RSA_ServerKeyExchange(input)); + RSA_ServerKeyExchange rsaSrvKeyExchange = + new RSA_ServerKeyExchange(input); + handshakeState.update(rsaSrvKeyExchange, resumingSession); + this.serverKeyExchange(rsaSrvKeyExchange); } catch (GeneralSecurityException e) { throwSSLException("Server key", e); } break; case K_DH_ANON: try { - this.serverKeyExchange(new DH_ServerKeyExchange( - input, protocolVersion)); + DH_ServerKeyExchange dhSrvKeyExchange = + new DH_ServerKeyExchange(input, protocolVersion); + handshakeState.update(dhSrvKeyExchange, resumingSession); + this.serverKeyExchange(dhSrvKeyExchange); } catch (GeneralSecurityException e) { throwSSLException("Server key", e); } @@ -262,11 +274,14 @@ case K_DHE_DSS: case K_DHE_RSA: try { - this.serverKeyExchange(new DH_ServerKeyExchange( + DH_ServerKeyExchange dhSrvKeyExchange = + new DH_ServerKeyExchange( input, serverKey, clnt_random.random_bytes, svr_random.random_bytes, messageLen, - getLocalSupportedSignAlgs(), protocolVersion)); + getLocalSupportedSignAlgs(), protocolVersion); + handshakeState.update(dhSrvKeyExchange, resumingSession); + this.serverKeyExchange(dhSrvKeyExchange); } catch (GeneralSecurityException e) { throwSSLException("Server key", e); } @@ -275,10 +290,13 @@ case K_ECDHE_RSA: case K_ECDH_ANON: try { - this.serverKeyExchange(new ECDH_ServerKeyExchange + ECDH_ServerKeyExchange ecdhSrvKeyExchange = + new ECDH_ServerKeyExchange (input, serverKey, clnt_random.random_bytes, svr_random.random_bytes, - getLocalSupportedSignAlgs(), protocolVersion)); + getLocalSupportedSignAlgs(), protocolVersion); + handshakeState.update(ecdhSrvKeyExchange, resumingSession); + this.serverKeyExchange(ecdhSrvKeyExchange); } catch (GeneralSecurityException e) { throwSSLException("Server key", e); } @@ -317,6 +335,7 @@ if (debug != null && Debug.isOn("handshake")) { certRequest.print(System.out); } + handshakeState.update(certRequest, resumingSession); if (protocolVersion.v >= ProtocolVersion.TLS12.v) { Collection<SignatureAndHashAlgorithm> peerSignAlgs = @@ -342,33 +361,23 @@ break; case HandshakeMessage.ht_server_hello_done: - this.serverHelloDone(new ServerHelloDone(input)); + ServerHelloDone serverHelloDone = new ServerHelloDone(input); + handshakeState.update(serverHelloDone, resumingSession); + this.serverHelloDone(serverHelloDone); break; case HandshakeMessage.ht_finished: - // A ChangeCipherSpec record must have been received prior to - // reception of the Finished message (RFC 5246, 7.4.9). - if (!receivedChangeCipherSpec()) { - fatalSE(Alerts.alert_handshake_failure, - "Received Finished message before ChangeCipherSpec"); - } + Finished serverFinished = + new Finished(protocolVersion, input, cipherSuite); + handshakeState.update(serverFinished, resumingSession); + this.serverFinished(serverFinished); - this.serverFinished( - new Finished(protocolVersion, input, cipherSuite)); break; default: throw new SSLProtocolException( "Illegal client handshake msg, " + type); } - - // - // Move state machine forward if the message handling - // code didn't already do so - // - if (state < type) { - state = type; - } } /* @@ -386,7 +395,7 @@ // Could be (e.g. at connection setup) that we already // sent the "client hello" but the server's not seen it. // - if (state < HandshakeMessage.ht_client_hello) { + if (!clientHelloDelivered) { if (!secureRenegotiation && !allowUnsafeRenegotiation) { // renegotiation is not allowed. if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) { @@ -609,7 +618,6 @@ // looks fine; resume it, and update the state machine. resumingSession = true; - state = HandshakeMessage.ht_finished - 1; calculateConnectionKeys(session.getMasterSecret()); if (debug != null && Debug.isOn("session")) { System.out.println("%% Server resumed " + session); @@ -708,7 +716,8 @@ session = new SSLSessionImpl(protocolVersion, cipherSuite, getLocalSupportedSignAlgs(), mesg.sessionId, getHostSE(), getPortSE(), - (extendedMasterSecretExt != null)); + (extendedMasterSecretExt != null), + getEndpointIdentificationAlgorithmSE()); setHandshakeSessionSE(session); if (debug != null && Debug.isOn("handshake")) { System.out.println("** " + cipherSuite); @@ -894,6 +903,7 @@ m1.print(System.out); } m1.write(output); + handshakeState.update(m1, resumingSession); } } @@ -1026,6 +1036,7 @@ } m2.write(output); + handshakeState.update(m2, resumingSession); /* * THIRD, send a "change_cipher_spec" record followed by the @@ -1130,6 +1141,7 @@ m3.print(System.out); } m3.write(output); + handshakeState.update(m3, resumingSession); output.doHashes(); } else { if (protocolVersion.v >= ProtocolVersion.TLS12.v) { @@ -1191,6 +1203,8 @@ if (resumingSession) { input.digestNow(); sendChangeCipherAndFinish(true); + } else { + handshakeFinished = true; } session.setLastAccessedTime(System.currentTimeMillis()); @@ -1236,13 +1250,6 @@ if (secureRenegotiation) { clientVerifyData = mesg.getVerifyData(); } - - /* - * Update state machine so server MUST send 'finished' next. - * (In "long" handshake case; in short case, we're responding - * to its message.) - */ - state = HandshakeMessage.ht_finished - 1; } @@ -1348,6 +1355,24 @@ } } + // ensure that the endpoint identification algorithm matches the + // one in the session + String identityAlg = getEndpointIdentificationAlgorithmSE(); + if (session != null && identityAlg != null) { + + String sessionIdentityAlg = + session.getEndpointIdentificationAlgorithm(); + if (!Objects.equals(identityAlg, sessionIdentityAlg)) { + + if (debug != null && Debug.isOn("session")) { + System.out.println("%% can't resume, endpoint id" + + " algorithm does not match, requested: " + + identityAlg + ", cached: " + sessionIdentityAlg); + } + session = null; + } + } + if (session != null) { if (debug != null) { if (Debug.isOn("handshake") || Debug.isOn("session")) {
--- a/src/share/classes/sun/security/ssl/HandshakeMessage.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/ssl/HandshakeMessage.java Mon Oct 22 06:23:01 2018 +0100 @@ -89,6 +89,8 @@ static final byte ht_finished = 20; + static final byte ht_not_applicable = -1; // N/A + /* Class and subclass dynamic debugging support */ public static final Debug debug = Debug.getInstance("ssl"); @@ -234,6 +236,7 @@ protocolVersion = ProtocolVersion.valueOf(s.getInt8(), s.getInt8()); clnt_random = new RandomCookie(s); sessionId = new SessionId(s.getBytes8()); + sessionId.checkLength(protocolVersion); cipherSuites = new CipherSuiteList(s); compression_methods = s.getBytes8(); if (messageLength() != messageLength) { @@ -353,6 +356,7 @@ input.getInt8()); svr_random = new RandomCookie(input); sessionId = new SessionId(input.getBytes8()); + sessionId.checkLength(protocolVersion); cipherSuite = CipherSuite.valueOf(input.getInt8(), input.getInt8()); compression_method = (byte)input.getInt8(); if (messageLength() != messageLength) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/security/ssl/HandshakeStateManager.java Mon Oct 22 06:23:01 2018 +0100 @@ -0,0 +1,765 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.ssl; + +import java.util.Collections; +import java.util.List; +import java.util.LinkedList; +import java.util.HashMap; +import javax.net.ssl.SSLProtocolException; + +import static sun.security.ssl.CipherSuite.KeyExchange; +import static sun.security.ssl.CipherSuite.KeyExchange.*; +import static sun.security.ssl.HandshakeStateManager.HandshakeState.*; +import static sun.security.ssl.HandshakeMessage.*; + +/* + * Handshake state manager. + * + * Messages flow for a full handshake: + * + * - - + * | HelloRequest (No.0, RFC 5246) [*] | + * | <-------------------------------------------- | + * | | + * | ClientHello (No.1, RFC 5246) | + * | --------------------------------------------> | + * | | + * C | ServerHello (No.2, RFC 5246) | S + * L | SupplementalData (No.23, RFC4680) [*] | E + * I | Certificate (No.11, RFC 5246) [*] | R + * E | CertificateStatus (No.22, RFC 6066) [*] | V + * N | ServerKeyExchange (No.12, RFC 5246) [*] | E + * T | CertificateRequest (No.13, RFC 5246) [*] | R + * | ServerHelloDone (No.14, RFC 5246) | + * | <-------------------------------------------- | + * | | + * | SupplementalData (No.23, RFC4680) [*] | + * | Certificate (No.11, RFC 5246) [*] Or | + * | CertificateURL (No.21, RFC6066) [*] | + * | ClientKeyExchange (No.16, RFC 5246) | + * | CertificateVerify (No.15, RFC 5246) [*] | + * | [ChangeCipherSpec] (RFC 5246) | + * | Finished (No.20, RFC 5246) | + * | --------------------------------------------> | + * | | + * | NewSessionTicket (No.4, RFC4507) [*] | + * | [ChangeCipherSpec] (RFC 5246) | + * | Finished (No.20, RFC 5246) | + * | <-------------------------------------------- | + * - - + * [*] Indicates optional or situation-dependent messages that are not + * always sent. + * + * Message flow for an abbreviated handshake: + * - - + * | ClientHello (No.1, RFC 5246) | + * | --------------------------------------------> | + * | | + * C | ServerHello (No.2, RFC 5246) | S + * L | NewSessionTicket (No.4, RFC4507) [*] | E + * I | [ChangeCipherSpec] (RFC 5246) | R + * E | Finished (No.20, RFC 5246) | V + * N | <-------------------------------------------- | E + * T | | R + * | [ChangeCipherSpec] (RFC 5246) | + * | Finished (No.20, RFC 5246) | + * | --------------------------------------------> | + * - - + * + * + * State machine of handshake states: + * + * +--------------+ + * START -----> | HelloRequest | + * | +--------------+ + * | | + * v v + * +---------------------+ --> +---------------------+ + * | ClientHello | | HelloVerifyRequest | + * +---------------------+ <-- +---------------------+ + * | + * | + * ========================================================================= + * | + * v + * +---------------------+ + * | ServerHello | ----------------------------------+------+ + * +---------------------+ --> +-------------------------+ | | + * | | Server SupplementalData | | | + * | +-------------------------+ | | + * | | | | + * v v | | + * +---------------------+ | | + * +---- | Server Certificate | | | + * | +---------------------+ | | + * | | | | + * | | +--------------------+ | | + * | +-> | CertificateStatus | | | + * | | +--------------------+ v | + * | | | | +--------------------+ | + * | v v +--> | ServerKeyExchange | | + * | +---------------------+ | +--------------------+ | + * | | CertificateRequest | | | | + * | +---------------------+ <-+---------+ | + * | | | | | + * v v | | | + * +---------------------+ <-------+ | | + * | ServerHelloDone | <-----------------+ | + * +---------------------+ | + * | | | + * | | | + * | | | + * ========================================================================= + * | | | + * | v | + * | +-------------------------+ | + * | | Client SupplementalData | --------------+ | + * | +-------------------------+ | | + * | | | | + * | v | | + * | +--------------------+ | | + * +-> | Client Certificate | ALT. | | + * | +--------------------+----------------+ | | + * | | CertificateURL | | | + * | +----------------+ | | + * v | | + * +-------------------+ <------------------------+ | + * | ClientKeyExchange | | + * +-------------------+ | + * | | | + * | v | + * | +-------------------+ | + * | | CertificateVerify | | + * | +-------------------+ | + * | | | + * v v | + * +-------------------------+ | + * | Client ChangeCipherSpec | <---------------+ | + * +-------------------------+ | | + * | | | + * v | | + * +-----------------+ (abbreviated) | | + * | Client Finished | -------------> END | | + * +-----------------+ (Abbreviated handshake) | | + * | | | + * | (full) | | + * | | | + * ================================ | | + * | | | + * | ================================ + * | | | + * v | | + * +------------------+ | (abbreviated) | + * | NewSessionTicket | <--------------------------------+ + * +------------------+ | | + * | | | + * v | | + * +-------------------------+ | (abbreviated) | + * | Server ChangeCipherSpec | <-------------------------------------+ + * +-------------------------+ | + * | | + * v | + * +-----------------+ (abbreviated) | + * | Server Finished | -------------------------+ + * +-----------------+ + * | (full) + * v + * END (Full handshake) + * + * + * The scenarios of the use of this class: + * 1. Create an instance of HandshakeStateManager during the initializtion + * handshake. + * 2. If receiving a handshake message, call HandshakeStateManager.check() + * to make sure that the message is of the expected handshake type. And + * then call HandshakeStateManager.update() in case handshake states may + * be impacted by this new incoming handshake message. + * 3. On delivering a handshake message, call HandshakeStateManager.update() + * in case handshake states may by thie new outgoing handshake message. + * 4. On receiving and delivering ChangeCipherSpec message, call + * HandshakeStateManager.changeCipherSpec() to check the present sequence + * of this message, and update the states if necessary. + */ +final class HandshakeStateManager { + // upcoming handshake states. + private LinkedList<HandshakeState> upcomingStates; + private LinkedList<HandshakeState> alternatives; + + private static final boolean debugIsOn; + + private static final HashMap<Byte, String> handshakeTypes; + + static { + debugIsOn = (Handshaker.debug != null) && + Debug.isOn("handshake") && Debug.isOn("verbose"); + handshakeTypes = new HashMap<>(8); + + handshakeTypes.put(ht_hello_request, "hello_request"); + handshakeTypes.put(ht_client_hello, "client_hello"); + handshakeTypes.put(ht_server_hello, "server_hello"); + handshakeTypes.put(ht_certificate, "certificate"); + handshakeTypes.put(ht_server_key_exchange, "server_key_exchange"); + handshakeTypes.put(ht_server_hello_done, "server_hello_done"); + handshakeTypes.put(ht_certificate_verify, "certificate_verify"); + handshakeTypes.put(ht_client_key_exchange, "client_key_exchange"); + handshakeTypes.put(ht_finished, "finished"); + } + + HandshakeStateManager() { + this.upcomingStates = new LinkedList<>(); + this.alternatives = new LinkedList<>(); + } + + // + // enumation of handshake type + // + static enum HandshakeState { + HS_HELLO_REQUEST( + "hello_request", + HandshakeMessage.ht_hello_request), + HS_CLIENT_HELLO( + "client_hello", + HandshakeMessage.ht_client_hello), + HS_SERVER_HELLO( + "server_hello", + HandshakeMessage.ht_server_hello), + HS_SERVER_CERTIFICATE( + "server certificate", + HandshakeMessage.ht_certificate), + HS_SERVER_KEY_EXCHANGE( + "server_key_exchange", + HandshakeMessage.ht_server_key_exchange, true), + HS_CERTIFICATE_REQUEST( + "certificate_request", + HandshakeMessage.ht_certificate_request, true), + HS_SERVER_HELLO_DONE( + "server_hello_done", + HandshakeMessage.ht_server_hello_done), + HS_CLIENT_CERTIFICATE( + "client certificate", + HandshakeMessage.ht_certificate, true), + HS_CLIENT_KEY_EXCHANGE( + "client_key_exchange", + HandshakeMessage.ht_client_key_exchange), + HS_CERTIFICATE_VERIFY( + "certificate_verify", + HandshakeMessage.ht_certificate_verify, true), + HS_CLIENT_CHANGE_CIPHER_SPEC( + "client change_cipher_spec", + HandshakeMessage.ht_not_applicable), + HS_CLIENT_FINISHED( + "client finished", + HandshakeMessage.ht_finished), + HS_SERVER_CHANGE_CIPHER_SPEC( + "server change_cipher_spec", + HandshakeMessage.ht_not_applicable), + HS_SERVER_FINISHED( + "server finished", + HandshakeMessage.ht_finished); + + final String description; + final byte handshakeType; + final boolean isOptional; + + HandshakeState(String description, byte handshakeType) { + this.description = description; + this.handshakeType = handshakeType; + this.isOptional = false; + } + + HandshakeState(String description, + byte handshakeType, boolean isOptional) { + + this.description = description; + this.handshakeType = handshakeType; + this.isOptional = isOptional; + } + + public String toString() { + return description + "[" + handshakeType + "]" + + (isOptional ? "(optional)" : ""); + } + } + + boolean isEmpty() { + return upcomingStates.isEmpty(); + } + + List<Byte> check(byte handshakeType) throws SSLProtocolException { + List<Byte> ignoredOptional = new LinkedList<>(); + String exceptionMsg = + "Handshake message sequence violation, " + handshakeType; + + if (debugIsOn) { + System.out.println( + "check handshake state: " + toString(handshakeType)); + } + + if (upcomingStates.isEmpty()) { + // Is it a kickstart message? + if ((handshakeType != HandshakeMessage.ht_hello_request) && + (handshakeType != HandshakeMessage.ht_client_hello)) { + throw new SSLProtocolException( + "Handshake message sequence violation, " + handshakeType); + } + + // It is a kickstart message. + return Collections.emptyList(); + } + + // Ignore the checking for HelloRequest messages as they + // may be sent by the server at any time. + if (handshakeType == HandshakeMessage.ht_hello_request) { + return Collections.emptyList(); + } + + for (HandshakeState handshakeState : upcomingStates) { + if (handshakeState.handshakeType == handshakeType) { + // It's the expected next handshake type. + return ignoredOptional; + } + + if (handshakeState.isOptional) { + ignoredOptional.add(handshakeState.handshakeType); + continue; + } else { + for (HandshakeState alternative : alternatives) { + if (alternative.handshakeType == handshakeType) { + return ignoredOptional; + } + + if (alternative.isOptional) { + continue; + } else { + throw new SSLProtocolException(exceptionMsg); + } + } + } + throw new SSLProtocolException(exceptionMsg); + } + + // Not an expected Handshake message. + throw new SSLProtocolException( + "Handshake message sequence violation, " + handshakeType); + } + + void update(HandshakeMessage handshakeMessage, + boolean isAbbreviated) throws SSLProtocolException { + + byte handshakeType = (byte)handshakeMessage.messageType(); + String exceptionMsg = + "Handshake message sequence violation, " + handshakeType; + + if (debugIsOn) { + System.out.println( + "update handshake state: " + toString(handshakeType)); + } + + boolean hasPresentState = false; + switch (handshakeType) { + case HandshakeMessage.ht_hello_request: + // + // State machine: + // PRESENT: START + // TO : ClientHello + // + + // No old state to update. + + // Add the upcoming states. + if (!upcomingStates.isEmpty()) { + // A ClientHello message should be followed. + upcomingStates.add(HS_CLIENT_HELLO); + + } // Otherwise, ignore this HelloRequest message. + + break; + + case HandshakeMessage.ht_client_hello: + // + // State machine: + // PRESENT: START + // HS_CLIENT_HELLO + // TO : HS_SERVER_HELLO + // + + // Check and update the present state. + if (!upcomingStates.isEmpty()) { + // The current state should be HS_CLIENT_HELLO. + HandshakeState handshakeState = upcomingStates.pop(); + if (handshakeState != HS_CLIENT_HELLO) { + throw new SSLProtocolException(exceptionMsg); + } + } + + // Add the upcoming states. + ClientHello clientHello = (ClientHello)handshakeMessage; + upcomingStates.add(HS_SERVER_HELLO); + + break; + + case HandshakeMessage.ht_server_hello: + // + // State machine: + // PRESENT: HS_SERVER_HELLO + // TO : + // Full handshake state stacks + // (ServerHello Flight) + // HS_SERVER_SUPPLEMENTAL_DATA [optional] + // --> HS_SERVER_CERTIFICATE [optional] + // --> HS_CERTIFICATE_STATUS [optional] + // --> HS_SERVER_KEY_EXCHANGE [optional] + // --> HS_CERTIFICATE_REQUEST [optional] + // --> HS_SERVER_HELLO_DONE + // (Client ClientKeyExchange Flight) + // --> HS_CLIENT_SUPPLEMENTAL_DATA [optional] + // --> HS_CLIENT_CERTIFICATE or + // HS_CERTIFICATE_URL + // --> HS_CLIENT_KEY_EXCHANGE + // --> HS_CERTIFICATE_VERIFY [optional] + // --> HS_CLIENT_CHANGE_CIPHER_SPEC + // --> HS_CLIENT_FINISHED + // (Server Finished Flight) + // --> HS_CLIENT_SUPPLEMENTAL_DATA [optional] + // + // Abbreviated handshake state stacks + // (Server Finished Flight) + // HS_NEW_SESSION_TICKET + // --> HS_SERVER_CHANGE_CIPHER_SPEC + // --> HS_SERVER_FINISHED + // (Client Finished Flight) + // --> HS_CLIENT_CHANGE_CIPHER_SPEC + // --> HS_CLIENT_FINISHED + // + // Note that this state may have an alternative option. + + // Check and update the present state. + if (!upcomingStates.isEmpty()) { + // The current state should be HS_SERVER_HELLO + HandshakeState handshakeState = upcomingStates.pop(); + HandshakeState alternative = null; + if (!alternatives.isEmpty()) { + alternative = alternatives.pop(); + } + + if ((handshakeState != HS_SERVER_HELLO) && + (alternative != HS_SERVER_HELLO)) { + throw new SSLProtocolException(exceptionMsg); + } + } else { + // No present state. + throw new SSLProtocolException(exceptionMsg); + } + + // Add the upcoming states. + ServerHello serverHello = (ServerHello)handshakeMessage; + HelloExtensions hes = serverHello.extensions; + + + // Not support SessionTicket extension yet. + // + // boolean hasSessionTicketExt = + // (hes.get(HandshakeMessage.ht_new_session_ticket) != null); + + if (isAbbreviated) { + // Not support SessionTicket extension yet. + // + // // Mandatory NewSessionTicket message + // if (hasSessionTicketExt) { + // upcomingStates.add(HS_NEW_SESSION_TICKET); + // } + + // Mandatory server ChangeCipherSpec and Finished messages + upcomingStates.add(HS_SERVER_CHANGE_CIPHER_SPEC); + upcomingStates.add(HS_SERVER_FINISHED); + + // Mandatory client ChangeCipherSpec and Finished messages + upcomingStates.add(HS_CLIENT_CHANGE_CIPHER_SPEC); + upcomingStates.add(HS_CLIENT_FINISHED); + } else { + // Not support SupplementalData extension yet. + // + // boolean hasSupplementalDataExt = + // (hes.get(HandshakeMessage.ht_supplemental_data) != null); + + // Not support CertificateURL extension yet. + // + // boolean hasCertificateUrlExt = + // (hes.get(ExtensionType EXT_CLIENT_CERTIFICATE_URL) + // != null); + + // Not support SupplementalData extension yet. + // + // // Optional SupplementalData message + // if (hasSupplementalDataExt) { + // upcomingStates.add(HS_SERVER_SUPPLEMENTAL_DATA); + // } + + // Need server Certificate message or not? + KeyExchange keyExchange = serverHello.cipherSuite.keyExchange; + if ((keyExchange != K_KRB5) && + (keyExchange != K_KRB5_EXPORT) && + (keyExchange != K_DH_ANON) && + (keyExchange != K_ECDH_ANON)) { + // Mandatory Certificate message + upcomingStates.add(HS_SERVER_CERTIFICATE); + } + + // Need ServerKeyExchange message or not? + if ((keyExchange == K_RSA_EXPORT) || + (keyExchange == K_DHE_RSA) || + (keyExchange == K_DHE_DSS) || + (keyExchange == K_DH_ANON) || + (keyExchange == K_ECDHE_RSA) || + (keyExchange == K_ECDHE_ECDSA) || + (keyExchange == K_ECDH_ANON)) { + // Optional ServerKeyExchange message + upcomingStates.add(HS_SERVER_KEY_EXCHANGE); + } + + // Optional CertificateRequest message + upcomingStates.add(HS_CERTIFICATE_REQUEST); + + // Mandatory ServerHelloDone message + upcomingStates.add(HS_SERVER_HELLO_DONE); + + // Not support SupplementalData extension yet. + // + // // Optional SupplementalData message + // if (hasSupplementalDataExt) { + // upcomingStates.add(HS_CLIENT_SUPPLEMENTAL_DATA); + // } + + // Optional client Certificate message + upcomingStates.add(HS_CLIENT_CERTIFICATE); + + // Not support CertificateURL extension yet. + // + // // Alternative CertificateURL message, optional too. + // // + // // Please put CertificateURL rather than Certificate + // // message in the alternatives list. So that we can + // // simplify the process of this alternative pair later. + // if (hasCertificateUrlExt) { + // alternatives.add(HS_CERTIFICATE_URL); + // } + + // Mandatory ClientKeyExchange message + upcomingStates.add(HS_CLIENT_KEY_EXCHANGE); + + // Optional CertificateVerify message + upcomingStates.add(HS_CERTIFICATE_VERIFY); + + // Mandatory client ChangeCipherSpec and Finished messages + upcomingStates.add(HS_CLIENT_CHANGE_CIPHER_SPEC); + upcomingStates.add(HS_CLIENT_FINISHED); + + // Not support SessionTicket extension yet. + // + // // Mandatory NewSessionTicket message + // if (hasSessionTicketExt) { + // upcomingStates.add(HS_NEW_SESSION_TICKET); + // } + + // Mandatory server ChangeCipherSpec and Finished messages + upcomingStates.add(HS_SERVER_CHANGE_CIPHER_SPEC); + upcomingStates.add(HS_SERVER_FINISHED); + } + + break; + + case HandshakeMessage.ht_certificate: + // + // State machine: + // PRESENT: HS_CERTIFICATE_URL or + // HS_CLIENT_CERTIFICATE + // TO : HS_CLIENT_KEY_EXCHANGE + // + // Or + // + // PRESENT: HS_SERVER_CERTIFICATE + // TO : HS_CERTIFICATE_STATUS [optional] + // HS_SERVER_KEY_EXCHANGE [optional] + // HS_CERTIFICATE_REQUEST [optional] + // HS_SERVER_HELLO_DONE + // + // Note that this state may have an alternative option. + + // Check and update the present state. + while (!upcomingStates.isEmpty()) { + HandshakeState handshakeState = upcomingStates.pop(); + if (handshakeState.handshakeType == handshakeType) { + hasPresentState = true; + + // The current state should be HS_CLIENT_CERTIFICATE or + // HS_SERVER_CERTIFICATE. + // + // Note that we won't put HS_CLIENT_CERTIFICATE into + // the alternative list. + if ((handshakeState != HS_CLIENT_CERTIFICATE) && + (handshakeState != HS_SERVER_CERTIFICATE)) { + throw new SSLProtocolException(exceptionMsg); + } + + // Is it an expected client Certificate message? + boolean isClientMessage = false; + if (!upcomingStates.isEmpty()) { + // If the next expected message is ClientKeyExchange, + // this one should be an expected client Certificate + // message. + HandshakeState nextState = upcomingStates.getFirst(); + if (nextState == HS_CLIENT_KEY_EXCHANGE) { + isClientMessage = true; + } + } + + if (isClientMessage) { + if (handshakeState != HS_CLIENT_CERTIFICATE) { + throw new SSLProtocolException(exceptionMsg); + } + + // Not support CertificateURL extension yet. + /******************************************* + // clear up the alternatives list + if (!alternatives.isEmpty()) { + HandshakeState alternative = alternatives.pop(); + + if (alternative != HS_CERTIFICATE_URL) { + throw new SSLProtocolException(exceptionMsg); + } + } + ********************************************/ + } else { + if ((handshakeState != HS_SERVER_CERTIFICATE)) { + throw new SSLProtocolException(exceptionMsg); + } + } + + break; + } else if (!handshakeState.isOptional) { + throw new SSLProtocolException(exceptionMsg); + } // Otherwise, looking for next state track. + } + + // No present state. + if (!hasPresentState) { + throw new SSLProtocolException(exceptionMsg); + } + + // no new upcoming states. + + break; + + default: + // Check and update the present state. + while (!upcomingStates.isEmpty()) { + HandshakeState handshakeState = upcomingStates.pop(); + if (handshakeState.handshakeType == handshakeType) { + hasPresentState = true; + break; + } else if (!handshakeState.isOptional) { + throw new SSLProtocolException(exceptionMsg); + } // Otherwise, looking for next state track. + } + + // No present state. + if (!hasPresentState) { + throw new SSLProtocolException(exceptionMsg); + } + + // no new upcoming states. + } + + if (debugIsOn) { + for (HandshakeState handshakeState : upcomingStates) { + System.out.println( + "upcoming handshake states: " + handshakeState); + } + for (HandshakeState handshakeState : alternatives) { + System.out.println( + "upcoming handshake alternative state: " + handshakeState); + } + } + } + + void changeCipherSpec(boolean isInput, + boolean isClient) throws SSLProtocolException { + + if (debugIsOn) { + System.out.println( + "update handshake state: change_cipher_spec"); + } + + String exceptionMsg = "ChangeCipherSpec message sequence violation"; + + HandshakeState expectedState; + if ((isClient && isInput) || (!isClient && !isInput)) { + expectedState = HS_SERVER_CHANGE_CIPHER_SPEC; + } else { + expectedState = HS_CLIENT_CHANGE_CIPHER_SPEC; + } + + boolean hasPresentState = false; + + // Check and update the present state. + while (!upcomingStates.isEmpty()) { + HandshakeState handshakeState = upcomingStates.pop(); + if (handshakeState == expectedState) { + hasPresentState = true; + break; + } else if (!handshakeState.isOptional) { + throw new SSLProtocolException(exceptionMsg); + } // Otherwise, looking for next state track. + } + + // No present state. + if (!hasPresentState) { + throw new SSLProtocolException(exceptionMsg); + } + + // no new upcoming states. + + if (debugIsOn) { + for (HandshakeState handshakeState : upcomingStates) { + System.out.println( + "upcoming handshake states: " + handshakeState); + } + for (HandshakeState handshakeState : alternatives) { + System.out.println( + "upcoming handshake alternative state: " + handshakeState); + } + } + } + + private static String toString(byte handshakeType) { + String s = handshakeTypes.get(handshakeType); + if (s == null) { + s = "unknown"; + } + return (s + "[" + handshakeType + "]"); + } +}
--- a/src/share/classes/sun/security/ssl/Handshaker.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/ssl/Handshaker.java Mon Oct 22 06:23:01 2018 +0100 @@ -113,10 +113,14 @@ HandshakeHash handshakeHash; HandshakeInStream input; HandshakeOutStream output; - int state; SSLContextImpl sslContext; RandomCookie clnt_random, svr_random; SSLSessionImpl session; + HandshakeStateManager handshakeState; + boolean clientHelloDelivered; + boolean serverHelloRequested; + boolean handshakeActivated; + boolean handshakeFinished; // current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL CipherSuite cipherSuite; @@ -130,10 +134,6 @@ // True if it's OK to start a new SSL session boolean enableNewSession; - // True if session keys have been calculated and the caller may receive - // and process a ChangeCipherSpec message - private boolean sessKeysCalculated; - // Temporary storage for the individual keys. Set by // calculateConnectionKeys() and cleared once the ciphers are // activated. @@ -254,9 +254,13 @@ this.secureRenegotiation = secureRenegotiation; this.clientVerifyData = clientVerifyData; this.serverVerifyData = serverVerifyData; - enableNewSession = true; - invalidated = false; - sessKeysCalculated = false; + this.enableNewSession = true; + this.invalidated = false; + this.handshakeState = new HandshakeStateManager(); + this.clientHelloDelivered = false; + this.serverHelloRequested = false; + this.handshakeActivated = false; + this.handshakeFinished = false; setCipherSuite(CipherSuite.C_NULL); setEnabledProtocols(enabledProtocols); @@ -266,22 +270,6 @@ } else { // engine != null algorithmConstraints = new SSLAlgorithmConstraints(engine, true); } - - - // - // In addition to the connection state machine, controlling - // how the connection deals with the different sorts of records - // that get sent (notably handshake transitions!), there's - // also a handshaking state machine that controls message - // sequencing. - // - // It's a convenient artifact of the protocol that this can, - // with only a couple of minor exceptions, be driven by the - // type constant for the last message seen: except for the - // client's cert verify, those constants are in a convenient - // order to drastically simplify state machine checking. - // - state = -2; // initialized but not activated } /* @@ -377,14 +365,6 @@ } } - final boolean receivedChangeCipherSpec() { - if (conn != null) { - return conn.receivedChangeCipherSpec(); - } else { - return engine.receivedChangeCipherSpec(); - } - } - String getEndpointIdentificationAlgorithmSE() { SSLParameters paras; if (conn != null) { @@ -544,8 +524,7 @@ engine.outputRecord.setHelloVersion(helloVersion); } - // move state to activated - state = -1; + handshakeActivated = true; } /** @@ -855,10 +834,9 @@ * this freshly created session can become the current one. */ boolean isDone() { - return state == HandshakeMessage.ht_finished; + return started() && handshakeState.isEmpty() && handshakeFinished; } - /* * Returns the session which was created through this * handshake sequence ... should be called after isDone() @@ -963,6 +941,13 @@ return; } + // Set the flags in the message receiving side. + if (messageType == HandshakeMessage.ht_client_hello) { + clientHelloDelivered = true; + } else if (messageType == HandshakeMessage.ht_hello_request) { + serverHelloRequested = true; + } + /* * Process the message. We require * that processMessage() consumes the entire message. In @@ -997,15 +982,14 @@ * In activated state, the handshaker may not send any messages out. */ boolean activated() { - return state >= -1; + return handshakeActivated; } /** * Returns true iff the handshaker has sent any messages. */ boolean started() { - return state >= 0; // 0: HandshakeMessage.ht_hello_request - // 1: HandshakeMessage.ht_client_hello + return (serverHelloRequested || clientHelloDelivered); } @@ -1015,11 +999,13 @@ * the subclass returns. NOP if handshaking's already started. */ void kickstart() throws IOException { - if (state >= 0) { + if ((isClient && clientHelloDelivered) || + (!isClient && serverHelloRequested)) { return; } HandshakeMessage m = getKickstartMessage(); + handshakeState.update(m, resumingSession); if (debug != null && Debug.isOn("handshake")) { m.print(System.out); @@ -1027,7 +1013,14 @@ m.write(output); output.flush(); - state = m.messageType(); + // Set the flags in the message delivering side. + int handshakeType = m.messageType(); + if (handshakeType == HandshakeMessage.ht_hello_request) { + serverHelloRequested = true; + } else { // HandshakeMessage.ht_client_hello + clientHelloDelivered = true; + } + } /** @@ -1059,16 +1052,6 @@ output.flush(); // i.e. handshake data - /* - * The write cipher state is protected by the connection write lock - * so we must grab it while making the change. We also - * make sure no writes occur between sending the ChangeCipherSpec - * message, installing the new cipher state, and sending the - * Finished message. - * - * We already hold SSLEngine/SSLSocket "this" by virtue - * of this being called from the readRecord code. - */ OutputRecord r; if (conn != null) { r = new OutputRecord(Record.ct_change_cipher_spec); @@ -1079,14 +1062,27 @@ r.setVersion(protocolVersion); r.write(1); // single byte of data + /* + * The write cipher state is protected by the connection write lock + * so we must grab it while making the change. We also + * make sure no writes occur between sending the ChangeCipherSpec + * message, installing the new cipher state, and sending the + * Finished message. + * + * We already hold SSLEngine/SSLSocket "this" by virtue + * of this being called from the readRecord code. + */ if (conn != null) { conn.writeLock.lock(); try { + handshakeState.changeCipherSpec(false, isClient); conn.writeRecord(r); conn.changeWriteCiphers(); if (debug != null && Debug.isOn("handshake")) { mesg.print(System.out); } + + handshakeState.update(mesg, resumingSession); mesg.write(output); output.flush(); } finally { @@ -1094,19 +1090,28 @@ } } else { synchronized (engine.writeLock) { + handshakeState.changeCipherSpec(false, isClient); engine.writeRecord((EngineOutputRecord)r); engine.changeWriteCiphers(); if (debug != null && Debug.isOn("handshake")) { mesg.print(System.out); } + + handshakeState.update(mesg, resumingSession); mesg.write(output); - if (lastMessage) { output.setFinishedMsg(); } output.flush(); } } + if (lastMessage) { + handshakeFinished = true; + } + } + + void receiveChangeCipherSpec() throws IOException { + handshakeState.changeCipherSpec(true, isClient); } /* @@ -1274,10 +1279,6 @@ throw new ProviderException(e); } - // Mark a flag that allows outside entities (like SSLSocket/SSLEngine) - // determine if a ChangeCipherSpec message could be processed. - sessKeysCalculated = true; - // // Dump the connection keys as they're generated. // @@ -1328,15 +1329,6 @@ } } - /** - * Return whether or not the Handshaker has derived session keys for - * this handshake. This is used for determining readiness to process - * an incoming ChangeCipherSpec message. - */ - boolean sessionKeysCalculated() { - return sessKeysCalculated; - } - private static void printHex(HexDumpEncoder dump, byte[] bytes) { if (bytes == null) { System.out.println("(key bytes not available)");
--- a/src/share/classes/sun/security/ssl/SSLEngineImpl.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/ssl/SSLEngineImpl.java Mon Oct 22 06:23:01 2018 +0100 @@ -212,11 +212,6 @@ static final byte clauth_required = 2; /* - * Flag indicating that the engine has received a ChangeCipherSpec message. - */ - private boolean receivedCCS; - - /* * Flag indicating if the next record we receive MUST be a Finished * message. Temporarily set during the handshake to ensure that * a change cipher spec message is followed by a finished message. @@ -365,7 +360,6 @@ */ roleIsServer = true; connectionState = cs_START; - receivedCCS = false; /* * default read and write side cipher and MAC support @@ -506,7 +500,6 @@ return HandshakeStatus.NEED_UNWRAP; } // else not handshaking } - return HandshakeStatus.NOT_HANDSHAKING; } } @@ -570,14 +563,6 @@ * Synchronized on "this" from readRecord. */ private void changeReadCiphers() throws SSLException { - if (connectionState != cs_HANDSHAKE - && connectionState != cs_RENEGOTIATE) { - throw new SSLProtocolException( - "State error, change cipher specs"); - } - - // ... create decompressor - CipherBox oldCipher = readCipher; try { @@ -761,6 +746,10 @@ synchronized (unwrapLock) { return readNetRecord(ea); } + } catch (SSLProtocolException spe) { + // may be an unexpected handshake message + fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe); + return null; // make compiler happy } catch (Exception e) { /* * Don't reset position so it looks like we didn't @@ -985,6 +974,7 @@ * session (new keys exchanged) with just this connection * in it. */ + initHandshaker(); if (!handshaker.activated()) { // prior to handshaking, activate the handshake @@ -1008,7 +998,6 @@ if (handshaker.invalidated) { handshaker = null; - receivedCCS = false; // if state is cs_RENEGOTIATE, revert it to cs_DATA if (connectionState == cs_RENEGOTIATE) { connectionState = cs_DATA; @@ -1027,8 +1016,6 @@ } handshaker = null; connectionState = cs_DATA; - receivedCCS = false; - // No handshakeListeners here. That's a // SSLSocket thing. } else if (handshaker.taskOutstanding()) { @@ -1066,14 +1053,11 @@ case Record.ct_change_cipher_spec: if ((connectionState != cs_HANDSHAKE - && connectionState != cs_RENEGOTIATE) - || !handshaker.sessionKeysCalculated() - || receivedCCS) { + && connectionState != cs_RENEGOTIATE)) { // For the CCS message arriving in the wrong state fatal(Alerts.alert_unexpected_message, "illegal change cipher spec msg, conn state = " - + connectionState + ", handshake state = " - + handshaker.state); + + connectionState); } else if (inputRecord.available() != 1 || inputRecord.read() != 1) { // For structural/content issues with the CCS @@ -1081,11 +1065,6 @@ "Malformed change cipher spec msg"); } - // Once we've received CCS, update the flag. - // If the remote endpoint sends it again in this handshake - // we won't process it. - receivedCCS = true; - // // The first message after a change_cipher_spec // record MUST be a "Finished" handshake record, @@ -1093,6 +1072,7 @@ // to be checked by a minor tweak to the state // machine. // + handshaker.receiveChangeCipherSpec(); changeReadCiphers(); // next message MUST be a finished message expectingFinished = true; @@ -1131,7 +1111,6 @@ } } // synchronized (this) } - return hsStatus; } @@ -1164,6 +1143,10 @@ synchronized (wrapLock) { return writeAppRecord(ea); } + } catch (SSLProtocolException spe) { + // may be an unexpected handshake message + fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe); + return null; // make compiler happy } catch (Exception e) { ea.resetPos(); @@ -1191,7 +1174,6 @@ * See if the handshaker needs to report back some SSLException. */ checkTaskThrown(); - /* * short circuit if we're closed/closing. */ @@ -1213,7 +1195,6 @@ * without trying to wrap anything. */ hsStatus = getHSStatus(null); - if (hsStatus == HandshakeStatus.NEED_UNWRAP) { return new SSLEngineResult(Status.OK, hsStatus, 0, 0); } @@ -2085,14 +2066,6 @@ return Thread.currentThread().getName(); } - /* - * Returns a boolean indicating whether the ChangeCipherSpec message - * has been received for this handshake. - */ - boolean receivedChangeCipherSpec() { - return receivedCCS; - } - /** * Returns a printable representation of this end of the connection. */
--- a/src/share/classes/sun/security/ssl/SSLSessionImpl.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/ssl/SSLSessionImpl.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2018, Oracle and/or its affiliates. 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 @@ -117,6 +117,10 @@ private Principal peerPrincipal; private Principal localPrincipal; + // The endpoint identification algorithm used to check certificates + // in this session. + private final String endpointIdentificationAlgorithm; + /* * Is the session currently re-established with a session-resumption * abbreviated initial handshake? @@ -148,7 +152,7 @@ */ private SSLSessionImpl() { this(ProtocolVersion.NONE, CipherSuite.C_NULL, null, - new SessionId(false, null), null, -1, false); + new SessionId(false, null), null, -1, false, null); } /* @@ -159,10 +163,10 @@ SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite, Collection<SignatureAndHashAlgorithm> algorithms, SecureRandom generator, String host, int port, - boolean useExtendedMasterSecret) { + boolean useExtendedMasterSecret, String endpointIdAlgorithm) { this(protocolVersion, cipherSuite, algorithms, new SessionId(defaultRejoinable, generator), host, port, - useExtendedMasterSecret); + useExtendedMasterSecret, endpointIdAlgorithm); } /* @@ -171,7 +175,8 @@ SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite, Collection<SignatureAndHashAlgorithm> algorithms, SessionId id, String host, int port, - boolean useExtendedMasterSecret) { + boolean useExtendedMasterSecret, + String endpointIdAlgorithm){ this.protocolVersion = protocolVersion; sessionId = id; peerCerts = null; @@ -184,6 +189,7 @@ localSupportedSignAlgs = SignatureAndHashAlgorithm.getAlgorithmNames(algorithms); this.useExtendedMasterSecret = useExtendedMasterSecret; + this.endpointIdentificationAlgorithm = endpointIdAlgorithm; if (debug != null && Debug.isOn("session")) { System.out.println("%% Initialized: " + this); @@ -245,6 +251,10 @@ localPrincipal = principal; } + String getEndpointIdentificationAlgorithm() { + return this.endpointIdentificationAlgorithm; + } + /** * Returns true iff this session may be resumed ... sessions are * usually resumable. Security policies may suggest otherwise,
--- a/src/share/classes/sun/security/ssl/SSLSocketImpl.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/ssl/SSLSocketImpl.java Mon Oct 22 06:23:01 2018 +0100 @@ -176,12 +176,6 @@ private volatile int connectionState; /* - * Flag indicating that the engine's handshaker has done the necessary - * steps so the engine may process a ChangeCipherSpec message. - */ - private boolean receivedCCS; - - /* * Flag indicating if the next record we receive MUST be a Finished * message. Temporarily set during the handshake to ensure that * a change cipher spec message is followed by a finished message. @@ -573,7 +567,6 @@ */ roleIsServer = isServer; connectionState = cs_START; - receivedCCS = false; /* * default read and write side cipher and MAC support @@ -901,7 +894,6 @@ readRecord(r, true); } - /* * Clear the pipeline of records from the peer, optionally returning * application data. Caller is responsible for knowing that it's @@ -1035,7 +1027,8 @@ if (handshaker.invalidated) { handshaker = null; - receivedCCS = false; + inrec.setHandshakeHash(null); + // if state is cs_RENEGOTIATE, revert it to cs_DATA if (connectionState == cs_RENEGOTIATE) { connectionState = cs_DATA; @@ -1051,7 +1044,6 @@ handshakeSession = null; handshaker = null; connectionState = cs_DATA; - receivedCCS = false; // // Tell folk about handshake completion, but do @@ -1098,25 +1090,17 @@ case Record.ct_change_cipher_spec: if ((connectionState != cs_HANDSHAKE - && connectionState != cs_RENEGOTIATE) - || !handshaker.sessionKeysCalculated() - || receivedCCS) { + && connectionState != cs_RENEGOTIATE)) { // For the CCS message arriving in the wrong state fatal(Alerts.alert_unexpected_message, "illegal change cipher spec msg, conn state = " - + connectionState + ", handshake state = " - + handshaker.state); + + connectionState); } else if (r.available() != 1 || r.read() != 1) { // For structural/content issues with the CCS fatal(Alerts.alert_unexpected_message, "Malformed change cipher spec msg"); } - // Once we've received CCS, update the flag. - // If the remote endpoint sends it again in this handshake - // we won't process it. - receivedCCS = true; - // // The first message after a change_cipher_spec // record MUST be a "Finished" handshake record, @@ -1124,6 +1108,7 @@ // to be checked by a minor tweak to the state // machine. // + handshaker.receiveChangeCipherSpec(); changeReadCiphers(); // next message MUST be a finished message expectingFinished = true; @@ -1318,13 +1303,10 @@ kickstartHandshake(); /* - * All initial handshaking goes through this - * InputRecord until we have a valid SSL connection. - * Once initial handshaking is finished, AppInputStream's - * InputRecord can handle any future renegotiation. + * All initial handshaking goes through this operation + * until we have a valid SSL connection. * - * Keep this local so that it goes out of scope and is - * eventually GC'd. + * Handle handshake messages only, need no application data. */ if (inrec == null) { inrec = new InputRecord(); @@ -2537,14 +2519,6 @@ } } - /* - * Returns a boolean indicating whether the ChangeCipherSpec message - * has been received for this handshake. - */ - boolean receivedChangeCipherSpec() { - return receivedCCS; - } - // // We allocate a separate thread to deliver handshake completion // events. This ensures that the notifications don't block the
--- a/src/share/classes/sun/security/ssl/ServerHandshaker.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/ssl/ServerHandshaker.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2018, Oracle and/or its affiliates. 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 @@ -208,21 +208,14 @@ */ void processMessage(byte type, int message_len) throws IOException { - // - // In SSLv3 and TLS, messages follow strictly increasing - // numerical order _except_ for one annoying special case. - // - if ((state >= type) - && (state != HandshakeMessage.ht_client_key_exchange - && type != HandshakeMessage.ht_certificate_verify)) { - throw new SSLProtocolException( - "Handshake message sequence violation, state = " + state - + ", type = " + type); - } + + // check the handshake state + handshakeState.check(type); switch (type) { case HandshakeMessage.ht_client_hello: ClientHello ch = new ClientHello(input, message_len); + handshakeState.update(ch, resumingSession); /* * send it off for processing. */ @@ -235,7 +228,9 @@ "client sent unsolicited cert chain"); // NOTREACHED } - this.clientCertificate(new CertificateMsg(input)); + CertificateMsg certificateMsg = new CertificateMsg(input); + handshakeState.update(certificateMsg, resumingSession); + this.clientCertificate(certificateMsg); break; case HandshakeMessage.ht_client_key_exchange: @@ -253,16 +248,19 @@ protocolVersion, clientRequestedVersion, sslContext.getSecureRandom(), input, message_len, privateKey); + handshakeState.update(pms, resumingSession); preMasterSecret = this.clientKeyExchange(pms); break; case K_KRB5: case K_KRB5_EXPORT: - preMasterSecret = this.clientKeyExchange( + KerberosClientKeyExchange kke = new KerberosClientKeyExchange(protocolVersion, clientRequestedVersion, sslContext.getSecureRandom(), input, - kerberosKeys)); + kerberosKeys); + handshakeState.update(kke, resumingSession); + preMasterSecret = this.clientKeyExchange(kke); break; case K_DHE_RSA: case K_DHE_DSS: @@ -273,16 +271,19 @@ * protocol difference in these five flavors is in how * the ServerKeyExchange message was constructed! */ - preMasterSecret = this.clientKeyExchange( - new DHClientKeyExchange(input)); + DHClientKeyExchange dhcke = new DHClientKeyExchange(input); + handshakeState.update(dhcke, resumingSession); + preMasterSecret = this.clientKeyExchange(dhcke); break; case K_ECDH_RSA: case K_ECDH_ECDSA: case K_ECDHE_RSA: case K_ECDHE_ECDSA: case K_ECDH_ANON: - preMasterSecret = this.clientKeyExchange - (new ECDHClientKeyExchange(input)); + ECDHClientKeyExchange ecdhcke = + new ECDHClientKeyExchange(input); + handshakeState.update(ecdhcke, resumingSession); + preMasterSecret = this.clientKeyExchange(ecdhcke); break; default: throw new SSLProtocolException @@ -302,38 +303,24 @@ break; case HandshakeMessage.ht_certificate_verify: - this.clientCertificateVerify(new CertificateVerify(input, - getLocalSupportedSignAlgs(), protocolVersion)); + CertificateVerify cvm = + new CertificateVerify(input, + getLocalSupportedSignAlgs(), protocolVersion); + handshakeState.update(cvm, resumingSession); + this.clientCertificateVerify(cvm); break; case HandshakeMessage.ht_finished: - // A ChangeCipherSpec record must have been received prior to - // reception of the Finished message (RFC 5246, 7.4.9). - if (!receivedChangeCipherSpec()) { - fatalSE(Alerts.alert_handshake_failure, - "Received Finished message before ChangeCipherSpec"); - } - - this.clientFinished( - new Finished(protocolVersion, input, cipherSuite)); + Finished cfm = + new Finished(protocolVersion, input, cipherSuite); + handshakeState.update(cfm, resumingSession); + this.clientFinished(cfm); break; default: throw new SSLProtocolException( "Illegal server handshake msg, " + type); } - - // - // Move state machine forward if the message handling - // code didn't already do so - // - if (state < type) { - if(type == HandshakeMessage.ht_certificate_verify) { - state = type + 2; // an annoying special case - } else { - state = type; - } - } } @@ -664,6 +651,25 @@ } } + // ensure that the endpoint identification algorithm matches the + // one in the session + String identityAlg = getEndpointIdentificationAlgorithmSE(); + if (resumingSession && identityAlg != null) { + + String sessionIdentityAlg = + previous.getEndpointIdentificationAlgorithm(); + if (!Objects.equals(identityAlg, sessionIdentityAlg)) { + + if (debug != null && Debug.isOn("session")) { + System.out.println("%% can't resume, endpoint id" + + " algorithm does not match, requested: " + + identityAlg + ", cached: " + + sessionIdentityAlg); + } + resumingSession = false; + } + } + if (resumingSession) { CipherSuite suite = previous.getSuite(); // verify that the ciphersuite from the cached session @@ -735,7 +741,8 @@ sslContext.getSecureRandom(), getHostAddressSE(), getPortSE(), (requestedToUseEMS && - (protocolVersion.v >= ProtocolVersion.TLS10.v))); + (protocolVersion.v >= ProtocolVersion.TLS10.v)), + getEndpointIdentificationAlgorithmSE()); if (protocolVersion.v >= ProtocolVersion.TLS12.v) { if (peerSupportedSignAlgs != null) { @@ -795,6 +802,7 @@ System.out.println("Cipher suite: " + session.getSuite()); } m1.write(output); + handshakeState.update(m1, resumingSession); // // If we are resuming a session, we finish writing handshake @@ -834,6 +842,7 @@ m2.print(System.out); } m2.write(output); + handshakeState.update(m2, resumingSession); // XXX has some side effects with OS TCP buffering, // leave it out for now @@ -929,6 +938,7 @@ m3.print(System.out); } m3.write(output); + handshakeState.update(m3, resumingSession); } // @@ -979,6 +989,7 @@ m4.print(System.out); } m4.write(output); + handshakeState.update(m4, resumingSession); } else { if (protocolVersion.v >= ProtocolVersion.TLS12.v) { handshakeHash.setCertificateVerifyAlg(null); @@ -994,6 +1005,7 @@ m5.print(System.out); } m5.write(output); + handshakeState.update(m5, resumingSession); /* * Flush any buffered messages so the client will see them. @@ -1731,6 +1743,8 @@ if (!resumingSession) { input.digestNow(); sendChangeCipherAndFinish(true); + } else { + handshakeFinished = true; } /* @@ -1778,16 +1792,6 @@ if (secureRenegotiation) { serverVerifyData = mesg.getVerifyData(); } - - /* - * Update state machine so client MUST send 'finished' next - * The update should only take place if it is not in the fast - * handshake mode since the server has to wait for a finished - * message from the client. - */ - if (finishedTag) { - state = HandshakeMessage.ht_finished; - } }
--- a/src/share/classes/sun/security/ssl/SessionId.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/ssl/SessionId.java Mon Oct 22 06:23:01 2018 +0100 @@ -27,6 +27,7 @@ package sun.security.ssl; import java.security.SecureRandom; +import javax.net.ssl.SSLProtocolException; /** * Encapsulates an SSL session ID. SSL Session IDs are not reused by @@ -41,6 +42,7 @@ final class SessionId { + static int MAX_LENGTH = 32; private byte sessionId []; // max 32 bytes /** Constructs a new session ID ... perhaps for a rejoinable session */ @@ -111,4 +113,19 @@ } return true; } + + /** + * Checks the length of the session ID to make sure it sits within + * the range called out in the specification + */ + void checkLength(ProtocolVersion pv) throws SSLProtocolException { + // As of today all versions of TLS have a 32-byte maximum length. + // In the future we can do more here to support protocol versions + // that may have longer max lengths. + if (sessionId.length > MAX_LENGTH) { + throw new SSLProtocolException("Invalid session ID length (" + + sessionId.length + " bytes)"); + } + } + }
--- a/src/share/classes/sun/security/tools/KeyStoreUtil.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/tools/KeyStoreUtil.java Mon Oct 22 06:23:01 2018 +0100 @@ -35,6 +35,7 @@ import java.security.KeyStore; +import java.security.cert.X509Certificate; import java.text.Collator; import java.util.Locale; @@ -59,6 +60,25 @@ }; /** + * Returns true if the certificate is self-signed, false otherwise. + */ + public static boolean isSelfSigned(X509Certificate cert) { + return signedBy(cert, cert); + } + + public static boolean signedBy(X509Certificate end, X509Certificate ca) { + if (!ca.getSubjectX500Principal().equals(end.getIssuerX500Principal())) { + return false; + } + try { + end.verify(ca.getPublicKey()); + return true; + } catch (Exception e) { + return false; + } + } + + /** * Returns true if KeyStore has a password. This is true except for * MSCAPI KeyStores */
--- a/src/share/classes/sun/security/tools/jarsigner/Main.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/tools/jarsigner/Main.java Mon Oct 22 06:23:01 2018 +0100 @@ -26,6 +26,8 @@ package sun.security.tools.jarsigner; import java.io.*; +import java.security.cert.CertPathValidatorException; +import java.security.cert.PKIXBuilderParameters; import java.util.*; import java.util.zip.*; import java.util.jar.*; @@ -46,11 +48,9 @@ import java.net.URL; import java.net.URLClassLoader; import java.security.cert.CertPath; -import java.security.cert.CertPathValidator; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateFactory; import java.security.cert.CertificateNotYetValidException; -import java.security.cert.PKIXParameters; import java.security.cert.TrustAnchor; import java.util.Map.Entry; import sun.security.pkcs.PKCS7; @@ -58,6 +58,8 @@ import sun.security.timestamp.TimestampToken; import sun.security.tools.KeyStoreUtil; import sun.security.tools.PathList; +import sun.security.validator.Validator; +import sun.security.validator.ValidatorException; import sun.security.x509.*; import sun.security.util.*; import sun.misc.BASE64Encoder; @@ -173,22 +175,34 @@ private boolean noTimestamp = false; private Date expireDate = new Date(0L); // used in noTimestamp warning - // Severe warnings + // Severe warnings. + + // jarsigner used to check signer cert chain validity and key usages + // itself and set various warnings. Later CertPath validation is + // added but chainNotValidated is only flagged when no other existing + // warnings are set. TSA cert chain check is added separately and + // only tsaChainNotValidated is set, i.e. has no affect on hasExpiredCert, + // notYetValidCert, or any badXyzUsage. + + private int weakAlg = 0; // 1. digestalg, 2. sigalg, 4. tsadigestalg private boolean hasExpiredCert = false; private boolean notYetValidCert = false; private boolean chainNotValidated = false; + private boolean tsaChainNotValidated = false; private boolean notSignedByAlias = false; private boolean aliasNotInStore = false; private boolean hasUnsignedEntry = false; private boolean badKeyUsage = false; private boolean badExtendedKeyUsage = false; private boolean badNetscapeCertType = false; + private boolean signerSelfSigned = false; + + private Throwable chainNotValidatedReason = null; + private Throwable tsaChainNotValidatedReason = null; private boolean seeWeak = false; - CertificateFactory certificateFactory; - CertPathValidator validator; - PKIXParameters pkixParameters; + PKIXBuilderParameters pkixParameters; public void run(String args[]) { try { @@ -275,7 +289,8 @@ if (strict) { int exitCode = 0; - if (chainNotValidated || hasExpiredCert || notYetValidCert) { + if (weakAlg != 0 || chainNotValidated + || hasExpiredCert || notYetValidCert || signerSelfSigned) { exitCode |= 4; } if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) { @@ -287,6 +302,9 @@ if (notSignedByAlias || aliasNotInStore) { exitCode |= 32; } + if (tsaChainNotValidated) { + exitCode |= 64; + } if (exitCode != 0) { System.exit(exitCode); } @@ -812,6 +830,9 @@ System.out.println(rb.getString("no.manifest.")); } + // If there is a time stamp block inside the PKCS7 block file + boolean hasTimestampBlock = false; + // Even if the verbose option is not specified, all out strings // must be generated so seeWeak can be updated. if (!digestMap.isEmpty() @@ -841,6 +862,7 @@ PublicKey key = signer.getPublicKey(); PKCS7 tsToken = si.getTsToken(); if (tsToken != null) { + hasTimestampBlock = true; SignerInfo tsSi = tsToken.getSignerInfos()[0]; X509Certificate tsSigner = tsSi.getCertificate(tsToken); byte[] encTsTokenInfo = tsToken.getContentInfo().getData(); @@ -898,6 +920,12 @@ } System.out.println(); + // If signer is a trusted cert or private entry in user's own + // keystore, it can be self-signed. + if (!aliasNotInStore) { + signerSelfSigned = false; + } + if (!anySigned) { if (seeWeak) { if (verbose != null) { @@ -918,8 +946,8 @@ boolean errorAppeared = false; if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType || notYetValidCert || chainNotValidated || hasExpiredCert || - hasUnsignedEntry || - aliasNotInStore || notSignedByAlias) { + hasUnsignedEntry || signerSelfSigned || (weakAlg != 0) || + aliasNotInStore || notSignedByAlias || tsaChainNotValidated) { if (strict) { System.out.println(rb.getString("jar.verified.with.signer.errors.")); @@ -933,6 +961,12 @@ warningAppeared = true; } + if (weakAlg != 0) { + // In fact, jarsigner verification did not catch this + // since it has not read the JarFile content itself. + // Everything is done with JarFile API. + } + if (badKeyUsage) { System.out.println( rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.")); @@ -962,8 +996,15 @@ } if (chainNotValidated) { - System.out.println( - rb.getString("This.jar.contains.entries.whose.certificate.chain.is.not.validated.")); + System.out.println(String.format( + rb.getString("This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1"), + chainNotValidatedReason.getLocalizedMessage())); + } + + if (tsaChainNotValidated) { + System.out.println(String.format( + rb.getString("This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1"), + tsaChainNotValidatedReason.getLocalizedMessage())); } if (notSignedByAlias) { @@ -974,6 +1015,11 @@ if (aliasNotInStore) { System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.")); } + + if (signerSelfSigned) { + System.out.println(rb.getString( + "This.jar.contains.entries.whose.signer.certificate.is.self.signed.")); + } } else { System.out.println(rb.getString("jar.verified.")); } @@ -988,8 +1034,15 @@ "This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.")); } if (noTimestamp) { - System.out.println( - String.format(rb.getString("no.timestamp.verifying"), expireDate)); + if (hasTimestampBlock) { + // JarSigner API has not seen the timestamp, + // might have ignored it due to weak alg, etc. + System.out.println( + String.format(rb.getString("bad.timestamp.verifying"), expireDate)); + } else { + System.out.println( + String.format(rb.getString("no.timestamp.verifying"), expireDate)); + } } } if (warningAppeared || errorAppeared) { @@ -1040,16 +1093,23 @@ private static MessageFormat expiredTimeForm = null; private static MessageFormat expiringTimeForm = null; - /* - * Display some details about a certificate: + /** + * Returns a string about a certificate: * * [<tab>] <cert-type> [", " <subject-DN>] [" (" <keystore-entry-alias> ")"] * [<validity-period> | <expiry-warning>] + * [<key-usage-warning>] * - * Note: no newline character at the end + * Note: no newline character at the end. + * + * When isTsCert is true, this method sets global flags like hasExpiredCert, + * notYetValidCert, badKeyUsage, badExtendedKeyUsage, badNetscapeCertType. + * + * @param isTsCert true if c is in the TSA cert chain, false otherwise. + * @param checkUsage true to check code signer keyUsage */ - String printCert(String tab, Certificate c, boolean checkValidityPeriod, - Date timestamp, boolean checkUsage) { + String printCert(boolean isTsCert, String tab, Certificate c, + Date timestamp, boolean checkUsage) throws Exception { StringBuilder certStr = new StringBuilder(); String space = rb.getString("SPACE"); @@ -1069,7 +1129,7 @@ certStr.append(space).append(alias); } - if (checkValidityPeriod && x509Cert != null) { + if (x509Cert != null) { certStr.append("\n").append(tab).append("["); Date notAfter = x509Cert.getNotAfter(); @@ -1082,7 +1142,7 @@ x509Cert.checkValidity(); // test if cert will expire within six months if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) { - hasExpiringCert = true; + if (!isTsCert) hasExpiringCert = true; if (expiringTimeForm == null) { expiringTimeForm = new MessageFormat( rb.getString("certificate.will.expire.on")); @@ -1103,7 +1163,7 @@ certStr.append(validityTimeForm.format(source)); } } catch (CertificateExpiredException cee) { - hasExpiredCert = true; + if (!isTsCert) hasExpiredCert = true; if (expiredTimeForm == null) { expiredTimeForm = new MessageFormat( @@ -1113,7 +1173,7 @@ certStr.append(expiredTimeForm.format(source)); } catch (CertificateNotYetValidException cnyve) { - notYetValidCert = true; + if (!isTsCert) notYetValidCert = true; if (notYetTimeForm == null) { notYetTimeForm = new MessageFormat( @@ -1226,7 +1286,25 @@ } void signJar(String jarName, String alias, String[] args) - throws Exception { + throws Exception { + + DisabledAlgorithmConstraints dac = + new DisabledAlgorithmConstraints( + DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS); + + if (digestalg != null && !dac.permits( + Collections.singleton(CryptoPrimitive.MESSAGE_DIGEST), digestalg, null)) { + weakAlg |= 1; + } + if (tSADigestAlg != null && !dac.permits( + Collections.singleton(CryptoPrimitive.MESSAGE_DIGEST), tSADigestAlg, null)) { + weakAlg |= 4; + } + if (sigalg != null && !dac.permits( + Collections.singleton(CryptoPrimitive.SIGNATURE), sigalg, null)) { + weakAlg |= 2; + } + boolean aliasUsed = false; X509Certificate tsaCert = null; @@ -1504,7 +1582,7 @@ tsaURI); } System.out.println(rb.getString("TSA.certificate.") + - printCert("", tsaCert, false, null, false)); + printCert(true, "", tsaCert, null, false)); } if (signingMechanism != null) { System.out.println( @@ -1567,6 +1645,30 @@ } } + // The JarSigner API always accepts the timestamp received. + // We need to extract the certs from the signed jar to + // validate it. + if (!noTimestamp) { + try (JarFile check = new JarFile(signedJarFile)) { + PKCS7 p7 = new PKCS7(check.getInputStream(check.getEntry( + "META-INF/" + sigfile + "." + privateKey.getAlgorithm()))); + SignerInfo si = p7.getSignerInfos()[0]; + PKCS7 tsToken = si.getTsToken(); + SignerInfo tsSi = tsToken.getSignerInfos()[0]; + try { + validateCertChain(Validator.VAR_TSA_SERVER, + tsSi.getCertificateChain(tsToken), null); + } catch (Exception e) { + tsaChainNotValidated = true; + tsaChainNotValidatedReason = e; + } + } catch (Exception e) { + if (debug) { + e.printStackTrace(); + } + } + } + // no IOException thrown in the follow try clause, so disable // the try clause. // try { @@ -1596,8 +1698,10 @@ } boolean warningAppeared = false; - if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType || - notYetValidCert || chainNotValidated || hasExpiredCert) { + if (weakAlg != 0 || badKeyUsage || badExtendedKeyUsage + || badNetscapeCertType || notYetValidCert + || chainNotValidated || tsaChainNotValidated + || hasExpiredCert || signerSelfSigned) { if (strict) { System.out.println(rb.getString("jar.signed.with.signer.errors.")); System.out.println(); @@ -1633,8 +1737,37 @@ } if (chainNotValidated) { + System.out.println(String.format( + rb.getString("The.signer.s.certificate.chain.is.invalid.reason.1"), + chainNotValidatedReason.getLocalizedMessage())); + } + + if (tsaChainNotValidated) { + System.out.println(String.format( + rb.getString("The.tsa.certificate.chain.is.invalid.reason.1"), + tsaChainNotValidatedReason.getLocalizedMessage())); + } + + if (signerSelfSigned) { System.out.println( - rb.getString("The.signer.s.certificate.chain.is.not.validated.")); + rb.getString("The.signer.s.certificate.is.self.signed.")); + } + + if ((weakAlg & 1) == 1) { + System.out.println(String.format( + rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."), + digestalg, "-digestalg")); + } + + if ((weakAlg & 2) == 2) { + System.out.println(String.format( + rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."), + sigalg, "-sigalg")); + } + if ((weakAlg & 4) == 4) { + System.out.println(String.format( + rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."), + tSADigestAlg, "-tsadigestalg")); } } else { System.out.println(rb.getString("jar.signed.")); @@ -1710,18 +1843,18 @@ /** * Returns a string of singer info, with a newline at the end */ - private String signerInfo(CodeSigner signer, String tab) { + private String signerInfo(CodeSigner signer, String tab) throws Exception { if (cacheForSignerInfo.containsKey(signer)) { return cacheForSignerInfo.get(signer); } - StringBuffer s = new StringBuffer(); + StringBuilder sb = new StringBuilder(); List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates(); // display the signature timestamp, if present Date timestamp; Timestamp ts = signer.getTimestamp(); if (ts != null) { - s.append(printTimestamp(tab, ts)); - s.append('\n'); + sb.append(printTimestamp(tab, ts)); + sb.append('\n'); timestamp = ts.getTimestamp(); } else { timestamp = null; @@ -1730,28 +1863,41 @@ // display the certificate(s). The first one is end-entity cert and // its KeyUsage should be checked. boolean first = true; + sb.append(tab).append(rb.getString("...Signer")).append('\n'); for (Certificate c : certs) { - s.append(printCert(tab, c, true, timestamp, first)); - s.append('\n'); + sb.append(printCert(false, tab, c, timestamp, first)); + sb.append('\n'); first = false; } try { - validateCertChain(certs); + validateCertChain(Validator.VAR_CODE_SIGNING, certs, ts); } catch (Exception e) { - if (debug) { - e.printStackTrace(); + chainNotValidated = true; + chainNotValidatedReason = e; + sb.append(tab).append(rb.getString(".Invalid.certificate.chain.")) + .append(e.getLocalizedMessage()).append("]\n"); + } + if (ts != null) { + sb.append(tab).append(rb.getString("...TSA")).append('\n'); + for (Certificate c : ts.getSignerCertPath().getCertificates()) { + sb.append(printCert(true, tab, c, timestamp, false)); + sb.append('\n'); } - if (e.getCause() != null && - (e.getCause() instanceof CertificateExpiredException || - e.getCause() instanceof CertificateNotYetValidException)) { - // No more warning, we alreay have hasExpiredCert or notYetValidCert - } else { - chainNotValidated = true; - s.append(tab + rb.getString(".CertPath.not.validated.") + - e.getLocalizedMessage() + "]\n"); // TODO + try { + validateCertChain(Validator.VAR_TSA_SERVER, + ts.getSignerCertPath().getCertificates(), null); + } catch (Exception e) { + tsaChainNotValidated = true; + tsaChainNotValidatedReason = e; + sb.append(tab).append(rb.getString(".Invalid.TSA.certificate.chain.")) + .append(e.getLocalizedMessage()).append("]\n"); } } - String result = s.toString(); + if (certs.size() == 1 + && KeyStoreUtil.isSelfSigned((X509Certificate)certs.get(0))) { + signerSelfSigned = true; + } + String result = sb.toString(); cacheForSignerInfo.put(signer, result); return result; } @@ -1803,9 +1949,6 @@ } try { - - certificateFactory = CertificateFactory.getInstance("X.509"); - validator = CertPathValidator.getInstance("PKIX"); Set<TrustAnchor> tas = new HashSet<>(); try { KeyStore caks = KeyStoreUtil.getCacertsKeyStore(); @@ -1881,7 +2024,7 @@ } } finally { try { - pkixParameters = new PKIXParameters(tas); + pkixParameters = new PKIXBuilderParameters(tas, null); pkixParameters.setRevocationEnabled(false); } catch (InvalidAlgorithmParameterException ex) { // Only if tas is empty @@ -1997,7 +2140,7 @@ } } - void getAliasInfo(String alias) { + void getAliasInfo(String alias) throws Exception { Key key = null; @@ -2043,21 +2186,18 @@ // We don't meant to print anything, the next call // checks validity and keyUsage etc - printCert("", certChain[0], true, null, true); + printCert(false, "", certChain[0], null, true); try { - validateCertChain(Arrays.asList(certChain)); + validateCertChain(Validator.VAR_CODE_SIGNING, + Arrays.asList(certChain), null); } catch (Exception e) { - if (debug) { - e.printStackTrace(); - } - if (e.getCause() != null && - (e.getCause() instanceof CertificateExpiredException || - e.getCause() instanceof CertificateNotYetValidException)) { - // No more warning, we alreay have hasExpiredCert or notYetValidCert - } else { - chainNotValidated = true; - } + chainNotValidated = true; + chainNotValidatedReason = e; + } + + if (KeyStoreUtil.isSelfSigned(certChain[0])) { + signerSelfSigned = true; } try { @@ -2111,19 +2251,55 @@ System.exit(1); } - void validateCertChain(List<? extends Certificate> certs) throws Exception { - int cpLen = 0; - out: for (; cpLen<certs.size(); cpLen++) { - for (TrustAnchor ta: pkixParameters.getTrustAnchors()) { - if (ta.getTrustedCert().equals(certs.get(cpLen))) { - break out; + /** + * Validates a cert chain. + * + * @param parameter this might be a timestamp + */ + void validateCertChain(String variant, List<? extends Certificate> certs, + Object parameter) + throws Exception { + try { + Validator.getInstance(Validator.TYPE_PKIX, + variant, + pkixParameters) + .validate(certs.toArray(new X509Certificate[certs.size()]), + null, parameter); + } catch (Exception e) { + if (debug) { + e.printStackTrace(); + } + + // Exception might be dismissed if another warning flag + // is already set by printCert. This is only done for + // code signing certs. + + if (variant.equals(Validator.VAR_CODE_SIGNING) && + e instanceof ValidatorException) { + // Throw cause if it's CertPathValidatorException, + if (e.getCause() != null && + e.getCause() instanceof CertPathValidatorException) { + e = (Exception) e.getCause(); + Throwable t = e.getCause(); + if ((t instanceof CertificateExpiredException && + hasExpiredCert) || + (t instanceof CertificateNotYetValidException && + notYetValidCert)) { + // we already have hasExpiredCert and notYetValidCert + return; + } + } + if (e instanceof ValidatorException) { + ValidatorException ve = (ValidatorException)e; + if (ve.getErrorType() == ValidatorException.T_EE_EXTENSIONS && + (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType)) { + // We already have badKeyUsage, badExtendedKeyUsage + // and badNetscapeCertType + return; + } } } - } - if (cpLen > 0) { - CertPath cp = certificateFactory.generateCertPath( - (cpLen == certs.size())? certs: certs.subList(0, cpLen)); - validator.validate(cp, pkixParameters); + throw e; } }
--- a/src/share/classes/sun/security/tools/jarsigner/Resources.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/tools/jarsigner/Resources.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. 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 @@ -199,7 +199,8 @@ {"certificate.is.not.valid.until", "certificate is not valid until {0}"}, {"certificate.will.expire.on", "certificate will expire on {0}"}, - {".CertPath.not.validated.", "[CertPath not validated: "}, + {".Invalid.certificate.chain.", "[Invalid certificate chain: "}, + {".Invalid.TSA.certificate.chain.", "[Invalid TSA certificate chain: "}, {"requesting.a.signature.timestamp", "requesting a signature timestamp"}, {"TSA.location.", "TSA location: "}, @@ -216,6 +217,8 @@ {"entry.was.signed.on", "entry was signed on {0}"}, {"Warning.", "Warning: "}, {"Error.", "Error: "}, + {"...Signer", ">>> Signer"}, + {"...TSA", ">>> TSA"}, {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.", "This jar contains unsigned entries which have not been integrity-checked. "}, {"This.jar.contains.entries.whose.signer.certificate.has.expired.", @@ -224,6 +227,8 @@ "This jar contains entries whose signer certificate will expire within six months. "}, {"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.", "This jar contains entries whose signer certificate is not yet valid. "}, + {"This.jar.contains.entries.whose.signer.certificate.is.self.signed.", + "This jar contains entries whose signer certificate is self-signed."}, {"Re.run.with.the.verbose.option.for.more.details.", "Re-run with the -verbose option for more details."}, {"Re.run.with.the.verbose.and.certs.options.for.more.details.", @@ -248,18 +253,28 @@ "This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing."}, {".{0}.extension.does.not.support.code.signing.", "[{0} extension does not support code signing]"}, - {"The.signer.s.certificate.chain.is.not.validated.", - "The signer's certificate chain is not validated."}, - {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.", - "This jar contains entries whose certificate chain is not validated."}, + {"The.signer.s.certificate.chain.is.invalid.reason.1", + "The signer's certificate chain is invalid. Reason: %s"}, + {"The.tsa.certificate.chain.is.invalid.reason.1", + "The TSA certificate chain is invalid. Reason: %s"}, + {"The.signer.s.certificate.is.self.signed.", + "The signer's certificate is self-signed."}, + {"The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.", + "The %1$s algorithm specified for the %2$s option is considered a security risk."}, + {"This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1", + "This jar contains entries whose certificate chain is invalid. Reason: %s"}, + {"This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1", + "This jar contains entries whose TSA certificate chain is invalid. Reason: %s"}, + {"no.timestamp.signing", + "No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."}, + {"no.timestamp.verifying", + "This jar contains signatures that does not include a timestamp. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."}, + {"bad.timestamp.verifying", + "This jar contains signatures that include an invalid timestamp. Without a valid timestamp, users may not be able to validate this jar after any of the signer certificates expire (as early as %1$tY-%1$tm-%1$td).\nRerun jarsigner with -J-Djava.security.debug=jar for more information."}, {"Unknown.password.type.", "Unknown password type: "}, {"Cannot.find.environment.variable.", "Cannot find environment variable: "}, {"Cannot.find.file.", "Cannot find file: "}, - {"no.timestamp.signing", - "No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."}, - {"no.timestamp.verifying", - "This jar contains signatures that does not include a timestamp. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."}, }; /**
--- a/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java Mon Oct 22 06:23:01 2018 +0100 @@ -199,7 +199,8 @@ {"certificate.is.not.valid.until", "\u8A3C\u660E\u66F8\u306F{0}\u307E\u3067\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093"}, {"certificate.will.expire.on", "\u8A3C\u660E\u66F8\u306F{0}\u306B\u5931\u52B9\u3057\u307E\u3059"}, - {".CertPath.not.validated.", "[CertPath\u304C\u691C\u8A3C\u3055\u308C\u3066\u3044\u307E\u305B\u3093: "}, + {".Invalid.certificate.chain.", "[\u7121\u52B9\u306A\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3: "}, + {".Invalid.TSA.certificate.chain.", "[\u7121\u52B9\u306ATSA\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3: "}, {"requesting.a.signature.timestamp", "\u7F72\u540D\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u30EA\u30AF\u30A8\u30B9\u30C8"}, {"TSA.location.", "TSA\u306E\u5834\u6240: "}, @@ -214,6 +215,8 @@ {"entry.was.signed.on", "\u30A8\u30F3\u30C8\u30EA\u306F{0}\u306B\u7F72\u540D\u3055\u308C\u307E\u3057\u305F"}, {"Warning.", "\u8B66\u544A: "}, {"Error.", "\u30A8\u30E9\u30FC: "}, + {"...Signer", ">>> \u7F72\u540D\u8005"}, + {"...TSA", ">>> TSA"}, {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.", "\u3053\u306Ejar\u306B\u306F\u3001\u6574\u5408\u6027\u30C1\u30A7\u30C3\u30AF\u3092\u3057\u3066\u3044\u306A\u3044\u7F72\u540D\u306A\u3057\u306E\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 "}, {"This.jar.contains.entries.whose.signer.certificate.has.expired.", @@ -222,6 +225,8 @@ "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u304C6\u304B\u6708\u4EE5\u5185\u306B\u671F\u9650\u5207\u308C\u3068\u306A\u308B\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 "}, {"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.", "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u304C\u307E\u3060\u6709\u52B9\u306B\u306A\u3063\u3066\u3044\u306A\u3044\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 "}, + {"This.jar.contains.entries.whose.signer.certificate.is.self.signed.", + "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u304C\u81EA\u5DF1\u7F72\u540D\u3055\u308C\u3066\u3044\u308B\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 "}, {"Re.run.with.the.verbose.option.for.more.details.", "\u8A73\u7D30\u306F\u3001-verbose\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}, {"Re.run.with.the.verbose.and.certs.options.for.more.details.", @@ -246,14 +251,24 @@ "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306ENetscapeCertType\u62E1\u5F35\u6A5F\u80FD\u304C\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u8A31\u53EF\u3057\u306A\u3044\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002"}, {".{0}.extension.does.not.support.code.signing.", "[{0}\u62E1\u5F35\u6A5F\u80FD\u306F\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u30B5\u30DD\u30FC\u30C8\u3057\u3066\u3044\u307E\u305B\u3093]"}, - {"The.signer.s.certificate.chain.is.not.validated.", - "\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u304C\u307E\u3060\u691C\u8A3C\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"}, - {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.", - "\u3053\u306Ejar\u306B\u306F\u3001\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u304C\u307E\u3060\u691C\u8A3C\u3055\u308C\u3066\u3044\u306A\u3044\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002"}, + {"The.signer.s.certificate.chain.is.invalid.reason.1", + "\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u304C\u7121\u52B9\u3067\u3059\u3002\u7406\u7531: %s"}, + {"The.tsa.certificate.chain.is.invalid.reason.1", + "TSA\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u304C\u7121\u52B9\u3067\u3059\u3002\u7406\u7531: %s"}, + {"The.signer.s.certificate.is.self.signed.", + "\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u306F\u81EA\u5DF1\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u3059\u3002"}, + {"The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.", + "%1$s\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0(%2$s\u30AA\u30D7\u30B7\u30E7\u30F3\u306B\u6307\u5B9A)\u306F\u3001\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002"}, + {"This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1", + "\u3053\u306Ejar\u306B\u306F\u3001\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u304C\u7121\u52B9\u306A\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002\u7406\u7531: %s"}, + {"This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1", + "\u3053\u306Ejar\u306B\u306F\u3001TSA\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u304C\u7121\u52B9\u306A\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002\u7406\u7531: %s"}, {"no.timestamp.signing", "-tsa\u307E\u305F\u306F-tsacert\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u306A\u3044\u305F\u3081\u3001\u3053\u306Ejar\u306B\u306F\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u304C\u4ED8\u52A0\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u304C\u306A\u3044\u3068\u3001\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306E\u6709\u52B9\u671F\u9650(%1$tY-%1$tm-%1$td)\u5F8C\u307E\u305F\u306F\u5C06\u6765\u306E\u5931\u52B9\u65E5\u5F8C\u306B\u3001\u30E6\u30FC\u30B6\u30FC\u306F\u3053\u306Ejar\u3092\u691C\u8A3C\u3067\u304D\u306A\u3044\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002"}, {"no.timestamp.verifying", "\u3053\u306Ejar\u306B\u306F\u3001\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u304C\u306A\u3044\u7F72\u540D\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u304C\u306A\u3044\u3068\u3001\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306E\u6709\u52B9\u671F\u9650(%1$tY-%1$tm-%1$td)\u5F8C\u307E\u305F\u306F\u5C06\u6765\u306E\u5931\u52B9\u65E5\u5F8C\u306B\u3001\u30E6\u30FC\u30B6\u30FC\u306F\u3053\u306Ejar\u3092\u691C\u8A3C\u3067\u304D\u306A\u3044\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002"}, + {"bad.timestamp.verifying", + "\u3053\u306Ejar\u306B\u306F\u3001\u7121\u52B9\u306A\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u3042\u308B\u7F72\u540D\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002\u6709\u52B9\u306A\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u304C\u306A\u3044\u3068\u3001\u3044\u305A\u308C\u304B\u306E\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306E\u6709\u52B9\u671F\u9650\u5F8C\u306B(\u65E9\u3051\u308C\u3070%1$tY-%1$tm-%1$td)\u30E6\u30FC\u30B6\u30FC\u306F\u3053\u306Ejar\u3092\u691C\u8A3C\u3067\u304D\u306A\u3044\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\n\u8A73\u7D30\u306F\u3001-J-Djava.security.debug=jar\u3092\u6307\u5B9A\u3057\u3066jarsigner\u3092\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}, {"Unknown.password.type.", "\u4E0D\u660E\u306A\u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30BF\u30A4\u30D7: "}, {"Cannot.find.environment.variable.", "\u74B0\u5883\u5909\u6570\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: "},
--- a/src/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java Mon Oct 22 06:23:01 2018 +0100 @@ -199,7 +199,8 @@ {"certificate.is.not.valid.until", "\u76F4\u5230{0}, \u8BC1\u4E66\u624D\u6709\u6548"}, {"certificate.will.expire.on", "\u8BC1\u4E66\u5C06\u5728{0}\u5230\u671F"}, - {".CertPath.not.validated.", "[CertPath \u672A\u9A8C\u8BC1: "}, + {".Invalid.certificate.chain.", "[\u65E0\u6548\u7684\u8BC1\u4E66\u94FE: "}, + {".Invalid.TSA.certificate.chain.", "[\u65E0\u6548 TSA \u7684\u8BC1\u4E66\u94FE: "}, {"requesting.a.signature.timestamp", "\u6B63\u5728\u8BF7\u6C42\u7B7E\u540D\u65F6\u95F4\u6233"}, {"TSA.location.", "TSA \u4F4D\u7F6E: "}, @@ -214,6 +215,8 @@ {"entry.was.signed.on", "\u6761\u76EE\u7684\u7B7E\u540D\u65E5\u671F\u4E3A {0}"}, {"Warning.", "\u8B66\u544A: "}, {"Error.", "\u9519\u8BEF: "}, + {"...Signer", ">>> \u7B7E\u540D\u8005"}, + {"...TSA", ">>> TSA"}, {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.", "\u6B64 jar \u5305\u542B\u5C1A\u672A\u8FDB\u884C\u5B8C\u6574\u6027\u68C0\u67E5\u7684\u672A\u7B7E\u540D\u6761\u76EE\u3002 "}, {"This.jar.contains.entries.whose.signer.certificate.has.expired.", @@ -222,6 +225,8 @@ "\u6B64 jar \u5305\u542B\u7B7E\u540D\u8005\u8BC1\u4E66\u5C06\u5728\u516D\u4E2A\u6708\u5185\u8FC7\u671F\u7684\u6761\u76EE\u3002 "}, {"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.", "\u6B64 jar \u5305\u542B\u7B7E\u540D\u8005\u8BC1\u4E66\u4ECD\u65E0\u6548\u7684\u6761\u76EE\u3002 "}, + {"This.jar.contains.entries.whose.signer.certificate.is.self.signed.", + "\u6B64 jar \u5305\u542B\u5176\u7B7E\u540D\u8005\u8BC1\u4E66\u4E3A\u81EA\u7B7E\u540D\u8BC1\u4E66\u7684\u6761\u76EE\u3002"}, {"Re.run.with.the.verbose.option.for.more.details.", "\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u4F7F\u7528 -verbose \u9009\u9879\u91CD\u65B0\u8FD0\u884C\u3002"}, {"Re.run.with.the.verbose.and.certs.options.for.more.details.", @@ -246,15 +251,25 @@ "\u6B64 jar \u5305\u542B\u7531\u4E8E\u7B7E\u540D\u8005\u8BC1\u4E66\u7684 NetscapeCertType \u6269\u5C55\u800C\u65E0\u6CD5\u8FDB\u884C\u4EE3\u7801\u7B7E\u540D\u7684\u6761\u76EE\u3002"}, {".{0}.extension.does.not.support.code.signing.", "[{0} \u6269\u5C55\u4E0D\u652F\u6301\u4EE3\u7801\u7B7E\u540D]"}, - {"The.signer.s.certificate.chain.is.not.validated.", - "\u7B7E\u540D\u8005\u7684\u8BC1\u4E66\u94FE\u672A\u9A8C\u8BC1\u3002"}, - {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.", - "\u6B64 jar \u5305\u542B\u8BC1\u4E66\u94FE\u672A\u9A8C\u8BC1\u7684\u6761\u76EE\u3002"}, + {"The.signer.s.certificate.chain.is.invalid.reason.1", + "\u7B7E\u540D\u8005\u8BC1\u4E66\u94FE\u65E0\u6548\u3002\u539F\u56E0: %s"}, + {"The.tsa.certificate.chain.is.invalid.reason.1", + "TSA \u8BC1\u4E66\u94FE\u65E0\u6548\u3002\u539F\u56E0: %s"}, + {"The.signer.s.certificate.is.self.signed.", + "\u7B7E\u540D\u8005\u8BC1\u4E66\u4E3A\u81EA\u7B7E\u540D\u8BC1\u4E66\u3002"}, + {"The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.", + "\u4E3A %2$s \u9009\u9879\u6307\u5B9A\u7684 %1$s \u7B97\u6CD5\u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u3002"}, + {"This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1", + "\u6B64 jar \u5305\u542B\u5176\u8BC1\u4E66\u94FE\u65E0\u6548\u7684\u6761\u76EE\u3002\u539F\u56E0: %s"}, + {"This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1", + "\u6B64 jar \u5305\u542B\u5176 TSA \u8BC1\u4E66\u94FE\u65E0\u6548\u7684\u6761\u76EE\u3002\u539F\u56E0: %s"}, {"Command.option.flag.needs.an.argument.", "\u547D\u4EE4\u9009\u9879{0}\u9700\u8981\u4E00\u4E2A\u53C2\u6570\u3002"}, {"no.timestamp.signing", "\u672A\u63D0\u4F9B -tsa \u6216 -tsacert, \u6B64 jar \u6CA1\u6709\u65F6\u95F4\u6233\u3002\u5982\u679C\u6CA1\u6709\u65F6\u95F4\u6233, \u5219\u5728\u7B7E\u540D\u8005\u8BC1\u4E66\u7684\u5230\u671F\u65E5\u671F (%1$tY-%1$tm-%1$td) \u6216\u4EE5\u540E\u7684\u4EFB\u4F55\u64A4\u9500\u65E5\u671F\u4E4B\u540E, \u7528\u6237\u53EF\u80FD\u65E0\u6CD5\u9A8C\u8BC1\u6B64 jar\u3002"}, {"no.timestamp.verifying", "\u6B64 jar \u5305\u542B\u7684\u7B7E\u540D\u6CA1\u6709\u65F6\u95F4\u6233\u3002\u5982\u679C\u6CA1\u6709\u65F6\u95F4\u6233, \u5219\u5728\u7B7E\u540D\u8005\u8BC1\u4E66\u7684\u5230\u671F\u65E5\u671F (%1$tY-%1$tm-%1$td) \u6216\u4EE5\u540E\u7684\u4EFB\u4F55\u64A4\u9500\u65E5\u671F\u4E4B\u540E, \u7528\u6237\u53EF\u80FD\u65E0\u6CD5\u9A8C\u8BC1\u6B64 jar\u3002"}, + {"bad.timestamp.verifying", + "\u6B64 jar \u5305\u542B\u5E26\u6709\u65E0\u6548\u65F6\u95F4\u6233\u7684\u7B7E\u540D\u3002\u5982\u679C\u6CA1\u6709\u6709\u6548\u65F6\u95F4\u6233, \u5219\u5728\u5176\u4E2D\u4EFB\u4E00\u7B7E\u540D\u8005\u8BC1\u4E66\u5230\u671F (\u6700\u65E9\u4E3A %1$tY-%1$tm-%1$td) \u4E4B\u540E, \u7528\u6237\u53EF\u80FD\u65E0\u6CD5\u9A8C\u8BC1\u6B64 jar\u3002\n\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u4F7F\u7528 -J-Djava.security.debug=jar \u91CD\u65B0\u8FD0\u884C jarsigner\u3002"}, {"Unknown.password.type.", "\u672A\u77E5\u53E3\u4EE4\u7C7B\u578B: "}, {"Cannot.find.environment.variable.", "\u627E\u4E0D\u5230\u73AF\u5883\u53D8\u91CF: "},
--- a/src/share/classes/sun/security/tools/keytool/Main.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/tools/keytool/Main.java Mon Oct 22 06:23:01 2018 +0100 @@ -1342,7 +1342,7 @@ for (Certificate ca: keyStore.getCertificateChain(alias)) { if (ca instanceof X509Certificate) { X509Certificate xca = (X509Certificate)ca; - if (!isSelfSigned(xca)) { + if (!KeyStoreUtil.isSelfSigned(xca)) { dumpCert(xca, out); } } @@ -2748,7 +2748,7 @@ // if certificate is self-signed, make sure it verifies boolean selfSigned = false; - if (isSelfSigned(cert)) { + if (KeyStoreUtil.isSelfSigned(cert)) { cert.verify(cert.getPublicKey()); selfSigned = true; } @@ -3052,25 +3052,6 @@ } /** - * Returns true if the certificate is self-signed, false otherwise. - */ - private boolean isSelfSigned(X509Certificate cert) { - return signedBy(cert, cert); - } - - private boolean signedBy(X509Certificate end, X509Certificate ca) { - if (!ca.getSubjectDN().equals(end.getIssuerDN())) { - return false; - } - try { - end.verify(ca.getPublicKey()); - return true; - } catch (Exception e) { - return false; - } - } - - /** * Locates a signer for a given certificate from a given keystore and * returns the signer's certificate. * @param cert the certificate whose signer is searched, not null @@ -3411,7 +3392,7 @@ // find a cert in the reply who signs thisCert int j; for (j=i; j<replyCerts.length; j++) { - if (signedBy(thisCert, (X509Certificate)replyCerts[j])) { + if (KeyStoreUtil.signedBy(thisCert, (X509Certificate)replyCerts[j])) { tmpCert = replyCerts[i]; replyCerts[i] = replyCerts[j]; replyCerts[j] = tmpCert; @@ -3569,7 +3550,7 @@ private boolean buildChain(Pair<String,X509Certificate> certToVerify, Vector<Pair<String,X509Certificate>> chain, Hashtable<Principal, Vector<Pair<String,X509Certificate>>> certs) { - if (isSelfSigned(certToVerify.snd)) { + if (KeyStoreUtil.isSelfSigned(certToVerify.snd)) { // reached self-signed root cert; // no verification needed because it's trusted. chain.addElement(certToVerify);
--- a/src/share/classes/sun/security/util/SignatureFileVerifier.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/classes/sun/security/util/SignatureFileVerifier.java Mon Oct 22 06:23:01 2018 +0100 @@ -725,7 +725,8 @@ if (signers == null) { signers = new ArrayList<>(); } - // Append the new code signer + // Append the new code signer. If timestamp is invalid, this + // jar will be treated as unsigned. signers.add(new CodeSigner(certChain, info.getTimestamp())); if (debug != null) {
--- a/src/share/lib/security/java.security-linux Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/lib/security/java.security-linux Mon Oct 22 06:23:01 2018 +0100 @@ -556,8 +556,8 @@ # # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 -jdk.tls.disabledAlgorithms=SSLv3, MD5withRSA, DH keySize < 1024, \ - EC keySize < 224, DES40_CBC, RC4_40, 3DES_EDE_CBC +jdk.tls.disabledAlgorithms=SSLv3, DES, MD5withRSA, DH keySize < 1024, \ + EC keySize < 224, RC4_40, 3DES_EDE_CBC # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation.
--- a/src/share/lib/security/java.security-macosx Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/lib/security/java.security-macosx Mon Oct 22 06:23:01 2018 +0100 @@ -561,8 +561,8 @@ # # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 -jdk.tls.disabledAlgorithms=SSLv3, MD5withRSA, DH keySize < 1024, \ - EC keySize < 224, DES40_CBC, RC4_40, 3DES_EDE_CBC +jdk.tls.disabledAlgorithms=SSLv3, DES, MD5withRSA, DH keySize < 1024, \ + EC keySize < 224, RC4_40, 3DES_EDE_CBC # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation.
--- a/src/share/lib/security/java.security-solaris Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/lib/security/java.security-solaris Mon Oct 22 06:23:01 2018 +0100 @@ -560,8 +560,8 @@ # # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 -jdk.tls.disabledAlgorithms=SSLv3, MD5withRSA, DH keySize < 1024, \ - EC keySize < 224, DES40_CBC, RC4_40, 3DES_EDE_CBC +jdk.tls.disabledAlgorithms=SSLv3, DES, MD5withRSA, DH keySize < 1024, \ + EC keySize < 224, RC4_40, 3DES_EDE_CBC # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation.
--- a/src/share/lib/security/java.security-windows Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/lib/security/java.security-windows Mon Oct 22 06:23:01 2018 +0100 @@ -561,8 +561,8 @@ # # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 -jdk.tls.disabledAlgorithms=SSLv3, MD5withRSA, DH keySize < 1024, \ - EC keySize < 224, DES40_CBC, RC4_40, 3DES_EDE_CBC +jdk.tls.disabledAlgorithms=SSLv3, DES, MD5withRSA, DH keySize < 1024, \ + EC keySize < 224, RC4_40, 3DES_EDE_CBC # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation.
--- a/src/share/native/sun/awt/libpng/CHANGES Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/CHANGES Mon Oct 22 06:23:01 2018 +0100 @@ -1,4 +1,3 @@ -#if 0 CHANGES - changes for libpng version 0.1 [March 29, 1995] @@ -833,7 +832,7 @@ Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes which are no longer used. Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is - defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED + defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXt_SUPPORTED is defined. Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory overrun when old applications fill the info_ptr->text structure directly. @@ -1454,7 +1453,7 @@ sequential read support. Added some "#if PNG_WRITE_SUPPORTED" blocks. Added #ifdef to remove some redundancy in png_malloc_default(). - Use png_malloc instead of png_zalloc to allocate the pallete. + Use png_malloc instead of png_zalloc to allocate the palette. Version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] Fixed buffer overflow vulnerability (CVE-2004-0597) in png_handle_tRNS(). @@ -3259,7 +3258,7 @@ Revised PNG_EXPORTA macro to not use an empty parameter, to accommodate the old VisualC++ preprocessor. Turned on interlace handling in png_read_png(). - Fixed gcc pendantic warnings. + Fixed gcc pedantic warnings. Handle longjmp in Cygwin. Fixed png_get_current_row_number() in the interlaced case. Cleaned up ALPHA flags and transformations. @@ -3359,7 +3358,7 @@ Pass "" instead of '\0' to png_default_error() in png_err(). This mistake was introduced in libpng-1.2.20beta01. This fixes CVE-2011-2691. Added PNG_WRITE_OPTIMIZE_CMF_SUPPORTED macro to make the zlib "CMF" byte - optimization configureable. + optimization configurable. IDAT compression failed if preceded by a compressed text chunk (bug introduced in libpng-1.5.3beta01-02). This was because the attempt to reset the zlib stream in png_write_IDAT happened after the first IDAT @@ -3643,7 +3642,7 @@ Fixed bug in png_write_chunk_header() debug print, introduced in 1.5.6beta01. Version 1.5.6beta06 [October 17, 2011] - Removed two redundant tests for unitialized row. + Removed two redundant tests for uninitialized row. Fixed a relatively harmless memory overwrite in compressed text writing with a 1 byte zlib buffer. Add ability to call png_read_update_info multiple times to pngvalid.c. @@ -3689,7 +3688,7 @@ crash. The pngmem.c implementation of png_malloc() included a cast to png_size_t which would fail on large allocations on 16-bit systems. Fix for the preprocessor of the Intel C compiler. The preprocessor - splits adjacent @ signs with a space; this changes the concatentation + splits adjacent @ signs with a space; this changes the concatenation token from @-@-@ to PNG_JOIN; that should work with all compiler preprocessors. Paeth filter speed improvements from work by Siarhei Siamashka. This @@ -3735,7 +3734,7 @@ gray (on palette) itself. Fixes for C++ compilation using g++ When libpng source is compiled using g++. The compiler imposes C++ rules on the C source; thus it - is desireable to make the source work with either C or C++ rules + is desirable to make the source work with either C or C++ rules without throwing away useful error information. This change adds png_voidcast to allow C semantic (void*) cases or the corresponding C++ static_cast operation, as appropriate. @@ -4061,7 +4060,7 @@ possible to call png_inflate() incrementally. A warning is no longer issued if the language tag or translated keyword in the iTXt chunk has zero length. - If benign errors are disabled use maximum window on ancilliary inflate. + If benign errors are disabled use maximum window on ancillary inflate. This works round a bug introduced in 1.5.4 where compressed ancillary chunks could end up with a too-small windowBits value in the deflate header. @@ -4176,7 +4175,7 @@ declared even though the functions are never actually defined. This change provides a dummy definition so that the declarations work, yet any implementation will fail to compile because of an incomplete type. - Re-eliminated the use of strcpy() in pngtest.c. An unncessary use of + Re-eliminated the use of strcpy() in pngtest.c. An unnecessary use of strcpy() was accidentally re-introduced in libpng16; this change replaces it with strncpy(). Eliminated use of png_sizeof(); use sizeof() instead. @@ -4309,7 +4308,7 @@ resulting in VS2010 having to update the files. Removed non-working ICC profile support code that was mostly added to libpng-1.6.0beta29 and beta30. There was too much code for too little - gain; implementing full ICC color correction may be desireable but is left + gain; implementing full ICC color correction may be desirable but is left up to applications. Version 1.6.0beta32 [November 25, 2012] @@ -4592,7 +4591,7 @@ the optimizations ('check' vs 'api') are exposed in the public header files except that the new setting PNG_ARM_NEON_OPT documents how libpng makes the decision about whether or not to use the optimizations. - Protect symbol prefixing against CC/CPPFLAGS/CFLAGS useage. + Protect symbol prefixing against CC/CPPFLAGS/CFLAGS usage. Previous iOS/Xcode fixes for the ARM NEON optimizations moved the test on __ARM_NEON__ from configure time to compile time. This breaks symbol prefixing because the definition of the special png_init_filter_functions @@ -5635,7 +5634,7 @@ to All and adds a list of the warnings that need to be turned off. This is semi-documentary; the intent is to tell libpng users which warnings have been examined and judged non-fixable at present. The warning about - structure padding is fixable, but it would be a signficant change (moving + structure padding is fixable, but it would be a significant change (moving structure members around). Version 1.6.24beta03 [July 4, 2016] @@ -5761,7 +5760,9 @@ if built with zlib-1.2.8.1. Version 1.6.27rc01 [December 27, 2016] - Control ADLER32 checking with new PNG_IGNORE_ADLER32 option. + Control ADLER32 checking with new PNG_IGNORE_ADLER32 option. Fixes + an endless loop when handling erroneous ADLER32 checksums; bug + introduced in libpng-1.6.26. Removed the use of a macro containing the pre-processor 'defined' operator. It is unclear whether this is valid; a macro that "generates" 'defined' is not permitted, but the use of the word @@ -5779,7 +5780,7 @@ Added option to Cmake build allowing a custom location of zlib to be specified in a scenario where libpng is being built as a subproject alongside zlib by another project (Sam Serrels). - Changed png_ptr->options from a png_byte to png_uint_32, to accomodate + Changed png_ptr->options from a png_byte to png_uint_32, to accommodate up to 16 options. Version 1.6.28rc02 [January 4, 2017] @@ -5794,11 +5795,277 @@ Version 1.6.28 [January 5, 2017] No changes. +Version 1.6.29beta01 [January 12, 2017] + Readded "include(GNUInstallDirs)" to CMakeLists.txt (Gianfranco Costamagna). + Moved SSE2 optimization code into the main libpng source directory. + Configure libpng with "configure --enable-intel-sse" or compile + libpng with "-DPNG_INTEL_SSE" in CPPFLAGS to enable it. + Simplified conditional compilation in pngvalid.c, for AIX (Michael Felt). + +Version 1.6.29beta02 [February 22, 2017] + Avoid conditional directives that break statements in pngrutil.c (Romero + Malaquias) + The contrib/examples/pngtopng.c recovery code was in the wrong "if" + branches; the comments were correct. + Added code for PowerPC VSX optimisation (Vadim Barkov). + +Version 1.6.29beta03 [March 1, 2017] + Avoid potential overflow of shift operations in png_do_expand() (Aaron Boxer). + Change test ZLIB_VERNUM >= 0x1281 to ZLIB_VERNUM >= 0x1290 in pngrutil.c + because Solaris 11 distributes zlib-1.2.8.f that is older than 1.2.8.1, + as suggested in zlib FAQ, item 24. + Suppress clang warnings about implicit sign changes in png.c + +Version 1.6.29 [March 16, 2017] + No changes. + +Version 1.6.30beta01 [April 1, 2017] + Added missing "$(CPPFLAGS)" to the compile line for c.pic.o in + makefile.linux and makefile.solaris-x86 (Cosmin). + Revised documentation of png_get_error_ptr() in the libpng manual. + Silence clang -Wcomma and const drop warnings (Viktor Szakats). + Update Sourceforge URLs in documentation (https instead of http). + +Version 1.6.30beta02 [April 22, 2017] + Document need to check for integer overflow when allocating a pixel + buffer for multiple rows in contrib/gregbook, contrib/pngminus, + example.c, and in the manual (suggested by Jaeseung Choi). This + is similar to the bug reported against pngquant in CVE-2016-5735. + Removed reference to the obsolete PNG_SAFE_LIMITS macro in the documentation. + +Version 1.6.30beta03 [May 22, 2017] + Check for integer overflow in contrib/visupng and contrib/tools/genpng. + Do not double evaluate CMAKE_SYSTEM_PROCESSOR in CMakeLists.txt. + Test CMAKE_HOST_WIN32 instead of WIN32 in CMakeLists.txt. + Fix some URL in documentation. + +Version 1.6.30beta04 [June 7, 2017] + Avoid writing an empty IDAT when the last IDAT exactly fills the + compression buffer (bug report by Brian Baird). This bug was + introduced in libpng-1.6.0. + +Version 1.6.30rc01 [June 14, 2017] + No changes. + +Version 1.6.30rc02 [June 25, 2017] + Update copyright year in pnglibconf.h, make ltmain.sh executable. + Add a reference to the libpng.download site in README. + +Version 1.6.30 [June 28, 2017] + No changes. + +Version 1.6.31beta01 [July 5, 2017] + Guard the definition of _POSIX_SOURCE in pngpriv.h (AIX already defines it; + bug report by Michael Felt). + Revised pngpriv.h to work around failure to compile arm/filter_neon.S + ("typedef" directive is unrecognized by the assembler). The problem + was introduced in libpng-1.6.30beta01. + Added "Requires: zlib" to libpng.pc.in (Pieter Neerincx). + Added special case for FreeBSD in arm/filter_neon.S (Maya Rashish). + +Version 1.6.31beta02 [July 8, 2017] + Added instructions for disabling hardware optimizations in INSTALL. + Added "--enable-hardware-optimizations" configuration flag to enable + or disable all hardware optimizations with one flag. + +Version 1.6.31beta03 [July 9, 2017] + Updated CMakeLists.txt to add INTEL_SSE and MIPS_MSA platforms. + Changed "int" to "png_size_t" in intel/filter_sse2.c to prevent + possible integer overflow (Bug report by John Bowler). + Quieted "declaration after statement" warnings in intel/filter_sse2.c. + Added scripts/makefile-linux-opt, which has hardware optimizations enabled. + +Version 1.6.31beta04 [July 11, 2017] + Removed one of the GCC-7.1.0 'strict-overflow' warnings that result when + integers appear on both sides of a compare. Worked around the others by + forcing the strict-overflow setting in the relevant functions to a level + where they are not reported (John Bowler). + Changed "FALL THROUGH" comments to "FALLTHROUGH" because GCC doesn't like + the space. + Worked around some C-style casts from (void*) because g++ 5.4.0 objects + to them. + Increased the buffer size for 'sprint' to pass the gcc 7.1.0 'sprint + overflow' check that is on by default with -Wall -Wextra. + +Version 1.6.31beta05 [July 13, 2017] + Added eXIf chunk support. + +Version 1.6.31beta06 [July 17, 2017] + Added a minimal eXIf chunk (with Orientation and FocalLengthIn35mmFilm + tags) to pngtest.png. + +Version 1.6.31beta07 [July 18, 2017] + Revised the eXIf chunk in pngtest.png to fix "Bad IFD1 Directory" warning. + +Version 1.6.31rc01 [July 19, 2017] + No changes. + +Version 1.6.31rc02 [July 25, 2017] + Fixed typo in example.c (png_free_image should be png_image_free) (Bug + report by John Smith) + +Version 1.6.31 [July 27, 2017] + No changes. + +Version 1.6.32beta01 [July 31, 2017] + Avoid possible NULL dereference in png_handle_eXIf when benign_errors + are allowed. Avoid leaking the input buffer "eXIf_buf". + Eliminated png_ptr->num_exif member from pngstruct.h and added num_exif + to arguments for png_get_eXIf() and png_set_eXIf(). + Added calls to png_handle_eXIf(() in pngread.c and png_write_eXIf() in + pngwrite.c, and made various other fixes to png_write_eXIf(). + Changed name of png_get_eXIF and png_set_eXIf() to png_get_eXIf_1() and + png_set_eXIf_1(), respectively, to avoid breaking API compatibility + with libpng-1.6.31. + +Version 1.6.32beta02 [August 1, 2017] + Updated contrib/libtests/pngunknown.c with eXIf chunk. + +Version 1.6.32beta03 [August 2, 2017] + Initialized btoa[] in pngstest.c + Stop memory leak when returning from png_handle_eXIf() with an error + (Bug report from the OSS-fuzz project). + +Version 1.6.32beta04 [August 2, 2017] + Replaced local eXIf_buf with info_ptr-eXIf_buf in png_handle_eXIf(). + Update libpng.3 and libpng-manual.txt about eXIf functions. + +Version 1.6.32beta05 [August 2, 2017] + Restored png_get_eXIf() and png_set_eXIf() to maintain API compatibility. + +Version 1.6.32beta06 [August 2, 2017] + Removed png_get_eXIf_1() and png_set_eXIf_1(). + +Version 1.6.32beta07 [August 3, 2017] + Check length of all chunks except IDAT against user limit to fix an + OSS-fuzz issue (Fixes CVE-2017-12652). + +Version 1.6.32beta08 [August 3, 2017] + Check length of IDAT against maximum possible IDAT size, accounting + for height, rowbytes, interlacing and zlib/deflate overhead. + Restored png_get_eXIf_1() and png_set_eXIf_1(), because strlen(eXIf_buf) + does not work (the eXIf chunk data can contain zeroes). + +Version 1.6.32beta09 [August 3, 2017] + Require cmake-2.8.8 in CMakeLists.txt. Revised symlink creation, + no longer using deprecated cmake LOCATION feature (Clifford Yapp). + Fixed five-byte error in the calculation of IDAT maximum possible size. + +Version 1.6.32beta10 [August 5, 2017] + Moved chunk-length check into a png_check_chunk_length() private + function (Suggested by Max Stepin). + Moved bad pngs from tests to contrib/libtests/crashers + Moved testing of bad pngs into a separate tests/pngtest-badpngs script + Added the --xfail (expected FAIL) option to pngtest.c. It writes XFAIL + in the output but PASS for the libpng test. + Require cmake-3.0.2 in CMakeLists.txt (Clifford Yapp). + Fix "const" declaration info_ptr argument to png_get_eXIf_1() and the + num_exif argument to png_get_eXIf_1() (Github Issue 171). + +Version 1.6.32beta11 [August 7, 2017] + Added "eXIf" to "chunks_to_ignore[]" in png_set_keep_unknown_chunks(). + Added huge_IDAT.png and empty_ancillary_chunks.png to testpngs/crashers. + Make pngtest --strict, --relax, --xfail options imply -m (multiple). + Removed unused chunk_name parameter from png_check_chunk_length(). + Relocated setting free_me for eXIf data, to stop an OSS-fuzz leak. + Initialize profile_header[] in png_handle_iCCP() to fix OSS-fuzz issue. + Initialize png_ptr->row_buf[0] to 255 in png_read_row() to fix OSS-fuzz UMR. + Attempt to fix a UMR in png_set_text_2() to fix OSS-fuzz issue. + Increase minimum zlib stream from 9 to 14 in png_handle_iCCP(), to account + for the minimum 'deflate' stream, and relocate the test to a point + after the keyword has been read. + Check that the eXIf chunk has at least 2 bytes and begins with "II" or "MM". + +Version 1.6.32rc01 [August 18, 2017] + Added a set of "huge_xxxx_chunk.png" files to contrib/testpngs/crashers, + one for each known chunk type, with length = 2GB-1. + Check for 0 return from png_get_rowbytes() and added some (size_t) typecasts + in contrib/pngminus/*.c to stop some Coverity issues (162705, 162706, + and 162707). + Renamed chunks in contrib/testpngs/crashers to avoid having files whose + names differ only in case; this causes problems with some platforms + (github issue #172). + +Version 1.6.32rc02 [August 22, 2017] + Added contrib/oss-fuzz directory which contains files used by the oss-fuzz + project (https://github.com/google/oss-fuzz/tree/master/projects/libpng). + +Version 1.6.32 [August 24, 2017] + No changes. + +Version 1.6.33beta01 [August 28, 2017] + Added PNGMINUS_UNUSED macro to contrib/pngminus/p*.c and added missing + parenthesis in contrib/pngminus/pnm2png.c (bug report by Christian Hesse). + Fixed off-by-one error in png_do_check_palette_indexes() (Bug report + by Mick P., Source Forge Issue #269). + +Version 1.6.33beta02 [September 3, 2017] + Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc + to fix shortlived oss-fuzz issue 3234. + Compute a larger limit on IDAT because some applications write a deflate + buffer for each row (Bug report by Andrew Church). + Use current date (DATE) instead of release-date (RDATE) in last + changed date of contrib/oss-fuzz files. + Enabled ARM support in CMakeLists.txt (Bernd Kuhls). + +Version 1.6.33beta03 [September 14, 2017] + Fixed incorrect typecast of some arguments to png_malloc() and + png_calloc() that were png_uint_32 instead of png_alloc_size_t + (Bug report by "irwir" in Github libpng issue #175). + Use pnglibconf.h.prebuilt when building for ANDROID with cmake (Github + issue 162, by rcdailey). + +Version 1.6.33rc01 [September 20, 2017] + Initialize memory allocated by png_inflate to zero, using memset, to + stop an oss-fuzz "use of uninitialized value" detection in png_set_text_2() + due to truncated iTXt or zTXt chunk. + Initialize memory allocated by png_read_buffer to zero, using memset, to + stop an oss-fuzz "use of uninitialized value" detection in + png_icc_check_tag_table() due to truncated iCCP chunk. + Removed a redundant test (suggested by "irwir" in Github issue #180). + +Version 1.6.33rc02 [September 23, 2017] + Added an interlaced version of each file in contrib/pngsuite. + Relocate new memset() call in pngrutil.c. + Removed more redundant tests (suggested by "irwir" in Github issue #180). + Add support for loading images with associated alpha in the Simplified + API (Samuel Williams). + +Version 1.6.33 [September 28, 2017] + Revert contrib/oss-fuzz/libpng_read_fuzzer.cc to libpng-1.6.32 state. + Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc + Add end_info structure and png_read_end() to the libpng fuzzer. + +Version 1.6.34 [September 29, 2017] + Removed contrib/pngsuite/i*.png; some of them caused test failures. + +Version 1.6.35beta01 [March 6, 2018] + Restored 21 of the contrib/pngsuite/i*.png, which do not cause test + failures. Placed the remainder in contrib/pngsuite/interlaced/i*.png. + Added calls to png_set_*() transforms commonly used by browsers to + the fuzzer. + Removed some unnecessary brackets in pngrtran.c + Fixed miscellaneous typos (Patch by github user "luzpaz"). + Change "ASM C" to "C ASM" in CMakeLists.txt + Fixed incorrect handling of bKGD chunk in sub-8-bit files (Cosmin) + Added hardware optimization directories to zip and 7z distributions. + Fixed incorrect bitmask for options. + Fixed many spelling typos. + +Version 1.6.35beta02 [March 28, 2018] + Make png_get_iCCP consistent with man page (allow compression-type argument + to be NULL, bug report by Lenard Szolnoki). + +Version 1.6.35 [July 15, 2018] + Replaced the remaining uses of png_size_t with size_t (Cosmin) + Fixed the calculation of row_factor in png_check_chunk_length + (reported by Thuan Pham in SourceForge issue #278) + Added missing parentheses to a macro definition + (suggested by "irwir" in GitHub issue #216) + Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) -or to glennrp at users.sourceforge.net +to subscribe). Glenn R-P -#endif
--- a/src/share/native/sun/awt/libpng/LICENSE Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/LICENSE Mon Oct 22 06:23:01 2018 +0100 @@ -10,8 +10,8 @@ This code is released under the libpng license. -libpng versions 1.0.7, July 1, 2000 through 1.6.28, January 5, 2017 are -Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson, are +libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are +Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are derived from libpng-1.0.6, and are distributed according to the same disclaimer and license as libpng-1.0.6 with the following individuals added to the list of Contributing Authors: @@ -23,6 +23,8 @@ Gilles Vollant James Yu Mandar Sahastrabuddhe + Google Inc. + Vadim Barkov and with the following additions to the disclaimer: @@ -128,4 +130,4 @@ Glenn Randers-Pehrson glennrp at users.sourceforge.net -January 5, 2017 +July 15, 2018
--- a/src/share/native/sun/awt/libpng/README Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/README Mon Oct 22 06:23:01 2018 +0100 @@ -1,4 +1,4 @@ -README for libpng version 1.6.28 - January 5, 2017 (shared library 16.0) +README for libpng version 1.6.35 - July 15, 2018 (shared library 16.0) See the note about version numbers near the top of png.h See INSTALL for instructions on how to install libpng. @@ -23,7 +23,7 @@ png_uint_32, which will affect shared-library applications that use this function. -To avoid problems with changes to the internals of png info_struct, +To avoid problems with changes to the internals of the png info_struct, new APIs have been made available in 0.95 to avoid direct application access to info_ptr. These functions are the png_set_<chunk> and png_get_<chunk> functions. These functions should be used when @@ -88,11 +88,11 @@ You may also want a copy of the PNG specification. It is available as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find -these at http://www.libpng.org/pub/png/documents/ +these at http://www.libpng.org/pub/png/pngdocs.html . -This code is currently being archived at libpng.sf.net in the -[DOWNLOAD] area, and at ftp://ftp.simplesystems.org. If you can't find it -in any of those places, e-mail me, and I'll help you find it. +This code is currently being archived at libpng.sourceforge.io in the +[DOWNLOAD] area, and at http://libpng.download/src . If you +can't find it in any of those places, e-mail me, and I'll help you find it. I am not a lawyer, but I believe that the Export Control Classification Number (ECCN) for libpng is EAR99, which means not subject to export @@ -118,7 +118,7 @@ Send comments/corrections/commendations to png-mng-implement at lists.sourceforge.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) or to glennrp at users.sourceforge.net +to subscribe). You can't reach Guy, the original libpng author, at the addresses given in previous versions of this document. He and Andreas will @@ -179,14 +179,16 @@ pngwtran.c => Write data transformations pngwutil.c => Write utility functions arm => Contains optimized code for the ARM platform + powerpc => Contains optimized code for the PowerPC platform contrib => Contributions arm-neon => Optimized code for ARM-NEON platform + powerpc-vsx => Optimized code for POWERPC-VSX platform examples => Example programs gregbook => source code for PNG reading and writing, from Greg Roelofs' "PNG: The Definitive Guide", O'Reilly, 1999 - intel => Optimized code for INTEL-SSE2 platform libtests => Test programs + mips-msa => Optimized code for MIPS-MSA platform pngminim => Minimal decoder, encoder, and progressive decoder programs demonstrating use of pngusr.dfa pngminus => Simple pnm2png and png2pnm programs @@ -194,6 +196,8 @@ testpngs tools => Various tools visupng => Contains a MSVC workspace for VisualPng + intel => Optimized code for INTEL-SSE2 platform + mips => Optimized code for MIPS platform projects => Contains project files and workspaces for building a DLL owatcom => Contains a WATCOM project for building libpng
--- a/src/share/native/sun/awt/libpng/png.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/png.c Mon Oct 22 06:23:01 2018 +0100 @@ -29,8 +29,8 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * Last changed in libpng 1.6.28 [January 5, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -42,7 +42,27 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_28 Your_png_h_is_not_version_1_6_28; +typedef png_libpng_version_1_6_35 Your_png_h_is_not_version_1_6_35; + +#ifdef __GNUC__ +/* The version tests may need to be added to, but the problem warning has + * consistently been fixed in GCC versions which obtain wide-spread release. + * The problem is that many versions of GCC rearrange comparison expressions in + * the optimizer in such a way that the results of the comparison will change + * if signed integer overflow occurs. Such comparisons are not permitted in + * ANSI C90, however GCC isn't clever enough to work out that that do not occur + * below in png_ascii_from_fp and png_muldiv, so it produces a warning with + * -Wextra. Unfortunately this is highly dependent on the optimizer and the + * machine architecture so the warning comes and goes unpredictably and is + * impossible to "fix", even were that a good idea. + */ +#if __GNUC__ == 7 && __GNUC_MINOR__ == 1 +#define GCC_STRICT_OVERFLOW 1 +#endif /* GNU 7.1.x */ +#endif /* GNU */ +#ifndef GCC_STRICT_OVERFLOW +#define GCC_STRICT_OVERFLOW 0 +#endif /* Tells libpng that we have already handled the first "num_bytes" bytes * of the PNG file signature. If the PNG data is embedded into another @@ -79,7 +99,7 @@ * PNG signature (this is the same behavior as strcmp, memcmp, etc). */ int PNGAPI -png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check) +png_sig_cmp(png_const_bytep sig, size_t start, size_t num_to_check) { png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; @@ -144,7 +164,7 @@ * trouble of calculating it. */ void /* PRIVATE */ -png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) +png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, size_t length) { int need_crc = 1; @@ -429,7 +449,7 @@ * those cases where it does anything other than a memset. */ PNG_FUNCTION(void,PNGAPI -png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), +png_info_init_3,(png_infopp ptr_ptr, size_t png_info_struct_size), PNG_DEPRECATED) { png_inforp info_ptr = *ptr_ptr; @@ -623,6 +643,26 @@ } #endif +#ifdef PNG_eXIf_SUPPORTED + /* Free any eXIf entry */ + if (((mask & PNG_FREE_EXIF) & info_ptr->free_me) != 0) + { +# ifdef PNG_READ_eXIf_SUPPORTED + if (info_ptr->eXIf_buf) + { + png_free(png_ptr, info_ptr->eXIf_buf); + info_ptr->eXIf_buf = NULL; + } +# endif + if (info_ptr->exif) + { + png_free(png_ptr, info_ptr->exif); + info_ptr->exif = NULL; + } + info_ptr->valid &= ~PNG_INFO_eXIf; + } +#endif + #ifdef PNG_hIST_SUPPORTED /* Free any hIST entry */ if (((mask & PNG_FREE_HIST) & info_ptr->free_me) != 0) @@ -804,15 +844,15 @@ #else # ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.6.28 - January 5, 2017" PNG_STRING_NEWLINE \ - "Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson" \ + "libpng version 1.6.35 - July 15, 2018" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \ PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; # else - return "libpng version 1.6.28 - January 5, 2017\ - Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson\ + return "libpng version 1.6.35 - July 15, 2018\ + Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; # endif @@ -930,7 +970,7 @@ /* The code is the fifth byte after each four byte string. Historically this * code was always searched from the end of the list, this is no longer - * necessary because the 'set' routine handles duplicate entries correcty. + * necessary because the 'set' routine handles duplicate entries correctly. */ do /* num_chunk_list > 0, so at least one */ { @@ -1901,12 +1941,12 @@ */ if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST) return png_icc_profile_error(png_ptr, colorspace, "sRGB", - (unsigned)intent, "invalid sRGB rendering intent"); + (png_alloc_size_t)intent, "invalid sRGB rendering intent"); if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 && colorspace->rendering_intent != intent) return png_icc_profile_error(png_ptr, colorspace, "sRGB", - (unsigned)intent, "inconsistent rendering intents"); + (png_alloc_size_t)intent, "inconsistent rendering intents"); if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0) { @@ -1967,7 +2007,6 @@ if (profile_length < 132) return png_icc_profile_error(png_ptr, colorspace, name, profile_length, "too short"); - return 1; } @@ -2056,7 +2095,7 @@ */ /* Data checks (could be skipped). These checks must be independent of the - * version number; however, the version number doesn't accomodate changes in + * version number; however, the version number doesn't accommodate changes in * the header fields (just the known tags and the interpretation of the * data.) */ @@ -2212,15 +2251,6 @@ * being in range. All defined tag types have an 8 byte header - a 4 byte * type signature then 0. */ - if ((tag_start & 3) != 0) - { - /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is - * only a warning here because libpng does not care about the - * alignment. - */ - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "ICC profile tag start not a multiple of 4"); - } /* This is a hard error; potentially it can cause read outside the * profile. @@ -2228,6 +2258,16 @@ if (tag_start > profile_length || tag_length > profile_length - tag_start) return png_icc_profile_error(png_ptr, colorspace, name, tag_id, "ICC profile tag outside profile"); + + if ((tag_start & 3) != 0) + { + /* CNHP730S.icc shipped with Microsoft Windows 64 violates this; it is + * only a warning here because libpng does not care about the + * alignment. + */ + (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, + "ICC profile tag start not a multiple of 4"); + } } return 1; /* success, maybe with warnings */ @@ -2695,7 +2735,7 @@ #if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) /* ASCII to fp functions */ -/* Check an ASCII formated floating point value, see the more detailed +/* Check an ASCII formatted floating point value, see the more detailed * comments in pngpriv.h */ /* The following is used internally to preserve the sticky flags */ @@ -2703,11 +2743,11 @@ #define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) int /* PRIVATE */ -png_check_fp_number(png_const_charp string, png_size_t size, int *statep, +png_check_fp_number(png_const_charp string, size_t size, int *statep, png_size_tp whereami) { int state = *statep; - png_size_t i = *whereami; + size_t i = *whereami; while (i < size) { @@ -2830,10 +2870,10 @@ /* The same but for a complete string. */ int -png_check_fp_string(png_const_charp string, png_size_t size) +png_check_fp_string(png_const_charp string, size_t size) { int state=0; - png_size_t char_index=0; + size_t char_index=0; if (png_check_fp_number(string, size, &state, &char_index) != 0 && (char_index == size || string[char_index] == 0)) @@ -2860,7 +2900,7 @@ if (power < 0) { if (power < DBL_MIN_10_EXP) return 0; - recip = 1, power = -power; + recip = 1; power = -power; } if (power > 0) @@ -2885,8 +2925,16 @@ /* Function to format a floating point value in ASCII with a given * precision. */ +#if GCC_STRICT_OVERFLOW +#pragma GCC diagnostic push +/* The problem arises below with exp_b10, which can never overflow because it + * comes, originally, from frexp and is therefore limited to a range which is + * typically +/-710 (log2(DBL_MAX)/log2(DBL_MIN)). + */ +#pragma GCC diagnostic warning "-Wstrict-overflow=2" +#endif /* GCC_STRICT_OVERFLOW */ void /* PRIVATE */ -png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, +png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size, double fp, unsigned int precision) { /* We use standard functions from math.h, but not printf because @@ -2938,7 +2986,9 @@ double test = png_pow10(exp_b10+1); if (test <= DBL_MAX) - ++exp_b10, base = test; + { + ++exp_b10; base = test; + } else break; @@ -2952,7 +3002,10 @@ * test on DBL_MAX above. */ fp /= base; - while (fp >= 1) fp /= 10, ++exp_b10; + while (fp >= 1) + { + fp /= 10; ++exp_b10; + } /* Because of the code above fp may, at this point, be * less than .1, this is ok because the code below can @@ -2969,7 +3022,7 @@ */ if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ { - czero = (unsigned int)(-exp_b10); /* PLUS 2 digits: TOTAL 3 */ + czero = 0U-exp_b10; /* PLUS 2 digits: TOTAL 3 */ exp_b10 = 0; /* Dot added below before first output. */ } else @@ -3003,7 +3056,7 @@ /* Rounding up to 10, handle that here. */ if (czero > 0) { - --czero, d = 1; + --czero; d = 1; if (cdigits == 0) --clead; } else @@ -3017,7 +3070,7 @@ else if (ch == 46) { - ch = *--ascii, ++size; + ch = *--ascii; ++size; /* Advance exp_b10 to '1', so that the * decimal point happens after the * previous digit. @@ -3044,7 +3097,9 @@ int ch = *--ascii; if (ch == 46) - ++size, exp_b10 = 1; + { + ++size; exp_b10 = 1; + } /* Else lost a leading zero, so 'exp_b10' is * still ok at (-1) @@ -3080,21 +3135,26 @@ */ if (exp_b10 != (-1)) { - if (exp_b10 == 0) *ascii++ = 46, --size; + if (exp_b10 == 0) + { + *ascii++ = 46; --size; + } /* PLUS 1: TOTAL 4 */ --exp_b10; } - *ascii++ = 48, --czero; + *ascii++ = 48; --czero; } if (exp_b10 != (-1)) { if (exp_b10 == 0) - *ascii++ = 46, --size; /* counted above */ + { + *ascii++ = 46; --size; /* counted above */ + } --exp_b10; } - *ascii++ = (char)(48 + (int)d), ++cdigits; + *ascii++ = (char)(48 + (int)d); ++cdigits; } } while (cdigits+czero < precision+clead && fp > DBL_MIN); @@ -3103,7 +3163,7 @@ /* Check for an exponent, if we don't need one we are * done and just need to terminate the string. At - * this point exp_b10==(-1) is effectively if flag - it got + * this point exp_b10==(-1) is effectively a flag - it got * to '-1' because of the decrement after outputting * the decimal point above (the exponent required is * *not* -1!) @@ -3117,7 +3177,7 @@ * zeros were *not* output, so this doesn't increase * the output count. */ - while (--exp_b10 >= 0) *ascii++ = 48; + while (exp_b10-- > 0) *ascii++ = 48; *ascii = 0; @@ -3135,7 +3195,7 @@ */ size -= cdigits; - *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */ + *ascii++ = 69; --size; /* 'E': PLUS 1 TOTAL 2+precision */ /* The following use of an unsigned temporary avoids ambiguities in * the signed arithmetic on exp_b10 and permits GCC at least to do @@ -3146,12 +3206,12 @@ if (exp_b10 < 0) { - *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ - uexp_b10 = (unsigned int)(-exp_b10); + *ascii++ = 45; --size; /* '-': PLUS 1 TOTAL 3+precision */ + uexp_b10 = 0U-exp_b10; } else - uexp_b10 = (unsigned int)exp_b10; + uexp_b10 = 0U+exp_b10; cdigits = 0; @@ -3194,6 +3254,9 @@ /* Here on buffer too small. */ png_error(png_ptr, "ASCII conversion buffer too small"); } +#if GCC_STRICT_OVERFLOW +#pragma GCC diagnostic pop +#endif /* GCC_STRICT_OVERFLOW */ # endif /* FLOATING_POINT */ @@ -3202,7 +3265,7 @@ */ void /* PRIVATE */ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, - png_size_t size, png_fixed_point fp) + size_t size, png_fixed_point fp) { /* Require space for 10 decimal digits, a decimal point, a minus sign and a * trailing \0, 13 characters: @@ -3213,7 +3276,9 @@ /* Avoid overflow here on the minimum integer. */ if (fp < 0) - *ascii++ = 45, num = (png_uint_32)(-fp); + { + *ascii++ = 45; num = (png_uint_32)(-fp); + } else num = (png_uint_32)fp; @@ -3251,7 +3316,10 @@ * then ndigits digits to first: */ i = 5; - while (ndigits < i) *ascii++ = 48, --i; + while (ndigits < i) + { + *ascii++ = 48; --i; + } while (ndigits >= first) *ascii++ = digits[--ndigits]; /* Don't output the trailing zeros! */ } @@ -3302,6 +3370,15 @@ * the nearest .00001). Overflow and divide by zero are signalled in * the result, a boolean - true on success, false on overflow. */ +#if GCC_STRICT_OVERFLOW /* from above */ +/* It is not obvious which comparison below gets optimized in such a way that + * signed overflow would change the result; looking through the code does not + * reveal any tests which have the form GCC complains about, so presumably the + * optimizer is moving an add or subtract into the 'if' somewhere. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic warning "-Wstrict-overflow=2" +#endif /* GCC_STRICT_OVERFLOW */ int png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, png_int_32 divisor) @@ -3416,6 +3493,9 @@ return 0; } +#if GCC_STRICT_OVERFLOW +#pragma GCC diagnostic pop +#endif /* GCC_STRICT_OVERFLOW */ #endif /* READ_GAMMA || INCH_CONVERSIONS */ #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) @@ -3709,7 +3789,7 @@ * of getting this accuracy in practice. * * To deal with this the following exp() function works out the exponent of the - * frational part of the logarithm by using an accurate 32-bit value from the + * fractional part of the logarithm by using an accurate 32-bit value from the * top four fractional bits then multiplying in the remaining bits. */ static const png_uint_32 @@ -4288,13 +4368,13 @@ if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT && (option & 1) == 0) { - png_uint_32 mask = 3 << option; - png_uint_32 setting = (2 + (onoff != 0)) << option; + png_uint_32 mask = 3U << option; + png_uint_32 setting = (2U + (onoff != 0)) << option; png_uint_32 current = png_ptr->options; - png_ptr->options = (png_uint_32)(((current & ~mask) | setting) & 0xff); - - return (current & mask) >> option; + png_ptr->options = (png_uint_32)((current & ~mask) | setting); + + return (int)(current & mask) >> option; } return PNG_OPTION_INVALID; @@ -4306,7 +4386,7 @@ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) /* sRGB conversion tables; these are machine generated with the code in * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the - * specification (see the article at http://en.wikipedia.org/wiki/SRGB) + * specification (see the article at https://en.wikipedia.org/wiki/SRGB) * is used, not the gamma=1/2.2 approximation use elsewhere in libpng. * The sRGB to linear table is exact (to the nearest 16-bit linear fraction). * The inverse (linear to sRGB) table has accuracies as follows:
--- a/src/share/native/sun/awt/libpng/png.h Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/png.h Mon Oct 22 06:23:01 2018 +0100 @@ -29,9 +29,9 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * libpng version 1.6.28, January 5, 2017 + * libpng version 1.6.35, July 15, 2018 * - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -40,7 +40,7 @@ * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.6.28, January 5, 2017: + * libpng versions 0.97, January 1998, through 1.6.35, July 15, 2018: * Glenn Randers-Pehrson. * See also "Contributing Authors", below. */ @@ -53,8 +53,8 @@ * * This code is released under the libpng license. * - * libpng versions 1.0.7, July 1, 2000 through 1.6.28, January 5, 2017 are - * Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson, are + * libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are * derived from libpng-1.0.6, and are distributed according to the same * disclaimer and license as libpng-1.0.6 with the following individuals * added to the list of Contributing Authors: @@ -66,6 +66,8 @@ * Gilles Vollant * James Yu * Mandar Sahastrabuddhe + * Google Inc. + * Vadim Barkov * * and with the following additions to the disclaimer: * @@ -103,9 +105,6 @@ * Greg Roelofs * Tom Tanner * - * Some files in the "scripts" directory have other copyright owners - * but are released under this license. - * * libpng versions 0.5, May 1995, through 0.88, January 1996, are * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * @@ -235,11 +234,11 @@ * ... * 1.0.19 10 10019 10.so.0.19[.0] * ... - * 1.2.57 13 10257 12.so.0.57[.0] + * 1.2.59 13 10257 12.so.0.59[.0] * ... - * 1.5.28 15 10527 15.so.15.28[.0] + * 1.5.30 15 10527 15.so.15.30[.0] * ... - * 1.6.28 16 10628 16.so.16.28[.0] + * 1.6.35 16 10635 16.so.16.35[.0] * * Henceforth the source version will match the shared-library major * and minor numbers; the shared-library major version number will be @@ -260,20 +259,20 @@ * * See libpng.txt or libpng.3 for more information. The PNG specification * is available as a W3C Recommendation and as an ISO Specification, - * <http://www.w3.org/TR/2003/REC-PNG-20031110/ + * <https://www.w3.org/TR/2003/REC-PNG-20031110/ */ /* * Y2K compliance in libpng: * ========================= * - * January 5, 2017 + * July 15, 2018 * * Since the PNG Development group is an ad-hoc body, we can't make * an official declaration. * * This is your unofficial assurance that libpng from version 0.71 and - * upward through 1.6.28 are Y2K compliant. It is my belief that + * upward through 1.6.35 are Y2K compliant. It is my belief that * earlier versions were also Y2K compliant. * * Libpng only has two year fields. One is a 2-byte unsigned integer @@ -335,8 +334,8 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.28" -#define PNG_HEADER_VERSION_STRING " libpng version 1.6.28 - January 5, 2017\n" +#define PNG_LIBPNG_VER_STRING "1.6.35" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.35 - July 15, 2018\n" #define PNG_LIBPNG_VER_SONUM 16 #define PNG_LIBPNG_VER_DLLNUM 16 @@ -344,13 +343,13 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 28 +#define PNG_LIBPNG_VER_RELEASE 35 /* This should match the numeric part of the final component of * PNG_LIBPNG_VER_STRING, omitting any leading zero: */ -#define PNG_LIBPNG_VER_BUILD 0 +#define PNG_LIBPNG_VER_BUILD 02 /* Release Status */ #define PNG_LIBPNG_BUILD_ALPHA 1 @@ -367,7 +366,7 @@ #define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with PNG_LIBPNG_BUILD_PRIVATE */ -#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA /* Careful here. At one time, Guy wanted to use 082, but that would be octal. * We must not include leading zeros. @@ -375,7 +374,7 @@ * version 1.0.0 was mis-numbered 100 instead of 10000). From * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ -#define PNG_LIBPNG_VER 10628 /* 1.6.28 */ +#define PNG_LIBPNG_VER 10635 /* 1.6.35 */ /* Library configuration: these options cannot be changed after * the library has been built. @@ -485,7 +484,7 @@ /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_6_28; +typedef char* png_libpng_version_1_6_35; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * @@ -626,8 +625,8 @@ png_charp key; /* keyword, 1-79 character description of "text" */ png_charp text; /* comment, may be an empty string (ie "") or a NULL pointer */ - png_size_t text_length; /* length of the text string */ - png_size_t itxt_length; /* length of the itxt string */ + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ png_charp lang; /* language code, 0-79 characters or a NULL pointer */ png_charp lang_key; /* keyword translated UTF-8 string, 0 or more @@ -680,7 +679,7 @@ { png_byte name[5]; /* Textual chunk name with '\0' terminator */ png_byte *data; /* Data, should not be modified on read! */ - png_size_t size; + size_t size; /* On write 'location' must be set using the flag values listed below. * Notice that on read it is set by libpng however the values stored have @@ -705,7 +704,7 @@ /* Maximum positive integer used in PNG is (2^31)-1 */ #define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) #define PNG_UINT_32_MAX ((png_uint_32)(-1)) -#define PNG_SIZE_MAX ((png_size_t)(-1)) +#define PNG_SIZE_MAX ((size_t)(-1)) /* These are constants for fixed point values encoded in the * PNG specification manner (x100000) @@ -802,6 +801,7 @@ #define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */ #define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ #define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ +#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ /* This is used for the transformation routines, as some of them * change these values for the row. It also should enable using @@ -810,7 +810,7 @@ typedef struct png_row_info_struct { png_uint_32 width; /* width of row */ - png_size_t rowbytes; /* number of bytes in row */ + size_t rowbytes; /* number of bytes in row */ png_byte color_type; /* color type of row */ png_byte bit_depth; /* bit depth of row */ png_byte channels; /* number of channels (1, 2, 3, or 4) */ @@ -829,7 +829,7 @@ * expected to return the read data in the buffer. */ typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); -typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t)); typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, int)); @@ -966,8 +966,8 @@ * signature, and non-zero otherwise. Having num_to_check == 0 or * start > 7 will always fail (ie return non-zero). */ -PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, - png_size_t num_to_check)); +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, + size_t num_to_check)); /* Simple signature checking function. This is the same as calling * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). @@ -986,11 +986,11 @@ png_error_ptr warn_fn), PNG_ALLOCATED); -PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, +PNG_EXPORT(6, size_t, png_get_compression_buffer_size, (png_const_structrp png_ptr)); PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, - png_size_t size)); + size_t size)); /* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp * match up. @@ -1043,7 +1043,7 @@ /* Write a PNG chunk - size, type, (optional) data, CRC. */ PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep - chunk_name, png_const_bytep data, png_size_t length)); + chunk_name, png_const_bytep data, size_t length)); /* Write the start of a PNG chunk - length and chunk name. */ PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, @@ -1051,7 +1051,7 @@ /* Write the data of a PNG chunk started with png_write_chunk_start(). */ PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, - png_const_bytep data, png_size_t length)); + png_const_bytep data, size_t length)); /* Finish a chunk started with png_write_chunk_start() (includes CRC). */ PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); @@ -1065,7 +1065,7 @@ * the API will be removed in the future. */ PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, - png_size_t png_info_struct_size), PNG_DEPRECATED); + size_t png_info_struct_size), PNG_DEPRECATED); /* Writes all the PNG information before the image. */ PNG_EXPORT(20, void, png_write_info_before_PLTE, @@ -1162,7 +1162,7 @@ * corresponding composited pixel, and the color channels are unassociated * (not premultiplied). The gamma encoded color channels must be scaled * according to the contribution and to do this it is necessary to undo - * the encoding, scale the color values, perform the composition and reencode + * the encoding, scale the color values, perform the composition and re-encode * the values. This is the 'PNG' mode. * * The alternative is to 'associate' the alpha with the color information by @@ -1218,7 +1218,7 @@ * * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); * In this case the output is assumed to be something like an sRGB conformant - * display preceeded by a power-law lookup table of power 1.45. This is how + * display preceded by a power-law lookup table of power 1.45. This is how * early Mac systems behaved. * * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); @@ -1716,7 +1716,7 @@ * chunk will cause an error at this point unless it is to be saved. * positive: The chunk was handled, libpng will ignore/discard it. * - * See "INTERACTION WTIH USER CHUNK CALLBACKS" below for important notes about + * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about * how this behavior will change in libpng 1.7 */ PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, @@ -1741,7 +1741,7 @@ /* Function to be called when data becomes available */ PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, - png_inforp info_ptr, png_bytep buffer, png_size_t buffer_size)); + png_inforp info_ptr, png_bytep buffer, size_t buffer_size)); /* A function which may be called *only* within png_process_data to stop the * processing of any more data. The function returns the number of bytes @@ -1750,7 +1750,7 @@ * 'save' is set to true the routine will first save all the pending data and * will always return 0. */ -PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structrp, int save)); +PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save)); /* A function which may be called *only* outside (after) a call to * png_process_data. It returns the number of bytes of data to skip in the @@ -1814,7 +1814,8 @@ #define PNG_FREE_PLTE 0x1000U #define PNG_FREE_TRNS 0x2000U #define PNG_FREE_TEXT 0x4000U -#define PNG_FREE_ALL 0x7fffU +#define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */ +#define PNG_FREE_ALL 0xffffU #define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ #ifdef PNG_USER_MEM_SUPPORTED @@ -1894,7 +1895,7 @@ png_const_inforp info_ptr, png_uint_32 flag)); /* Returns number of bytes needed to hold a transformed row. */ -PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structrp png_ptr, +PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, png_const_inforp info_ptr)); #ifdef PNG_INFO_IMAGE_SUPPORTED @@ -2033,6 +2034,18 @@ png_fixed_point int_blue_Z)) #endif +#ifdef PNG_eXIf_SUPPORTED +PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *exif)); +PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, const png_bytep exif)); + +PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif)); +PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr, + png_inforp info_ptr, const png_uint_32 num_exif, const png_bytep exif)); +#endif + #ifdef PNG_gAMA_SUPPORTED PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, png_const_inforp info_ptr, double *file_gamma)) @@ -2051,9 +2064,6 @@ #ifdef PNG_hIST_SUPPORTED PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, png_inforp info_ptr, png_uint_16p *hist)); -#endif - -#ifdef PNG_hIST_SUPPORTED PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, png_inforp info_ptr, png_const_uint_16p hist)); #endif @@ -2254,7 +2264,7 @@ * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks * it simply resets the behavior to the libpng default. * - * INTERACTION WTIH USER CHUNK CALLBACKS: + * INTERACTION WITH USER CHUNK CALLBACKS: * The per-chunk handling is always used when there is a png_user_chunk_ptr * callback and the callback returns 0; the chunk is then always stored *unless* * it is critical and the per-chunk setting is other than ALWAYS. Notice that @@ -2673,7 +2683,7 @@ * The simplified API hides the details of both libpng and the PNG file format * itself. It allows PNG files to be read into a very limited number of * in-memory bitmap formats or to be written from the same formats. If these - * formats do not accomodate your needs then you can, and should, use the more + * formats do not accommodate your needs then you can, and should, use the more * sophisticated APIs above - these support a wide variety of in-memory formats * and a wide variety of sophisticated transformations to those formats as well * as a wide variety of APIs to manipulate ancillary information. @@ -2779,7 +2789,7 @@ * * When the simplified API needs to convert between sRGB and linear colorspaces, * the actual sRGB transfer curve defined in the sRGB specification (see the - * article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 + * article at https://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 * approximation used elsewhere in libpng. * * When an alpha channel is present it is expected to denote pixel coverage @@ -2834,6 +2844,8 @@ # define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ #endif +#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */ + /* Commonly used formats have predefined macros. * * First the single byte (sRGB) formats: @@ -3033,7 +3045,7 @@ #endif /* STDIO */ PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, - png_const_voidp memory, png_size_t size)); + png_const_voidp memory, size_t size)); /* The PNG header is read from the given memory buffer. */ PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, @@ -3146,7 +3158,7 @@ * than or equal to the original value. * * If the function returns false and *memory_bytes was not changed an error - * occured during write. If *memory_bytes was changed, or is not 0 if + * occurred during write. If *memory_bytes was changed, or is not 0 if * 'memory' was NULL, the write would have succeeded but for the memory * buffer being too small. *memory_bytes contains the required number of * bytes and will be bigger that the original value. @@ -3230,7 +3242,7 @@ * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given * by the PNG_OPTION_ defines below. * - * HARDWARE: normally hardware capabilites, such as the Intel SSE instructions, + * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions, * are detected at run time, however sometimes it may be impossible * to do this in user mode, in which case it is necessary to discover * the capabilities in an OS specific way. Such capabilities are @@ -3252,7 +3264,10 @@ # define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */ #endif #define PNG_IGNORE_ADLER32 8 -#define PNG_OPTION_NEXT 10 /* Next option - numbers must be even */ +#ifdef PNG_POWERPC_VSX_API_SUPPORTED +# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions supported */ +#endif +#define PNG_OPTION_NEXT 12 /* Next option - numbers must be even */ /* Return values: NOTE: there are four values and 'off' is *not* zero */ #define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ @@ -3276,7 +3291,7 @@ * one to use is one more than this.) */ #ifdef PNG_EXPORT_LAST_ORDINAL - PNG_EXPORT_LAST_ORDINAL(245); + PNG_EXPORT_LAST_ORDINAL(249); #endif #ifdef __cplusplus
--- a/src/share/native/sun/awt/libpng/pngconf.h Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pngconf.h Mon Oct 22 06:23:01 2018 +0100 @@ -29,9 +29,9 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * libpng version 1.6.28, January 5, 2017 + * libpng version 1.6.35, July 15, 2018 * - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -155,7 +155,7 @@ * * These cases only differ if the operating system does not use the C * calling convention, at present this just means the above cases - * (x86 DOS/Windows sytems) and, even then, this does not apply to + * (x86 DOS/Windows systems) and, even then, this does not apply to * Cygwin running on those systems. * * Note that the value must be defined in pnglibconf.h so that what @@ -543,8 +543,10 @@ # error "libpng requires an unsigned 32-bit (or more) type" #endif -/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however, - * requires an ISOC90 compiler and relies on consistent behavior of sizeof. +/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t. + * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant + * behavior of sizeof and ptrdiff_t are required. + * The legacy typedefs are provided here for backwards compatibility. */ typedef size_t png_size_t; typedef ptrdiff_t png_ptrdiff_t; @@ -565,13 +567,12 @@ # endif #endif -/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, and no - * smaller than png_uint_32. Casts from png_size_t or png_uint_32 to - * png_alloc_size_t are not necessary; in fact, it is recommended not to use - * them at all so that the compiler can complain when something turns out to be - * problematic. +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller + * than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are + * not necessary; in fact, it is recommended not to use them at all, so that + * the compiler can complain when something turns out to be problematic. * - * Casts in the other direction (from png_alloc_size_t to png_size_t or + * Casts in the other direction (from png_alloc_size_t to size_t or * png_uint_32) should be explicitly applied; however, we do not expect to * encounter practical situations that require such conversions. * @@ -581,7 +582,7 @@ #ifdef PNG_SMALL_SIZE_T typedef png_uint_32 png_alloc_size_t; #else - typedef png_size_t png_alloc_size_t; + typedef size_t png_alloc_size_t; #endif /* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler @@ -617,8 +618,8 @@ typedef const char * png_const_charp; typedef png_fixed_point * png_fixed_point_p; typedef const png_fixed_point * png_const_fixed_point_p; -typedef png_size_t * png_size_tp; -typedef const png_size_t * png_const_size_tp; +typedef size_t * png_size_tp; +typedef const size_t * png_const_size_tp; #ifdef PNG_STDIO_SUPPORTED typedef FILE * png_FILE_p;
--- a/src/share/native/sun/awt/libpng/pngerror.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pngerror.c Mon Oct 22 06:23:01 2018 +0100 @@ -29,8 +29,8 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.31 [July 27, 2017] + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -191,7 +191,7 @@ case PNG_NUMBER_FORMAT_02u: /* Expects at least 2 digits. */ mincount = 2; - /* FALL THROUGH */ + /* FALLTHROUGH */ case PNG_NUMBER_FORMAT_u: *--end = digits[number % 10]; @@ -201,7 +201,7 @@ case PNG_NUMBER_FORMAT_02x: /* This format expects at least two digits */ mincount = 2; - /* FALL THROUGH */ + /* FALLTHROUGH */ case PNG_NUMBER_FORMAT_x: *--end = digits[number & 0xf];
--- a/src/share/native/sun/awt/libpng/pngget.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pngget.c Mon Oct 22 06:23:01 2018 +0100 @@ -28,9 +28,9 @@ * License version 2 only, as published by the Free Software Foundation. * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: - - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -54,7 +54,7 @@ return(0); } -png_size_t PNGAPI +size_t PNGAPI png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr) { if (png_ptr != NULL && info_ptr != NULL) @@ -395,7 +395,7 @@ static png_fixed_point png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns) { - /* Convert from metres * 1,000,000 to inches * 100,000, meters to + /* Convert from meters * 1,000,000 to inches * 100,000, meters to * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127. * Notice that this can overflow - a warning is output and 0 is * returned. @@ -769,8 +769,7 @@ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) != 0 && - name != NULL && compression_type != NULL && profile != NULL && - proflen != NULL) + name != NULL && profile != NULL && proflen != NULL) { *name = info_ptr->iccp_name; *profile = info_ptr->iccp_profile; @@ -778,11 +777,13 @@ /* This is somewhat irrelevant since the profile data returned has * actually been uncompressed. */ - *compression_type = PNG_COMPRESSION_TYPE_BASE; + if (compression_type != NULL) + *compression_type = PNG_COMPRESSION_TYPE_BASE; return (PNG_INFO_iCCP); } return (0); + } #endif @@ -801,6 +802,35 @@ } #endif +#ifdef PNG_eXIf_SUPPORTED +png_uint_32 PNGAPI +png_get_eXIf(png_const_structrp png_ptr, png_inforp info_ptr, + png_bytep *exif) +{ + png_warning(png_ptr, "png_get_eXIf does not work; use png_get_eXIf_1"); + PNG_UNUSED(info_ptr) + PNG_UNUSED(exif) + return 0; +} + +png_uint_32 PNGAPI +png_get_eXIf_1(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_uint_32 *num_exif, png_bytep *exif) +{ + png_debug1(1, "in %s retrieval function", "eXIf"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_eXIf) != 0 && exif != NULL) + { + *num_exif = info_ptr->num_exif; + *exif = info_ptr->exif; + return (PNG_INFO_eXIf); + } + + return (0); +} +#endif + #ifdef PNG_hIST_SUPPORTED png_uint_32 PNGAPI png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr, @@ -1163,7 +1193,7 @@ } #endif -png_size_t PNGAPI +size_t PNGAPI png_get_compression_buffer_size(png_const_structrp png_ptr) { if (png_ptr == NULL)
--- a/src/share/native/sun/awt/libpng/pnginfo.h Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pnginfo.h Mon Oct 22 06:23:01 2018 +0100 @@ -29,8 +29,8 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * Last changed in libpng 1.6.1 [March 28, 2013] - * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2013,2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -83,10 +83,10 @@ struct png_info_def { /* The following are necessary for every PNG file */ - png_uint_32 width; /* width of image in pixels (from IHDR) */ - png_uint_32 height; /* height of image in pixels (from IHDR) */ - png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ - png_size_t rowbytes; /* bytes needed to hold an untransformed row */ + png_uint_32 width; /* width of image in pixels (from IHDR) */ + png_uint_32 height; /* height of image in pixels (from IHDR) */ + png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ + size_t rowbytes; /* bytes needed to hold an untransformed row */ png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ @@ -213,6 +213,14 @@ png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ #endif +#ifdef PNG_eXIf_SUPPORTED + int num_exif; /* Added at libpng-1.6.31 */ + png_bytep exif; +# ifdef PNG_READ_eXIf_SUPPORTED + png_bytep eXIf_buf; /* Added at libpng-1.6.32 */ +# endif +#endif + #ifdef PNG_hIST_SUPPORTED /* The hIST chunk contains the relative frequency or importance of the * various palette entries, so that a viewer can intelligently select a @@ -267,7 +275,7 @@ /* The sCAL chunk describes the actual physical dimensions of the * subject matter of the graphic. The chunk contains a unit specification * a byte value, and two ASCII strings representing floating-point - * values. The values are width and height corresponsing to one pixel + * values. The values are width and height corresponding to one pixel * in the image. Data values are valid if (valid & PNG_INFO_sCAL) is * non-zero. */
--- a/src/share/native/sun/awt/libpng/pnglibconf.h Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pnglibconf.h Mon Oct 22 06:23:01 2018 +0100 @@ -1,6 +1,11 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file and, per its terms, should not be removed: + * * 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. Oracle designates this @@ -33,9 +38,9 @@ * file and, per its terms, should not be removed: */ -/* libpng version 1.6.28, January 5, 2017 */ +/* libpng version 1.6.35, July 15, 2018 */ -/* Copyright (c) 1998-2016 Glenn Randers-Pehrson */ +/* Copyright (c) 1998-2018 Glenn Randers-Pehrson */ /* This code is released under the libpng license. */ /* For conditions of distribution and use, see the disclaimer */
--- a/src/share/native/sun/awt/libpng/pngpread.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pngpread.c Mon Oct 22 06:23:01 2018 +0100 @@ -29,8 +29,8 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -62,7 +62,7 @@ void PNGAPI png_process_data(png_structrp png_ptr, png_inforp info_ptr, - png_bytep buffer, png_size_t buffer_size) + png_bytep buffer, size_t buffer_size) { if (png_ptr == NULL || info_ptr == NULL) return; @@ -75,7 +75,7 @@ } } -png_size_t PNGAPI +size_t PNGAPI png_process_data_pause(png_structrp png_ptr, int save) { if (png_ptr != NULL) @@ -88,7 +88,7 @@ else { /* This includes any pending saved bytes: */ - png_size_t remaining = png_ptr->buffer_size; + size_t remaining = png_ptr->buffer_size; png_ptr->buffer_size = 0; /* So subtract the saved buffer size, unless all the data @@ -161,8 +161,8 @@ void /* PRIVATE */ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) { - png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ - num_to_check = 8 - num_checked; + size_t num_checked = png_ptr->sig_bytes; /* SAFE, does not exceed 8 */ + size_t num_to_check = 8 - num_checked; if (png_ptr->buffer_size < num_to_check) { @@ -217,6 +217,7 @@ png_crc_read(png_ptr, chunk_tag, 4); png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_check_chunk_length(png_ptr, png_ptr->push_length); png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; } @@ -445,7 +446,7 @@ } void PNGCBAPI -png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, size_t length) { png_bytep ptr; @@ -455,7 +456,7 @@ ptr = buffer; if (png_ptr->save_buffer_size != 0) { - png_size_t save_size; + size_t save_size; if (length < png_ptr->save_buffer_size) save_size = length; @@ -472,7 +473,7 @@ } if (length != 0 && png_ptr->current_buffer_size != 0) { - png_size_t save_size; + size_t save_size; if (length < png_ptr->current_buffer_size) save_size = length; @@ -494,7 +495,7 @@ { if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) { - png_size_t i, istop; + size_t i, istop; png_bytep sp; png_bytep dp; @@ -509,7 +510,7 @@ if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > png_ptr->save_buffer_max) { - png_size_t new_max; + size_t new_max; png_bytep old_buffer; if (png_ptr->save_buffer_size > PNG_SIZE_MAX - @@ -521,7 +522,7 @@ new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; old_buffer = png_ptr->save_buffer; png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, - (png_size_t)new_max); + (size_t)new_max); if (png_ptr->save_buffer == NULL) { @@ -549,7 +550,7 @@ void /* PRIVATE */ png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) + size_t buffer_length) { png_ptr->current_buffer = buffer; png_ptr->current_buffer_size = buffer_length; @@ -589,7 +590,7 @@ if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0) { - png_size_t save_size = png_ptr->save_buffer_size; + size_t save_size = png_ptr->save_buffer_size; png_uint_32 idat_size = png_ptr->idat_size; /* We want the smaller of 'idat_size' and 'current_buffer_size', but they @@ -599,7 +600,7 @@ * will break on either 16-bit or 64-bit platforms. */ if (idat_size < save_size) - save_size = (png_size_t)idat_size; + save_size = (size_t)idat_size; else idat_size = (png_uint_32)save_size; @@ -616,7 +617,7 @@ if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0) { - png_size_t save_size = png_ptr->current_buffer_size; + size_t save_size = png_ptr->current_buffer_size; png_uint_32 idat_size = png_ptr->idat_size; /* We want the smaller of 'idat_size' and 'current_buffer_size', but they @@ -625,7 +626,7 @@ * larger - this cannot overflow. */ if (idat_size < save_size) - save_size = (png_size_t)idat_size; + save_size = (size_t)idat_size; else idat_size = (png_uint_32)save_size; @@ -652,7 +653,7 @@ void /* PRIVATE */ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) + size_t buffer_length) { /* The caller checks for a non-zero buffer length. */ if (!(buffer_length > 0) || buffer == NULL)
--- a/src/share/native/sun/awt/libpng/pngpriv.h Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pngpriv.h Mon Oct 22 06:23:01 2018 +0100 @@ -29,8 +29,8 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -63,7 +63,9 @@ * Windows/Visual Studio) there is no effect; the OS specific tests below are * still required (as of 2011-05-02.) */ -#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ +#endif #ifndef PNG_VERSION_INFO_ONLY /* Standard library headers not required by png.h: */ @@ -218,6 +220,56 @@ # endif #endif +#ifndef PNG_POWERPC_VSX_OPT +# if defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__) +# define PNG_POWERPC_VSX_OPT 2 +# else +# define PNG_POWERPC_VSX_OPT 0 +# endif +#endif + +#ifndef PNG_INTEL_SSE_OPT +# ifdef PNG_INTEL_SSE + /* Only check for SSE if the build configuration has been modified to + * enable SSE optimizations. This means that these optimizations will + * be off by default. See contrib/intel for more details. + */ +# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \ + defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ + (defined(_M_IX86_FP) && _M_IX86_FP >= 2) +# define PNG_INTEL_SSE_OPT 1 +# else +# define PNG_INTEL_SSE_OPT 0 +# endif +# else +# define PNG_INTEL_SSE_OPT 0 +# endif +#endif + +#if PNG_INTEL_SSE_OPT > 0 +# ifndef PNG_INTEL_SSE_IMPLEMENTATION +# if defined(__SSE4_1__) || defined(__AVX__) + /* We are not actually using AVX, but checking for AVX is the best + way we can detect SSE4.1 and SSSE3 on MSVC. + */ +# define PNG_INTEL_SSE_IMPLEMENTATION 3 +# elif defined(__SSSE3__) +# define PNG_INTEL_SSE_IMPLEMENTATION 2 +# elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ + (defined(_M_IX86_FP) && _M_IX86_FP >= 2) +# define PNG_INTEL_SSE_IMPLEMENTATION 1 +# else +# define PNG_INTEL_SSE_IMPLEMENTATION 0 +# endif +# endif + +# if PNG_INTEL_SSE_IMPLEMENTATION > 0 +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2 +# endif +#else +# define PNG_INTEL_SSE_IMPLEMENTATION 0 +#endif + #if PNG_MIPS_MSA_OPT > 0 # define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_msa # ifndef PNG_MIPS_MSA_IMPLEMENTATION @@ -238,6 +290,13 @@ # endif #endif /* PNG_MIPS_MSA_OPT > 0 */ +#ifdef PNG_POWERPC_VSX_API_SUPPORTED +#if PNG_POWERPC_VSX_OPT > 0 +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_vsx +# define PNG_POWERPC_VSX_IMPLEMENTATION 1 +#endif +#endif + /* Is this a build of a DLL where compilation of the object modules requires * different preprocessor settings to those required for a simple library? If @@ -431,6 +490,21 @@ # define png_fixed_error(s1,s2) png_err(s1) #endif +/* Some fixed point APIs are still required even if not exported because + * they get used by the corresponding floating point APIs. This magic + * deals with this: + */ +#ifdef PNG_FIXED_POINT_SUPPORTED +# define PNGFAPI PNGAPI +#else +# define PNGFAPI /* PRIVATE */ +#endif + +#ifndef PNG_VERSION_INFO_ONLY +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ + /* C allows up-casts from (void*) to any pointer and (const void*) to any * pointer to a const object. C++ regards this as a type error and requires an * explicit, static, cast and provides the static_cast<> rune to ensure that @@ -445,25 +519,20 @@ static_cast<type>(static_cast<const void*>(value)) #else # define png_voidcast(type, value) (value) -# define png_constcast(type, value) ((type)(value)) +# ifdef _WIN64 +# ifdef __GNUC__ + typedef unsigned long long png_ptruint; +# else + typedef unsigned __int64 png_ptruint; +# endif +# else + typedef unsigned long png_ptruint; +# endif +# define png_constcast(type, value) ((type)(png_ptruint)(const void*)(value)) # define png_aligncast(type, value) ((void*)(value)) # define png_aligncastconst(type, value) ((const void*)(value)) #endif /* __cplusplus */ -/* Some fixed point APIs are still required even if not exported because - * they get used by the corresponding floating point APIs. This magic - * deals with this: - */ -#ifdef PNG_FIXED_POINT_SUPPORTED -# define PNGFAPI PNGAPI -#else -# define PNGFAPI /* PRIVATE */ -#endif - -#ifndef PNG_VERSION_INFO_ONLY -/* Other defines specific to compilers can go here. Try to keep - * them inside an appropriate ifdef/endif pair for portability. - */ #if defined(PNG_FLOATING_POINT_SUPPORTED) ||\ defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) /* png.c requires the following ANSI-C constants if the conversion of @@ -695,8 +764,8 @@ /* Added to libpng-1.2.6 JB */ #define PNG_ROWBYTES(pixel_bits, width) \ ((pixel_bits) >= 8 ? \ - ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ - (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) + ((size_t)(width) * (((size_t)(pixel_bits)) >> 3)) : \ + (( ((size_t)(width) * ((size_t)(pixel_bits))) + 7) >> 3) ) /* This returns the number of trailing bits in the last byte of a row, 0 if the * last byte is completely full of pixels. It is, in principle, (pixel_bits x @@ -809,6 +878,7 @@ #define png_PLTE PNG_U32( 80, 76, 84, 69) #define png_bKGD PNG_U32( 98, 75, 71, 68) #define png_cHRM PNG_U32( 99, 72, 82, 77) +#define png_eXIf PNG_U32(101, 88, 73, 102) /* registered July 2017 */ #define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */ #define png_gAMA PNG_U32(103, 65, 77, 65) #define png_gIFg PNG_U32(103, 73, 70, 103) @@ -883,7 +953,7 @@ * PNG files the -I directives must match. * * The most likely explanation is that you passed a -I in CFLAGS. This will - * not work; all the preprocessor directories and in particular all the -I + * not work; all the preprocessor directives and in particular all the -I * directives must be in CPPFLAGS. */ #endif @@ -1012,15 +1082,15 @@ */ PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_read_data,(png_structp png_ptr, - png_bytep data, png_size_t length),PNG_EMPTY); + png_bytep data, size_t length),PNG_EMPTY); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr, - png_bytep buffer, png_size_t length),PNG_EMPTY); + png_bytep buffer, size_t length),PNG_EMPTY); #endif PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr, - png_bytep data, png_size_t length),PNG_EMPTY); + png_bytep data, size_t length),PNG_EMPTY); #ifdef PNG_WRITE_FLUSH_SUPPORTED # ifdef PNG_STDIO_SUPPORTED @@ -1034,7 +1104,7 @@ /* Write the "data" buffer to whatever output you are using */ PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr, - png_const_bytep data, png_size_t length),PNG_EMPTY); + png_const_bytep data, size_t length),PNG_EMPTY); /* Read and check the PNG file signature */ PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr, @@ -1046,7 +1116,7 @@ /* Read data from whatever input you are using into the "data" buffer */ PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data, - png_size_t length),PNG_EMPTY); + size_t length),PNG_EMPTY); /* Read bytes into buf, and update png_ptr->crc */ PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf, @@ -1064,7 +1134,7 @@ * since this is the maximum buffer size we can specify. */ PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr, - png_const_bytep ptr, png_size_t length),PNG_EMPTY); + png_const_bytep ptr, size_t length),PNG_EMPTY); #ifdef PNG_WRITE_FLUSH_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY); @@ -1109,6 +1179,11 @@ int intent),PNG_EMPTY); #endif +#ifdef PNG_WRITE_eXIf_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_eXIf,(png_structrp png_ptr, + png_bytep exif, int num_exif),PNG_EMPTY); +#endif + #ifdef PNG_WRITE_iCCP_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr, png_const_charp name, png_const_bytep profile), PNG_EMPTY); @@ -1142,7 +1217,7 @@ /* Chunks that have keywords */ #ifdef PNG_WRITE_tEXt_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_write_tEXt,(png_structrp png_ptr, - png_const_charp key, png_const_charp text, png_size_t text_len),PNG_EMPTY); + png_const_charp key, png_const_charp text, size_t text_len),PNG_EMPTY); #endif #ifdef PNG_WRITE_zTXt_SUPPORTED @@ -1284,6 +1359,38 @@ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); #endif +#if PNG_POWERPC_VSX_OPT > 0 +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_vsx,(png_row_infop row_info, + png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +#endif + +#if PNG_INTEL_SSE_IMPLEMENTATION > 0 +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +#endif + /* Choose the best filter to use and filter the row data */ PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr, png_row_infop row_info),PNG_EMPTY); @@ -1376,6 +1483,11 @@ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); #endif +#ifdef PNG_READ_eXIf_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_eXIf,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + #ifdef PNG_READ_gAMA_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); @@ -1451,8 +1563,11 @@ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); #endif -PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_structrp png_ptr, - png_uint_32 chunk_name),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_const_structrp png_ptr, + const png_uint_32 chunk_name),PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(void,png_check_chunk_length,(png_const_structrp png_ptr, + const png_uint_32 chunk_length),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY); @@ -1495,10 +1610,10 @@ PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr), PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr, - png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); + png_bytep buffer, size_t buffer_length),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_read_IDAT,(png_structrp png_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr, - png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); + png_bytep buffer, size_t buffer_length),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr), PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr, @@ -1768,13 +1883,13 @@ #ifdef PNG_FLOATING_POINT_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_ascii_from_fp,(png_const_structrp png_ptr, - png_charp ascii, png_size_t size, double fp, unsigned int precision), + png_charp ascii, size_t size, double fp, unsigned int precision), PNG_EMPTY); #endif /* FLOATING_POINT */ #ifdef PNG_FIXED_POINT_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, - png_charp ascii, png_size_t size, png_fixed_point fp),PNG_EMPTY); + png_charp ascii, size_t size, png_fixed_point fp),PNG_EMPTY); #endif /* FIXED_POINT */ #endif /* sCAL */ @@ -1867,7 +1982,7 @@ * the problem character.) This has not been tested within libpng. */ PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, - png_size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); + size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); /* This is the same but it checks a complete string and returns true * only if it just contains a floating point number. As of 1.5.4 this @@ -1876,7 +1991,7 @@ * for negative or zero values using the sticky flag. */ PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string, - png_size_t size),PNG_EMPTY); + size_t size),PNG_EMPTY); #endif /* pCAL || sCAL */ #if defined(PNG_GAMMA_SUPPORTED) ||\ @@ -1951,7 +2066,7 @@ png_voidp error_buf; /* Always a jmp_buf at present. */ png_const_bytep memory; /* Memory buffer. */ - png_size_t size; /* Size of the memory buffer. */ + size_t size; /* Size of the memory buffer. */ unsigned int for_write :1; /* Otherwise it is a read structure */ unsigned int owned_file :1; /* We own the file in io_ptr */ @@ -2019,6 +2134,11 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa, (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); #endif + +# if PNG_INTEL_SSE_IMPLEMENTATION > 0 +PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); +# endif #endif PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
--- a/src/share/native/sun/awt/libpng/pngread.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pngread.c Mon Oct 22 06:23:01 2018 +0100 @@ -29,8 +29,8 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -203,6 +203,11 @@ png_handle_cHRM(png_ptr, info_ptr, length); #endif +#ifdef PNG_READ_eXIf_SUPPORTED + else if (chunk_name == png_eXIf) + png_handle_eXIf(png_ptr, info_ptr, length); +#endif + #ifdef PNG_READ_gAMA_SUPPORTED else if (chunk_name == png_gAMA) png_handle_gAMA(png_ptr, info_ptr, length); @@ -562,6 +567,7 @@ png_error(png_ptr, "Invalid attempt to read row data"); /* Fill the row with IDAT data: */ + png_ptr->row_buf[0]=255; /* to force error if no data was found */ png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1); if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) @@ -870,6 +876,11 @@ png_handle_cHRM(png_ptr, info_ptr, length); #endif +#ifdef PNG_READ_eXIf_SUPPORTED + else if (chunk_name == png_eXIf) + png_handle_eXIf(png_ptr, info_ptr, length); +#endif + #ifdef PNG_READ_gAMA_SUPPORTED else if (chunk_name == png_gAMA) png_handle_gAMA(png_ptr, info_ptr, length); @@ -1549,7 +1560,7 @@ #endif /* STDIO */ static void PNGCBAPI -png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) +png_image_memory_read(png_structp png_ptr, png_bytep out, size_t need) { if (png_ptr != NULL) { @@ -1560,7 +1571,7 @@ if (cp != NULL) { png_const_bytep memory = cp->memory; - png_size_t size = cp->size; + size_t size = cp->size; if (memory != NULL && size >= need) { @@ -1579,7 +1590,7 @@ } int PNGAPI png_image_begin_read_from_memory(png_imagep image, - png_const_voidp memory, png_size_t size) + png_const_voidp memory, size_t size) { if (image != NULL && image->version == PNG_IMAGE_VERSION) { @@ -1911,7 +1922,7 @@ { case 4: entry[afirst ? 0 : 3] = (png_uint_16)alpha; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 3: if (alpha < 65535) @@ -1933,7 +1944,7 @@ case 2: entry[1 ^ afirst] = (png_uint_16)alpha; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 1: if (alpha < 65535) @@ -1962,6 +1973,7 @@ { case 4: entry[afirst ? 0 : 3] = (png_byte)alpha; + /* FALLTHROUGH */ case 3: entry[afirst + (2 ^ bgr)] = (png_byte)blue; entry[afirst + 1] = (png_byte)green; @@ -1970,6 +1982,7 @@ case 2: entry[1 ^ afirst] = (png_byte)alpha; + /* FALLTHROUGH */ case 1: entry[afirst] = (png_byte)green; break; @@ -2889,7 +2902,7 @@ case P_sRGB: /* Change to 8-bit sRGB */ png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB); - /* FALL THROUGH */ + /* FALLTHROUGH */ case P_FILE: if (png_ptr->bit_depth > 8) @@ -3207,8 +3220,7 @@ image->colormap_entries == 244 /* 216 + 1 + 27 */) break; - /* goto bad_output; */ - /* FALL THROUGH */ + goto bad_output; default: bad_output: @@ -3776,6 +3788,12 @@ output_gamma = PNG_DEFAULT_sRGB; } + if ((change & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) + { + mode = PNG_ALPHA_OPTIMIZED; + change &= ~PNG_FORMAT_FLAG_ASSOCIATED_ALPHA; + } + /* If 'do_local_background' is set check for the presence of gamma * correction; this is part of the work-round for the libpng bug * described above. @@ -4001,6 +4019,10 @@ else if (do_local_compose != 0) /* internal error */ png_error(png_ptr, "png_image_read: alpha channel lost"); + if ((format & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) { + info_format |= PNG_FORMAT_FLAG_ASSOCIATED_ALPHA; + } + if (info_ptr->bit_depth == 16) info_format |= PNG_FORMAT_FLAG_LINEAR; @@ -4156,7 +4178,7 @@ * * NOTE: this will be changed in 1.7 because PNG_IMAGE_BUFFER_SIZE * will be changed to use png_alloc_size_t; bigger images can be - * accomodated on 64-bit systems. + * accommodated on 64-bit systems. */ if (image->height <= 0xffffffffU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check)
--- a/src/share/native/sun/awt/libpng/pngrio.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pngrio.c Mon Oct 22 06:23:01 2018 +0100 @@ -29,8 +29,8 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -57,7 +57,7 @@ * to read more than 64K on a 16-bit machine. */ void /* PRIVATE */ -png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) +png_read_data(png_structrp png_ptr, png_bytep data, size_t length) { png_debug1(4, "reading %d bytes", (int)length); @@ -75,14 +75,14 @@ * than changing the library. */ void PNGCBAPI -png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +png_default_read_data(png_structp png_ptr, png_bytep data, size_t length) { - png_size_t check; + size_t check; if (png_ptr == NULL) return; - /* fread() returns 0 on error, so it is OK to store this in a png_size_t + /* fread() returns 0 on error, so it is OK to store this in a size_t * instead of an int, which is what fread() actually returns. */ check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr));
--- a/src/share/native/sun/awt/libpng/pngrtran.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pngrtran.c Mon Oct 22 06:23:01 2018 +0100 @@ -29,8 +29,8 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -77,6 +77,7 @@ case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ png_warning(png_ptr, "Can't discard critical data on CRC error"); + /* FALLTHROUGH */ case PNG_CRC_ERROR_QUIT: /* Error/quit */ case PNG_CRC_DEFAULT: @@ -319,7 +320,7 @@ * who use the inverse of the gamma value accidentally! Since some of these * values are reasonable this may have to be changed: * - * 1.6.x: changed from 0.07..3 to 0.01..100 (to accomodate the optimal 16-bit + * 1.6.x: changed from 0.07..3 to 0.01..100 (to accommodate the optimal 16-bit * gamma of 36, and its reciprocal.) */ if (output_gamma < 1000 || output_gamma > 10000000) @@ -457,7 +458,7 @@ int i; png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte)))); for (i = 0; i < num_palette; i++) png_ptr->quantize_index[i] = (png_byte)i; } @@ -474,7 +475,7 @@ /* Initialize an array to sort colors */ png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte)))); /* Initialize the quantize_sort array */ for (i = 0; i < num_palette; i++) @@ -608,9 +609,11 @@ /* Initialize palette index arrays */ png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * + (sizeof (png_byte)))); png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * + (sizeof (png_byte)))); /* Initialize the sort array */ for (i = 0; i < num_palette; i++) @@ -619,7 +622,7 @@ png_ptr->palette_to_index[i] = (png_byte)i; } - hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * + hash = (png_dsortpp)png_calloc(png_ptr, (png_alloc_size_t)(769 * (sizeof (png_dsortp)))); num_new_palette = num_palette; @@ -650,7 +653,7 @@ { t = (png_dsortp)png_malloc_warn(png_ptr, - (png_uint_32)(sizeof (png_dsort))); + (png_alloc_size_t)(sizeof (png_dsort))); if (t == NULL) break; @@ -772,12 +775,12 @@ int num_red = (1 << PNG_QUANTIZE_RED_BITS); int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); - png_size_t num_entries = ((png_size_t)1 << total_bits); + size_t num_entries = ((size_t)1 << total_bits); png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, - (png_uint_32)(num_entries * (sizeof (png_byte)))); - - distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + (png_alloc_size_t)(num_entries * (sizeof (png_byte)))); + + distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries * (sizeof (png_byte)))); memset(distance, 0xff, num_entries * (sizeof (png_byte))); @@ -1281,7 +1284,7 @@ default: case 8: - /* FALL THROUGH (Already 8 bits) */ + /* FALLTHROUGH */ /* (Already 8 bits) */ case 16: /* Already a full 16 bits */ @@ -1342,7 +1345,7 @@ else if (png_ptr->screen_gamma != 0) /* The converse - assume the file matches the screen, note that this - * perhaps undesireable default can (from 1.5.4) be changed by calling + * perhaps undesirable default can (from 1.5.4) be changed by calling * png_set_alpha_mode (even if the alpha handling mode isn't required * or isn't changed from the default.) */ @@ -1910,7 +1913,7 @@ png_ptr->transformations &= ~PNG_SHIFT; - /* significant bits can be in the range 1 to 7 for a meaninful result, if + /* significant bits can be in the range 1 to 7 for a meaningful result, if * the number of significant bits is 0 then no shift is done (this is an * error condition which is silently ignored.) */ @@ -2176,8 +2179,8 @@ { case 1: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); - png_bytep dp = row + (png_size_t)row_width - 1; + png_bytep sp = row + (size_t)((row_width - 1) >> 3); + png_bytep dp = row + (size_t)row_width - 1; png_uint_32 shift = 7U - ((row_width + 7U) & 0x07); for (i = 0; i < row_width; i++) { @@ -2200,8 +2203,8 @@ case 2: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); - png_bytep dp = row + (png_size_t)row_width - 1; + png_bytep sp = row + (size_t)((row_width - 1) >> 2); + png_bytep dp = row + (size_t)row_width - 1; png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1); for (i = 0; i < row_width; i++) { @@ -2223,8 +2226,8 @@ case 4: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); - png_bytep dp = row + (png_size_t)row_width - 1; + png_bytep sp = row + (size_t)((row_width - 1) >> 1); + png_bytep dp = row + (size_t)row_width - 1; png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2); for (i = 0; i < row_width; i++) { @@ -2488,95 +2491,94 @@ static void png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) { + png_uint_32 row_width = row_info->width; + png_debug(1, "in png_do_read_swap_alpha"); + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { - png_uint_32 row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) { - /* This converts from RGBA to ARGB */ - if (row_info->bit_depth == 8) + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; } + } #ifdef PNG_READ_16BIT_SUPPORTED - /* This converts from RRGGBBAA to AARRGGBB */ - else + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; } + } #endif - } - - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) { - /* This converts from GA to AG */ - if (row_info->bit_depth == 8) + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; } + } #ifdef PNG_READ_16BIT_SUPPORTED - /* This converts from GGAA to AAGG */ - else + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; } + } #endif - } } } #endif @@ -2706,8 +2708,8 @@ if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from G to GX */ - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width; + png_bytep dp = sp + (size_t)row_width; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2722,8 +2724,8 @@ else { /* This changes the data from G to XG */ - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width; + png_bytep dp = sp + (size_t)row_width; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2741,8 +2743,8 @@ if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from GG to GGXX */ - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 2; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2760,8 +2762,8 @@ else { /* This changes the data from GG to XXGG */ - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 2; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2783,8 +2785,8 @@ if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from RGB to RGBX */ - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width * 3; + png_bytep dp = sp + (size_t)row_width; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2801,8 +2803,8 @@ else { /* This changes the data from RGB to XRGB */ - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width * 3; + png_bytep dp = sp + (size_t)row_width; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2822,8 +2824,8 @@ if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from RRGGBB to RRGGBBXX */ - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 6; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2845,8 +2847,8 @@ else { /* This changes the data from RRGGBB to XXRRGGBB */ - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 6; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2887,8 +2889,8 @@ if (row_info->bit_depth == 8) { /* This changes G to RGB */ - png_bytep sp = row + (png_size_t)row_width - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width - 1; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(dp--) = *sp; @@ -2900,8 +2902,8 @@ else { /* This changes GG to RRGGBB */ - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; + png_bytep sp = row + (size_t)row_width * 2 - 1; + png_bytep dp = sp + (size_t)row_width * 4; for (i = 0; i < row_width; i++) { *(dp--) = *sp; @@ -2919,8 +2921,8 @@ if (row_info->bit_depth == 8) { /* This changes GA to RGBA */ - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 2 - 1; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(dp--) = *(sp--); @@ -2933,8 +2935,8 @@ else { /* This changes GGAA to RRGGBBAA */ - png_bytep sp = row + (png_size_t)row_width * 4 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; + png_bytep sp = row + (size_t)row_width * 4 - 1; + png_bytep dp = sp + (size_t)row_width * 4; for (i = 0; i < row_width; i++) { *(dp--) = *(sp--); @@ -2962,7 +2964,7 @@ * using the equation given in Poynton's ColorFAQ of 1998-01-04 at * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008 but * versions dated 1998 through November 2002 have been archived at - * http://web.archive.org/web/20000816232553/http://www.inforamp.net/ + * https://web.archive.org/web/20000816232553/www.inforamp.net/ * ~poynton/notes/colour_and_gamma/ColorFAQ.txt ) * Charles Poynton poynton at poynton.com * @@ -3005,7 +3007,7 @@ * values this results in an implicit assumption that the original PNG RGB * values were linear. * - * Other integer coefficents can be used via png_set_rgb_to_gray(). Because + * Other integer coefficients can be used via png_set_rgb_to_gray(). Because * the API takes just red and green coefficients the blue coefficient is * calculated to make the sum 32768. This will result in different rounding * to that used above. @@ -3234,351 +3236,75 @@ png_debug(1, "in png_do_compose"); + switch (row_info->color_type) { - switch (row_info->color_type) + case PNG_COLOR_TYPE_GRAY: { - case PNG_COLOR_TYPE_GRAY: + switch (row_info->bit_depth) { - switch (row_info->bit_depth) + case 1: { - case 1: + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); + } + + if (shift == 0) + { + shift = 7; + sp++; + } + + else + shift--; + } + break; + } + + case 2: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) { sp = row; - shift = 7; + shift = 6; for (i = 0; i < row_width; i++) { - if ((png_uint_16)((*sp >> shift) & 0x01) - == png_ptr->trans_color.gray) + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) { - unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); tmp |= - (unsigned int)(png_ptr->background.gray << shift); + (unsigned int)png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); + } + + else + { + unsigned int p = (*sp >> shift) & 0x03; + unsigned int g = (gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03; + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= (unsigned int)(g << shift); *sp = (png_byte)(tmp & 0xff); } if (shift == 0) { - shift = 7; + shift = 6; sp++; } else - shift--; - } - break; - } - - case 2: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x03) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= - (unsigned int)png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - else - { - unsigned int p = (*sp >> shift) & 0x03; - unsigned int g = (gamma_table [p | (p << 2) | - (p << 4) | (p << 6)] >> 6) & 0x03; - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= (unsigned int)(g << shift); - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 6; - sp++; - } - - else - shift -= 2; - } - } - - else -#endif - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x03) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= - (unsigned int)png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 6; - sp++; - } - - else - shift -= 2; - } - } - break; - } - - case 4: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= - (unsigned int)(png_ptr->background.gray << shift); - *sp = (png_byte)(tmp & 0xff); - } - - else - { - unsigned int p = (*sp >> shift) & 0x0f; - unsigned int g = (gamma_table[p | (p << 4)] >> 4) & - 0x0f; - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= (unsigned int)(g << shift); - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 4; - sp++; - } - - else - shift -= 4; - } - } - - else -#endif - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= - (unsigned int)(png_ptr->background.gray << shift); - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 4; - sp++; - } - - else - shift -= 4; - } - } - break; - } - - case 8: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->background.gray; - - else - *sp = gamma_table[*sp]; - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->background.gray; - } - } - break; - } - - case 16: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - if (v == png_ptr->trans_color.gray) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray - & 0xff); - } - - else - { - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - if (v == png_ptr->trans_color.gray) - { - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray - & 0xff); - } - } - } - break; - } - - default: - break; - } - break; - } - - case PNG_COLOR_TYPE_RGB: - { - if (row_info->bit_depth == 8) - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 3) - { - if (*sp == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } - - else - { - *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 3) - { - if (*sp == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } - } - } - } - else /* if (row_info->bit_depth == 16) */ - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 6) - { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); - - if (r == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } - - else - { - png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } + shift -= 2; } } @@ -3586,67 +3312,153 @@ #endif { sp = row; - for (i = 0; i < row_width; i++, sp += 6) + shift = 6; + for (i = 0; i < row_width; i++) { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); - - if (r == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= + (unsigned int)png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); + } + + if (shift == 0) { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + shift = 6; + sp++; } + + else + shift -= 2; + } + } + break; + } + + case 4: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); + } + + else + { + unsigned int p = (*sp >> shift) & 0x0f; + unsigned int g = (gamma_table[p | (p << 4)] >> 4) & + 0x0f; + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= (unsigned int)(g << shift); + *sp = (png_byte)(tmp & 0xff); + } + + if (shift == 0) + { + shift = 4; + sp++; + } + + else + shift -= 4; } } + + else +#endif + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); + } + + if (shift == 0) + { + shift = 4; + sp++; + } + + else + shift -= 4; + } + } + break; } - break; - } - - case PNG_COLOR_TYPE_GRAY_ALPHA: - { - if (row_info->bit_depth == 8) + + case 8: { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; + + else + *sp = gamma_table[*sp]; + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; + } + } + break; + } + + case 16: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) { sp = row; for (i = 0; i < row_width; i++, sp += 2) { - png_uint_16 a = *(sp + 1); - - if (a == 0xff) - *sp = gamma_table[*sp]; - - else if (a == 0) + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + if (v == png_ptr->trans_color.gray) { /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.gray; + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); } else { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.gray); - if (optimize == 0) - w = gamma_from_1[w]; - *sp = w; + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); } } } @@ -3656,298 +3468,486 @@ sp = row; for (i = 0; i < row_width; i++, sp += 2) { - png_byte a = *(sp + 1); - - if (a == 0) - *sp = (png_byte)png_ptr->background.gray; - - else if (a < 0xff) - png_composite(*sp, *sp, a, png_ptr->background.gray); - } - } - } - else /* if (png_ptr->bit_depth == 16) */ - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; - - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } - - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } - - else - { - png_uint_16 g, v, w; - - g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(v, g, a, png_ptr->background_1.gray); - if (optimize != 0) - w = v; - else - w = gamma_16_from_1[(v & 0xff) >> - gamma_shift][v >> 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - if (a == 0) + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + if (v == png_ptr->trans_color.gray) { *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } - - else if (a < 0xffff) - { - png_uint_16 g, v; - - g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_composite_16(v, g, a, png_ptr->background.gray); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } - } - } - } - break; - } - - case PNG_COLOR_TYPE_RGB_ALPHA: - { - if (row_info->bit_depth == 8) - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_byte a = *(sp + 3); - - if (a == 0xff) - { - *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } - - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } - - else - { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.red); - if (optimize == 0) w = gamma_from_1[w]; - *sp = w; - - v = gamma_to_1[*(sp + 1)]; - png_composite(w, v, a, png_ptr->background_1.green); - if (optimize == 0) w = gamma_from_1[w]; - *(sp + 1) = w; - - v = gamma_to_1[*(sp + 2)]; - png_composite(w, v, a, png_ptr->background_1.blue); - if (optimize == 0) w = gamma_from_1[w]; - *(sp + 2) = w; + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); } } } - else + break; + } + + default: + break; + } + break; + } + + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else #endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else { - png_byte a = *(sp + 3); - - if (a == 0) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } - - else if (a < 0xff) - { - png_composite(*sp, *sp, a, png_ptr->background.red); - - png_composite(*(sp + 1), *(sp + 1), a, - png_ptr->background.green); - - png_composite(*(sp + 2), *(sp + 2), a, - png_ptr->background.blue); - } + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + *sp = gamma_table[*sp]; + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.gray; + } + + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.gray); + if (optimize == 0) + w = gamma_from_1[w]; + *sp = w; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_byte a = *(sp + 1); + + if (a == 0) + *sp = (png_byte)png_ptr->background.gray; + + else if (a < 0xff) + png_composite(*sp, *sp, a, png_ptr->background.gray); + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + + else + { + png_uint_16 g, v, w; + + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, png_ptr->background_1.gray); + if (optimize != 0) + w = v; + else + w = gamma_16_from_1[(v & 0xff) >> + gamma_shift][v >> 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); } } } - else /* if (row_info->bit_depth == 16) */ + else +#endif { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 8) + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == 0) { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); - - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; - - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } - - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } - - else - { - png_uint_16 v, w; - - v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(w, v, a, png_ptr->background_1.red); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; - png_composite_16(w, v, a, png_ptr->background_1.green); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - - *(sp + 2) = (png_byte)((w >> 8) & 0xff); - *(sp + 3) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; - png_composite_16(w, v, a, png_ptr->background_1.blue); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - - *(sp + 4) = (png_byte)((w >> 8) & 0xff); - *(sp + 5) = (png_byte)(w & 0xff); - } + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + + else if (a < 0xffff) + { + png_uint_16 g, v; + + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, png_ptr->background.gray); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); } } - - else -#endif + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 8) + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); - - if (a == 0) - { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } - - else if (a < 0xffff) - { - png_uint_16 v; - - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); - - png_composite_16(v, r, a, png_ptr->background.red); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - - png_composite_16(v, g, a, png_ptr->background.green); - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - - png_composite_16(v, b, a, png_ptr->background.blue); - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.red); + if (optimize == 0) w = gamma_from_1[w]; + *sp = w; + + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, png_ptr->background_1.green); + if (optimize == 0) w = gamma_from_1[w]; + *(sp + 1) = w; + + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, png_ptr->background_1.blue); + if (optimize == 0) w = gamma_from_1[w]; + *(sp + 2) = w; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_byte a = *(sp + 3); + + if (a == 0) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else if (a < 0xff) + { + png_composite(*sp, *sp, a, png_ptr->background.red); + + png_composite(*(sp + 1), *(sp + 1), a, + png_ptr->background.green); + + png_composite(*(sp + 2), *(sp + 2), a, + png_ptr->background.blue); } } } - break; } - - default: - break; + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else + { + png_uint_16 v, w; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, png_ptr->background_1.red); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, png_ptr->background_1.green); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + + *(sp + 2) = (png_byte)((w >> 8) & 0xff); + *(sp + 3) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, png_ptr->background_1.blue); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + + *(sp + 4) = (png_byte)((w >> 8) & 0xff); + *(sp + 5) = (png_byte)(w & 0xff); + } + } + } + + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else if (a < 0xffff) + { + png_uint_16 v; + + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + png_composite_16(v, r, a, png_ptr->background.red); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + png_composite_16(v, g, a, png_ptr->background.green); + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + png_composite_16(v, b, a, png_ptr->background.blue); + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; } + + default: + break; } } #endif /* READ_BACKGROUND || READ_ALPHA_MODE */ @@ -4245,8 +4245,8 @@ { case 1: { - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 3); + dp = row + (size_t)row_width - 1; shift = 7 - (int)((row_width + 7) & 0x07); for (i = 0; i < row_width; i++) { @@ -4272,8 +4272,8 @@ case 2: { - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 2); + dp = row + (size_t)row_width - 1; shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); for (i = 0; i < row_width; i++) { @@ -4295,8 +4295,8 @@ case 4: { - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 1); + dp = row + (size_t)row_width - 1; shift = (int)((row_width & 0x01) << 2); for (i = 0; i < row_width; i++) { @@ -4329,8 +4329,8 @@ { if (num_trans > 0) { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 2) - 1; + sp = row + (size_t)row_width - 1; + dp = row + ((size_t)row_width << 2) - 1; for (i = 0; i < row_width; i++) { @@ -4354,8 +4354,8 @@ else { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width * 3) - 1; + sp = row + (size_t)row_width - 1; + dp = row + (size_t)(row_width * 3) - 1; for (i = 0; i < row_width; i++) { @@ -4390,195 +4390,130 @@ png_debug(1, "in png_do_expand"); + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + unsigned int gray = trans_color != NULL ? trans_color->gray : 0; + + if (row_info->bit_depth < 8) { - unsigned int gray = trans_color != NULL ? trans_color->gray : 0; - - if (row_info->bit_depth < 8) + switch (row_info->bit_depth) { - switch (row_info->bit_depth) + case 1: { - case 1: - { - gray = (gray & 0x01) * 0xff; - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; - shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - if ((*sp >> shift) & 0x01) - *dp = 0xff; - - else - *dp = 0; - - if (shift == 7) - { - shift = 0; - sp--; - } - - else - shift++; - - dp--; - } - break; - } - - case 2: - { - gray = (gray & 0x03) * 0x55; - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; - shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x03; - *dp = (png_byte)(value | (value << 2) | (value << 4) | - (value << 6)); - if (shift == 6) - { - shift = 0; - sp--; - } - - else - shift += 2; - - dp--; - } - break; - } - - case 4: - { - gray = (gray & 0x0f) * 0x11; - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; - shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x0f; - *dp = (png_byte)(value | (value << 4)); - if (shift == 4) - { - shift = 0; - sp--; - } - - else - shift = 4; - - dp--; - } - break; - } - - default: - break; - } - - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - - if (trans_color != NULL) - { - if (row_info->bit_depth == 8) - { - gray = gray & 0xff; - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 1) - 1; - + gray = (gray & 0x01) * 0xff; + sp = row + (size_t)((row_width - 1) >> 3); + dp = row + (size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); for (i = 0; i < row_width; i++) { - if ((*sp & 0xffU) == gray) - *dp-- = 0; + if ((*sp >> shift) & 0x01) + *dp = 0xff; else - *dp-- = 0xff; - - *dp-- = *sp--; - } - } - - else if (row_info->bit_depth == 16) - { - unsigned int gray_high = (gray >> 8) & 0xff; - unsigned int gray_low = gray & 0xff; - sp = row + row_info->rowbytes - 1; - dp = row + (row_info->rowbytes << 1) - 1; - for (i = 0; i < row_width; i++) - { - if ((*(sp - 1) & 0xffU) == gray_high && - (*(sp) & 0xffU) == gray_low) + *dp = 0; + + if (shift == 7) { - *dp-- = 0; - *dp-- = 0; + shift = 0; + sp--; } else + shift++; + + dp--; + } + break; + } + + case 2: + { + gray = (gray & 0x03) * 0x55; + sp = row + (size_t)((row_width - 1) >> 2); + dp = row + (size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) { - *dp-- = 0xff; - *dp-- = 0xff; + shift = 0; + sp--; } - *dp-- = *sp--; - *dp-- = *sp--; + else + shift += 2; + + dp--; } + break; } - row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; - row_info->channels = 2; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_width); + case 4: + { + gray = (gray & 0x0f) * 0x11; + sp = row + (size_t)((row_width - 1) >> 1); + dp = row + (size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift = 4; + + dp--; + } + break; + } + + default: + break; } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB && - trans_color != NULL) + + if (trans_color != NULL) { if (row_info->bit_depth == 8) { - png_byte red = (png_byte)(trans_color->red & 0xff); - png_byte green = (png_byte)(trans_color->green & 0xff); - png_byte blue = (png_byte)(trans_color->blue & 0xff); - sp = row + (png_size_t)row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 2) - 1; + gray = gray & 0xff; + sp = row + (size_t)row_width - 1; + dp = row + ((size_t)row_width << 1) - 1; + for (i = 0; i < row_width; i++) { - if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + if ((*sp & 0xffU) == gray) *dp-- = 0; else *dp-- = 0xff; *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; } } + else if (row_info->bit_depth == 16) { - png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); - png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); - png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); - png_byte red_low = (png_byte)(trans_color->red & 0xff); - png_byte green_low = (png_byte)(trans_color->green & 0xff); - png_byte blue_low = (png_byte)(trans_color->blue & 0xff); + unsigned int gray_high = (gray >> 8) & 0xff; + unsigned int gray_low = gray & 0xff; sp = row + row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 3) - 1; + dp = row + (row_info->rowbytes << 1) - 1; for (i = 0; i < row_width; i++) { - if (*(sp - 5) == red_high && - *(sp - 4) == red_low && - *(sp - 3) == green_high && - *(sp - 2) == green_low && - *(sp - 1) == blue_high && - *(sp ) == blue_low) + if ((*(sp - 1) & 0xffU) == gray_high && + (*(sp) & 0xffU) == gray_low) { *dp-- = 0; *dp-- = 0; @@ -4592,17 +4527,80 @@ *dp-- = *sp--; *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; } } - row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - row_info->channels = 4; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && + trans_color != NULL) + { + if (row_info->bit_depth == 8) + { + png_byte red = (png_byte)(trans_color->red & 0xff); + png_byte green = (png_byte)(trans_color->green & 0xff); + png_byte blue = (png_byte)(trans_color->blue & 0xff); + sp = row + (size_t)row_info->rowbytes - 1; + dp = row + ((size_t)row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); + png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); + png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); + png_byte red_low = (png_byte)(trans_color->red & 0xff); + png_byte green_low = (png_byte)(trans_color->green & 0xff); + png_byte blue_low = (png_byte)(trans_color->blue & 0xff); + sp = row + row_info->rowbytes - 1; + dp = row + ((size_t)row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); } } #endif @@ -4629,7 +4627,9 @@ png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ while (dp > sp) - dp[-2] = dp[-1] = *--sp, dp -= 2; + { + dp[-2] = dp[-1] = *--sp; dp -= 2; + } row_info->rowbytes *= 2; row_info->bit_depth = 16; @@ -4783,8 +4783,7 @@ &(png_ptr->trans_color)); else - png_do_expand(row_info, png_ptr->row_buf + 1, - NULL); + png_do_expand(row_info, png_ptr->row_buf + 1, NULL); } } #endif @@ -5008,7 +5007,7 @@ (png_ptr, /* png_ptr */ row_info, /* row_info: */ /* png_uint_32 width; width of row */ - /* png_size_t rowbytes; number of bytes in row */ + /* size_t rowbytes; number of bytes in row */ /* png_byte color_type; color type of pixels */ /* png_byte bit_depth; bit depth of samples */ /* png_byte channels; number of channels (1-4) */
--- a/src/share/native/sun/awt/libpng/pngrutil.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pngrutil.c Mon Oct 22 06:23:01 2018 +0100 @@ -29,8 +29,8 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * Last changed in libpng 1.6.27 [January 5, 2017] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -148,7 +148,7 @@ void /* PRIVATE */ png_read_sig(png_structrp png_ptr, png_inforp info_ptr) { - png_size_t num_checked, num_to_check; + size_t num_checked, num_to_check; /* Exit if the user application does not expect a signature. */ if (png_ptr->sig_bytes >= 8) @@ -209,6 +209,9 @@ /* Check to see if chunk name is valid. */ png_check_chunk_name(png_ptr, png_ptr->chunk_name); + /* Check for too-large chunk length */ + png_check_chunk_length(png_ptr, length); + #ifdef PNG_IO_STATE_SUPPORTED png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; #endif @@ -339,6 +342,7 @@ if (buffer != NULL) { + memset(buffer, 0, new_size); /* just in case */ png_ptr->read_buffer = buffer; png_ptr->read_buffer_size = new_size; } @@ -446,7 +450,7 @@ png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; } -#if ZLIB_VERNUM >= 0x1281 && \ +#if ZLIB_VERNUM >= 0x1290 && \ defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_IGNORE_ADLER32) if (((png_ptr->options >> PNG_IGNORE_ADLER32) & 3) == PNG_OPTION_ON) /* Turn off validation of the ADLER32 checksum in IDAT chunks */ @@ -698,6 +702,8 @@ if (text != NULL) { + memset(text, 0, buffer_size); + ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, png_ptr->read_buffer + prefix_size, &lzsize, text + prefix_size, newlength); @@ -761,9 +767,7 @@ { /* inflateReset failed, store the error message */ png_zstream_error(png_ptr, ret); - - if (ret == Z_STREAM_END) - ret = PNG_UNEXPECTED_ZLIB_RETURN; + ret = PNG_UNEXPECTED_ZLIB_RETURN; } } @@ -1405,11 +1409,13 @@ * chunk is just ignored, so does not invalidate the color space. An * alternative is to set the 'invalid' flags at the start of this routine * and only clear them in they were not set before and all the tests pass. - * The minimum 'deflate' stream is assumed to be just the 2 byte header and - * 4 byte checksum. The keyword must be at least one character and there is - * a terminator (0) byte and the compression method. */ - if (length < 9) + + /* The keyword must be at least one character and there is a + * terminator (0) byte and the compression method byte, and the + * 'zlib' datastream is at least 11 bytes. + */ + if (length < 14) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "too short"); @@ -1441,6 +1447,16 @@ png_crc_read(png_ptr, (png_bytep)keyword, read_length); length -= read_length; + /* The minimum 'zlib' stream is assumed to be just the 2 byte header, + * 5 bytes minimum 'deflate' stream, and the 4 byte checksum. + */ + if (length < 11) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "too short"); + return; + } + keyword_length = 0; while (keyword_length < 80 && keyword_length < read_length && keyword[keyword_length] != 0) @@ -1459,7 +1475,7 @@ if (png_inflate_claim(png_ptr, png_iCCP) == Z_OK) { - Byte profile_header[132]; + Byte profile_header[132]={0}; Byte local_buffer[PNG_INFLATE_BUF_SIZE]; png_alloc_size_t size = (sizeof profile_header); @@ -1489,7 +1505,7 @@ /* Now read the tag table; a variable size buffer is * needed at this point, allocate one for the whole * profile. The header check has already validated - * that none of these stuff will overflow. + * that none of this stuff will overflow. */ const png_uint_32 tag_count = png_get_uint_32( profile_header+128); @@ -1596,19 +1612,11 @@ return; } } - - else if (size > 0) - errmsg = "truncated"; - -#ifndef __COVERITY__ - else + if (errmsg == NULL) errmsg = png_ptr->zstream.msg; -#endif } - /* else png_icc_check_tag_table output an error */ } - else /* profile truncated */ errmsg = png_ptr->zstream.msg; } @@ -1668,7 +1676,7 @@ int entry_size, i; png_uint_32 skip = 0; png_uint_32 dl; - png_size_t max_dl; + size_t max_dl; png_debug(1, "in png_handle_sPLT"); @@ -2017,6 +2025,15 @@ else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) /* GRAY */ { + if (png_ptr->bit_depth <= 8) + { + if (buf[0] != 0 || buf[1] >= (unsigned int)(1 << png_ptr->bit_depth)) + { + png_chunk_benign_error(png_ptr, "invalid gray level"); + return; + } + } + background.index = 0; background.red = background.green = @@ -2026,6 +2043,15 @@ else { + if (png_ptr->bit_depth <= 8) + { + if (buf[0] != 0 || buf[2] != 0 || buf[4] != 0) + { + png_chunk_benign_error(png_ptr, "invalid color"); + return; + } + } + background.index = 0; background.red = png_get_uint_16(buf); background.green = png_get_uint_16(buf + 2); @@ -2037,6 +2063,69 @@ } #endif +#ifdef PNG_READ_eXIf_SUPPORTED +void /* PRIVATE */ +png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + unsigned int i; + + png_debug(1, "in png_handle_eXIf"); + + if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) + png_chunk_error(png_ptr, "missing IHDR"); + + if (length < 2) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "too short"); + return; + } + + else if (info_ptr == NULL || (info_ptr->valid & PNG_INFO_eXIf) != 0) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + info_ptr->free_me |= PNG_FREE_EXIF; + + info_ptr->eXIf_buf = png_voidcast(png_bytep, + png_malloc_warn(png_ptr, length)); + + if (info_ptr->eXIf_buf == NULL) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + for (i = 0; i < length; i++) + { + png_byte buf[1]; + png_crc_read(png_ptr, buf, 1); + info_ptr->eXIf_buf[i] = buf[0]; + if (i == 1 && buf[0] != 'M' && buf[0] != 'I' + && info_ptr->eXIf_buf[0] != buf[0]) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "incorrect byte-order specifier"); + png_free(png_ptr, info_ptr->eXIf_buf); + info_ptr->eXIf_buf = NULL; + return; + } + } + + if (png_crc_finish(png_ptr, 0) != 0) + return; + + png_set_eXIf_1(png_ptr, info_ptr, length, info_ptr->eXIf_buf); + + png_free(png_ptr, info_ptr->eXIf_buf); + info_ptr->eXIf_buf = NULL; +} +#endif + #ifdef PNG_READ_hIST_SUPPORTED void /* PRIVATE */ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) @@ -2316,7 +2405,7 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { png_bytep buffer; - png_size_t i; + size_t i; int state; png_debug(1, "in png_handle_sCAL"); @@ -2386,7 +2475,7 @@ else { - png_size_t heighti = i; + size_t heighti = i; state = 0; if (png_check_fp_number((png_const_charp)buffer, length, @@ -2565,6 +2654,9 @@ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) png_ptr->mode |= PNG_AFTER_IDAT; + /* Note, "length" is sufficient here; we won't be adding + * a null terminator later. + */ buffer = png_read_buffer(png_ptr, length, 2/*silent*/); if (buffer == NULL) @@ -2611,23 +2703,28 @@ { png_text text; - /* It worked; png_ptr->read_buffer now looks like a tEXt chunk except - * for the extra compression type byte and the fact that it isn't - * necessarily '\0' terminated. - */ - buffer = png_ptr->read_buffer; - buffer[uncompressed_length+(keyword_length+2)] = 0; - - text.compression = PNG_TEXT_COMPRESSION_zTXt; - text.key = (png_charp)buffer; - text.text = (png_charp)(buffer + keyword_length+2); - text.text_length = uncompressed_length; - text.itxt_length = 0; - text.lang = NULL; - text.lang_key = NULL; - - if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0) - errmsg = "insufficient memory"; + if (png_ptr->read_buffer == NULL) + errmsg="Read failure in png_handle_zTXt"; + else + { + /* It worked; png_ptr->read_buffer now looks like a tEXt chunk + * except for the extra compression type byte and the fact that + * it isn't necessarily '\0' terminated. + */ + buffer = png_ptr->read_buffer; + buffer[uncompressed_length+(keyword_length+2)] = 0; + + text.compression = PNG_TEXT_COMPRESSION_zTXt; + text.key = (png_charp)buffer; + text.text = (png_charp)(buffer + keyword_length+2); + text.text_length = uncompressed_length; + text.itxt_length = 0; + text.lang = NULL; + text.lang_key = NULL; + + if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0) + errmsg = "insufficient memory"; + } } else @@ -2816,7 +2913,7 @@ { PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name); /* The following is safe because of the PNG_SIZE_MAX init above */ - png_ptr->unknown_chunk.size = (png_size_t)length/*SAFE*/; + png_ptr->unknown_chunk.size = (size_t)length/*SAFE*/; /* 'mode' is a flag array, only the bottom four bits matter here */ png_ptr->unknown_chunk.location = (png_byte)png_ptr->mode/*SAFE*/; @@ -3003,7 +3100,7 @@ case 2: png_ptr->user_chunk_cache_max = 1; png_chunk_benign_error(png_ptr, "no space in chunk cache"); - /* FALL THROUGH */ + /* FALLTHROUGH */ case 1: /* NOTE: prior to 1.6.0 this case resulted in an unknown critical * chunk being skipped, now there will be a hard error below. @@ -3012,7 +3109,7 @@ default: /* not at limit */ --(png_ptr->user_chunk_cache_max); - /* FALL THROUGH */ + /* FALLTHROUGH */ case 0: /* no limit */ # endif /* USER_LIMITS */ /* Here when the limit isn't reached or when limits are compiled @@ -3063,20 +3160,61 @@ */ void /* PRIVATE */ -png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name) +png_check_chunk_name(png_const_structrp png_ptr, const png_uint_32 chunk_name) { int i; + png_uint_32 cn=chunk_name; png_debug(1, "in png_check_chunk_name"); for (i=1; i<=4; ++i) { - int c = chunk_name & 0xff; + int c = cn & 0xff; if (c < 65 || c > 122 || (c > 90 && c < 97)) png_chunk_error(png_ptr, "invalid chunk type"); - chunk_name >>= 8; + cn >>= 8; + } +} + +void /* PRIVATE */ +png_check_chunk_length(png_const_structrp png_ptr, const png_uint_32 length) +{ + png_alloc_size_t limit = PNG_UINT_31_MAX; + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_malloc_max > 0 && + png_ptr->user_chunk_malloc_max < limit) + limit = png_ptr->user_chunk_malloc_max; +# elif PNG_USER_CHUNK_MALLOC_MAX > 0 + if (PNG_USER_CHUNK_MALLOC_MAX < limit) + limit = PNG_USER_CHUNK_MALLOC_MAX; +# endif + if (png_ptr->chunk_name == png_IDAT) + { + png_alloc_size_t idat_limit = PNG_UINT_31_MAX; + size_t row_factor = + (size_t)png_ptr->width + * (size_t)png_ptr->channels + * (png_ptr->bit_depth > 8? 2: 1) + + 1 + + (png_ptr->interlaced? 6: 0); + if (png_ptr->height > PNG_UINT_32_MAX/row_factor) + idat_limit = PNG_UINT_31_MAX; + else + idat_limit = png_ptr->height * row_factor; + row_factor = row_factor > 32566? 32566 : row_factor; + idat_limit += 6 + 5*(idat_limit/row_factor+1); /* zlib+deflate overhead */ + idat_limit=idat_limit < PNG_UINT_31_MAX? idat_limit : PNG_UINT_31_MAX; + limit = limit < idat_limit? idat_limit : limit; + } + + if (length > limit) + { + png_debug2(0," length = %lu, limit = %lu", + (unsigned long)length,(unsigned long)limit); + png_chunk_error(png_ptr, "chunk data is too large"); } } @@ -3405,7 +3543,7 @@ */ do { - dp[0] = sp[0], dp[1] = sp[1]; + dp[0] = sp[0]; dp[1] = sp[1]; if (row_width <= bytes_to_jump) return; @@ -3426,7 +3564,7 @@ */ for (;;) { - dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2]; + dp[0] = sp[0]; dp[1] = sp[1]; dp[2] = sp[2]; if (row_width <= bytes_to_jump) return; @@ -3590,8 +3728,8 @@ { case 1: { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + png_bytep sp = row + (size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (size_t)((final_width - 1) >> 3); unsigned int sshift, dshift; unsigned int s_start, s_end; int s_inc; @@ -3717,8 +3855,8 @@ case 4: { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + png_bytep sp = row + (size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (size_t)((final_width - 1) >> 1); unsigned int sshift, dshift; unsigned int s_start, s_end; int s_inc; @@ -3780,12 +3918,12 @@ default: { - png_size_t pixel_bytes = (row_info->pixel_depth >> 3); - - png_bytep sp = row + (png_size_t)(row_info->width - 1) + size_t pixel_bytes = (row_info->pixel_depth >> 3); + + png_bytep sp = row + (size_t)(row_info->width - 1) * pixel_bytes; - png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + png_bytep dp = row + (size_t)(final_width - 1) * pixel_bytes; int jstop = (int)png_pass_inc[pass]; png_uint_32 i; @@ -3822,8 +3960,8 @@ png_read_filter_row_sub(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; unsigned int bpp = (row_info->pixel_depth + 7) >> 3; png_bytep rp = row + bpp; @@ -3840,8 +3978,8 @@ png_read_filter_row_up(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; png_bytep rp = row; png_const_bytep pp = prev_row; @@ -3856,11 +3994,11 @@ png_read_filter_row_avg(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - png_size_t i; + size_t i; png_bytep rp = row; png_const_bytep pp = prev_row; unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_size_t istop = row_info->rowbytes - bpp; + size_t istop = row_info->rowbytes - bpp; for (i = 0; i < bpp; i++) { @@ -3915,7 +4053,10 @@ /* Find the best predictor, the least of pa, pb, pc favoring the earlier * ones in the case of a tie. */ - if (pb < pa) pa = pb, a = b; + if (pb < pa) + { + pa = pb; a = b; + } if (pc < pa) a = c; /* Calculate the current pixel in a, and move the previous row pixel to c @@ -3967,7 +4108,10 @@ pc = (p + pc) < 0 ? -(p + pc) : p + pc; #endif - if (pb < pa) pa = pb, a = b; + if (pb < pa) + { + pa = pb; a = b; + } if (pc < pa) a = c; a += *row; @@ -4290,7 +4434,7 @@ static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; unsigned int max_pixel_depth; - png_size_t row_bytes; + size_t row_bytes; png_debug(1, "in png_read_start_row");
--- a/src/share/native/sun/awt/libpng/pngset.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pngset.c Mon Oct 22 06:23:01 2018 +0100 @@ -29,8 +29,8 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -162,6 +162,53 @@ #endif /* cHRM */ +#ifdef PNG_eXIf_SUPPORTED +void PNGAPI +png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr, + const png_bytep eXIf_buf) +{ + png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1"); + PNG_UNUSED(info_ptr) + PNG_UNUSED(eXIf_buf) +} + +void PNGAPI +png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr, + const png_uint_32 num_exif, const png_bytep eXIf_buf) +{ + int i; + + png_debug1(1, "in %s storage function", "eXIf"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->exif) + { + png_free(png_ptr, info_ptr->exif); + info_ptr->exif = NULL; + } + + info_ptr->num_exif = num_exif; + + info_ptr->exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr, + info_ptr->num_exif)); + + if (info_ptr->exif == NULL) + { + png_warning(png_ptr, "Insufficient memory for eXIf chunk data"); + return; + } + + info_ptr->free_me |= PNG_FREE_EXIF; + + for (i = 0; i < (int) info_ptr->num_exif; i++) + info_ptr->exif[i] = eXIf_buf[i]; + + info_ptr->valid |= PNG_INFO_eXIf; +} +#endif /* eXIf */ + #ifdef PNG_gAMA_SUPPORTED void PNGFAPI png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr, @@ -294,7 +341,7 @@ png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, png_const_charp units, png_charpp params) { - png_size_t length; + size_t length; int i; png_debug1(1, "in %s storage function", "pCAL"); @@ -371,7 +418,7 @@ memcpy(info_ptr->pcal_units, units, length); info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, - (png_size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp))))); + (size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp))))); if (info_ptr->pcal_params == NULL) { @@ -411,7 +458,7 @@ png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, int unit, png_const_charp swidth, png_const_charp sheight) { - png_size_t lengthw = 0, lengthh = 0; + size_t lengthw = 0, lengthh = 0; png_debug1(1, "in %s storage function", "sCAL"); @@ -672,7 +719,7 @@ { png_charp new_iccp_name; png_bytep new_iccp_profile; - png_size_t length; + size_t length; png_debug1(1, "in %s storage function", "iCCP"); @@ -999,7 +1046,7 @@ /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ info_ptr->trans_alpha = png_voidcast(png_bytep, png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); - memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); + memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans); } png_ptr->trans_alpha = info_ptr->trans_alpha; } @@ -1079,7 +1126,7 @@ do { - png_size_t length; + size_t length; /* Skip invalid input entries */ if (entries->name == NULL || entries->entries == NULL) @@ -1130,8 +1177,9 @@ info_ptr->valid |= PNG_INFO_sPLT; ++(info_ptr->splt_palettes_num); ++np; + ++entries; } - while (++entries, --nentries); + while (--nentries); if (nentries > 0) png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR); @@ -1382,6 +1430,7 @@ static PNG_CONST png_byte chunks_to_ignore[] = { 98, 75, 71, 68, '\0', /* bKGD */ 99, 72, 82, 77, '\0', /* cHRM */ + 101, 88, 73, 102, '\0', /* eXIf */ 103, 65, 77, 65, '\0', /* gAMA */ 104, 73, 83, 84, '\0', /* hIST */ 105, 67, 67, 80, '\0', /* iCCP */ @@ -1542,7 +1591,7 @@ #endif void PNGAPI -png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size) +png_set_compression_buffer_size(png_structrp png_ptr, size_t size) { if (png_ptr == NULL) return; @@ -1724,14 +1773,16 @@ png_byte ch = (png_byte)*key++; if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/)) - *new_key++ = ch, ++key_len, space = 0; + { + *new_key++ = ch; ++key_len; space = 0; + } else if (space == 0) { /* A space or an invalid character when one wasn't seen immediately * before; output just a space. */ - *new_key++ = 32, ++key_len, space = 1; + *new_key++ = 32; ++key_len; space = 1; /* If the character was not a space then it is invalid. */ if (ch != 32) @@ -1744,7 +1795,7 @@ if (key_len > 0 && space != 0) /* trailing space */ { - --key_len, --new_key; + --key_len; --new_key; if (bad_character == 0) bad_character = 32; }
--- a/src/share/native/sun/awt/libpng/pngstruct.h Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pngstruct.h Mon Oct 22 06:23:01 2018 +0100 @@ -29,8 +29,8 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * Last changed in libpng 1.6.28 [January 5, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -75,7 +75,7 @@ /* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib * can handle at once. This type need be no larger than 16 bits (so maximum of * 65535), this define allows us to discover how big it is, but limited by the - * maximuum for png_size_t. The value can be overriden in a library build + * maximum for size_t. The value can be overridden in a library build * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably * lower value (e.g. 255 works). A lower value may help memory usage (slightly) * and may even improve performance on some systems (and degrade it on others.) @@ -242,7 +242,7 @@ png_uint_32 height; /* height of image in pixels */ png_uint_32 num_rows; /* number of rows in current pass */ png_uint_32 usr_width; /* width of row at start of write */ - png_size_t rowbytes; /* size of row in bytes */ + size_t rowbytes; /* size of row in bytes */ png_uint_32 iwidth; /* width of current interlaced row in pixels */ png_uint_32 row_number; /* current row in interlace pass */ png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */ @@ -260,7 +260,7 @@ png_bytep try_row; /* buffer to save trial row when filtering */ png_bytep tst_row; /* buffer to save best trial row when filtering */ #endif - png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ + size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ png_uint_32 idat_size; /* current IDAT size for read */ png_uint_32 crc; /* current chunk CRC value */ @@ -335,7 +335,7 @@ #endif #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift; /* shift for significant bit tranformation */ + png_color_8 shift; /* shift for significant bit transformation */ #endif #if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ @@ -356,10 +356,10 @@ png_bytep current_buffer; /* buffer for recently used data */ png_uint_32 push_length; /* size of current input chunk */ png_uint_32 skip_length; /* bytes to skip in input data */ - png_size_t save_buffer_size; /* amount of data now in save_buffer */ - png_size_t save_buffer_max; /* total size of save_buffer */ - png_size_t buffer_size; /* total amount of available input data */ - png_size_t current_buffer_size; /* amount of data now in current_buffer */ + size_t save_buffer_size; /* amount of data now in save_buffer */ + size_t save_buffer_max; /* total size of save_buffer */ + size_t buffer_size; /* total amount of available input data */ + size_t current_buffer_size; /* amount of data now in current_buffer */ int process_mode; /* what push library is currently doing */ int cur_palette; /* current push library palette index */ @@ -479,7 +479,7 @@ #endif /* New member added in libpng-1.2.26 */ - png_size_t old_big_row_buf_size; + size_t old_big_row_buf_size; #ifdef PNG_READ_SUPPORTED /* New member added in libpng-1.2.30 */
--- a/src/share/native/sun/awt/libpng/pngtrans.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/share/native/sun/awt/libpng/pngtrans.c Mon Oct 22 06:23:01 2018 +0100 @@ -29,8 +29,8 @@ * However, the following notice accompanied the original version of this * file and, per its terms, should not be removed: * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -297,8 +297,8 @@ if (row_info->color_type == PNG_COLOR_TYPE_GRAY) { png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i++) { @@ -311,8 +311,8 @@ row_info->bit_depth == 8) { png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i += 2) { @@ -326,8 +326,8 @@ row_info->bit_depth == 16) { png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i += 4) { @@ -542,11 +542,15 @@ if (at_start != 0) /* Skip initial filler */ ++sp; else /* Skip initial channel and, for sp, the filler */ - sp += 2, ++dp; + { + sp += 2; ++dp; + } /* For a 1 pixel wide image there is nothing to do */ while (sp < ep) - *dp++ = *sp, sp += 2; + { + *dp++ = *sp; sp += 2; + } row_info->pixel_depth = 8; } @@ -556,10 +560,14 @@ if (at_start != 0) /* Skip initial filler */ sp += 2; else /* Skip initial channel and, for sp, the filler */ - sp += 4, dp += 2; + { + sp += 4; dp += 2; + } while (sp < ep) - *dp++ = *sp++, *dp++ = *sp, sp += 3; + { + *dp++ = *sp++; *dp++ = *sp; sp += 3; + } row_info->pixel_depth = 16; } @@ -582,11 +590,15 @@ if (at_start != 0) /* Skip initial filler */ ++sp; else /* Skip initial channels and, for sp, the filler */ - sp += 4, dp += 3; + { + sp += 4; dp += 3; + } /* Note that the loop adds 3 to dp and 4 to sp each time. */ while (sp < ep) - *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2; + { + *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp; sp += 2; + } row_info->pixel_depth = 24; } @@ -596,14 +608,16 @@ if (at_start != 0) /* Skip initial filler */ sp += 2; else /* Skip initial channels and, for sp, the filler */ - sp += 8, dp += 6; + { + sp += 8; dp += 6; + } while (sp < ep) { /* Copy 6 bytes, skip 2 */ - *dp++ = *sp++, *dp++ = *sp++; - *dp++ = *sp++, *dp++ = *sp++; - *dp++ = *sp++, *dp++ = *sp, sp += 3; + *dp++ = *sp++; *dp++ = *sp++; + *dp++ = *sp++; *dp++ = *sp++; + *dp++ = *sp++; *dp++ = *sp; sp += 3; } row_info->pixel_depth = 48; @@ -623,7 +637,7 @@ return; /* The filler channel has gone already */ /* Fix the rowbytes value. */ - row_info->rowbytes = (unsigned int)(dp-row); + row_info->rowbytes = (size_t)(dp-row); } #endif @@ -722,7 +736,7 @@ * forms produced on either GCC or MSVC. */ int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width); - png_bytep rp = png_ptr->row_buf + row_info->rowbytes; + png_bytep rp = png_ptr->row_buf + row_info->rowbytes - 1; switch (row_info->bit_depth) {
--- a/src/solaris/native/java/net/NetworkInterface.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/solaris/native/java/net/NetworkInterface.c Mon Oct 22 06:23:01 2018 +0100 @@ -305,10 +305,18 @@ jboolean match = JNI_FALSE; #ifdef AF_INET6 - int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6; + int family = getInetAddress_family(env, iaObj); JNU_CHECK_EXCEPTION_RETURN(env, NULL); + + if (family == IPv4) { + family = AF_INET; + } else if (family == IPv6) { + family = AF_INET6; + } else { + return NULL; // Invalid family + } #else - int family = AF_INET; + int family = AF_INET; #endif ifs = enumInterfaces(env); @@ -329,7 +337,9 @@ if (family == AF_INET) { int address1 = htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr); int address2 = getInetAddress_addr(env, iaObj); - JNU_CHECK_EXCEPTION_RETURN(env, NULL); + if ((*env)->ExceptionCheck(env)) { + goto cleanup; + } if (address1 == address2) { match = JNI_TRUE; break; @@ -375,6 +385,8 @@ obj = createNetworkInterface(env, curr); } +cleanup: + // release the interface list freeif(ifs); return obj; }
--- a/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. 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 @@ -677,7 +677,7 @@ } try { - return invoke(new Callable<File[]>() { + File[] files = invoke(new Callable<File[]>() { public File[] call() throws InterruptedException { if (!isDirectory()) { return null; @@ -732,6 +732,9 @@ : list.toArray(new ShellFolder[list.size()]); } }, InterruptedException.class); + + return Win32ShellFolderManager2.checkFiles(files); + } catch (InterruptedException e) { return new File[0]; }
--- a/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Mon Oct 22 04:45:27 2018 +0100 +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. 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 @@ -380,21 +380,30 @@ return null; } - private File checkFile(File file) { + private static File checkFile(File file) { SecurityManager sm = System.getSecurityManager(); return (sm == null || file == null) ? file : checkFile(file, sm); } - private File checkFile(File file, SecurityManager sm) { + private static File checkFile(File file, SecurityManager sm) { try { sm.checkRead(file.getPath()); + + if (file instanceof Win32ShellFolder2) { + Win32ShellFolder2 f = (Win32ShellFolder2)file; + if (f.isLink()) { + Win32ShellFolder2 link = (Win32ShellFolder2)f.getLinkLocation(); + if (link != null) + sm.checkRead(link.getPath()); + } + } return file; } catch (SecurityException se) { return null; } } - private File[] checkFiles(File[] files) { + static File[] checkFiles(File[] files) { SecurityManager sm = System.getSecurityManager(); if (sm == null || files == null || files.length == 0) { return files; @@ -402,7 +411,7 @@ return checkFiles(Arrays.asList(files), sm); } - private File[] checkFiles(List<File> files) { + private static File[] checkFiles(List<File> files) { SecurityManager sm = System.getSecurityManager(); if (sm == null || files.isEmpty()) { return files.toArray(new File[files.size()]); @@ -410,7 +419,7 @@ return checkFiles(files, sm); } - private File[] checkFiles(List<File> files, SecurityManager sm) { + private static File[] checkFiles(List<File> files, SecurityManager sm) { List<File> checkedFiles = new ArrayList<File>(files.size()); for (File file: files) { if(checkFile(file, sm) != null){
--- a/src/windows/native/java/net/NetworkInterface.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/windows/native/java/net/NetworkInterface.c Mon Oct 22 06:23:01 2018 +0100 @@ -272,6 +272,7 @@ if (curr->name == NULL || curr->displayName == NULL) { if (curr->name) free(curr->name); if (curr->displayName) free(curr->displayName); + free(curr); curr = NULL; } } @@ -564,7 +565,10 @@ /* default ctor will set family to AF_INET */ setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr)); - JNU_CHECK_EXCEPTION_RETURN(env, NULL); + if ((*env)->ExceptionCheck(env)) { + free_netaddr(netaddrP); + return NULL; + } if (addrs->mask != -1) { ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj == NULL) { @@ -578,7 +582,10 @@ return NULL; } setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr)); - JNU_CHECK_EXCEPTION_RETURN(env, NULL); + if ((*env)->ExceptionCheck(env)) { + free_netaddr(netaddrP); + return NULL; + } (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj); (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); @@ -589,6 +596,7 @@ if (iaObj) { int ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); if (ret == JNI_FALSE) { + free_netaddr(netaddrP); return NULL; }
--- a/src/windows/native/java/net/NetworkInterface_winXP.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/windows/native/java/net/NetworkInterface_winXP.c Mon Oct 22 06:23:01 2018 +0100 @@ -428,22 +428,29 @@ jobjectArray addrArr, bindsArr, childArr; netaddr *addrs; jint addr_index; - int netaddrCount=ifs->naddrs; - netaddr *netaddrP=ifs->addrs; + int netaddrCount = ifs->naddrs; + netaddr *netaddrP = ifs->addrs; + netaddr *netaddrPToFree = NULL; jint bind_index; /* * Create a NetworkInterface object and populate it */ netifObj = (*env)->NewObject(env, ni_class, ni_ctor); + if (netifObj == NULL) { + return NULL; + } name = (*env)->NewStringUTF(env, ifs->name); + if (name == NULL) { + return NULL; + } if (ifs->dNameIsUnicode) { displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName, (jsize)wcslen ((PWCHAR)ifs->displayName)); } else { displayName = (*env)->NewStringUTF(env, ifs->displayName); } - if (netifObj == NULL || name == NULL || displayName == NULL) { + if (displayName == NULL) { return NULL; } (*env)->SetObjectField(env, netifObj, ni_nameID, name); @@ -454,21 +461,23 @@ * Note that 0 is a valid number of addresses. */ if (netaddrCount < 0) { - netaddrCount = enumAddresses_win(env, ifs, &netaddrP); + netaddrCount = enumAddresses_win(env, ifs, &netaddrPToFree); if (netaddrCount == -1) { return NULL; } + netaddrP = netaddrPToFree; } addrArr = (*env)->NewObjectArray(env, netaddrCount, ni_iacls, NULL); if (addrArr == NULL) { + free_netaddr(netaddrPToFree); return NULL; } bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL); if (bindsArr == NULL) { - free_netaddr(netaddrP); - return NULL; + free_netaddr(netaddrPToFree); + return NULL; } addrs = netaddrP; @@ -480,51 +489,62 @@ if (addrs->addr.him.sa_family == AF_INET) { iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4Ctor); if (iaObj == NULL) { + free_netaddr(netaddrPToFree); return NULL; } /* default ctor will set family to AF_INET */ setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr)); - JNU_CHECK_EXCEPTION_RETURN(env, NULL); + if ((*env)->ExceptionCheck(env)) { + free_netaddr(netaddrPToFree); + return NULL; + } ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj == NULL) { - free_netaddr(netaddrP); - return NULL; + free_netaddr(netaddrPToFree); + return NULL; } (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4Ctor); if (ia2Obj == NULL) { - free_netaddr(netaddrP); - return NULL; + free_netaddr(netaddrPToFree); + return NULL; } setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr)); - JNU_CHECK_EXCEPTION_RETURN(env, NULL); + if ((*env)->ExceptionCheck(env)) { + free_netaddr(netaddrPToFree); + return NULL; + } (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj); (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); } else /* AF_INET6 */ { int scope; + int ret; iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID); - if (iaObj) { - int ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); - if (ret == JNI_FALSE) { - return NULL; - } - scope = addrs->addr.him6.sin6_scope_id; - if (scope != 0) { /* zero is default value, no need to set */ - setInet6Address_scopeid(env, iaObj, scope); - setInet6Address_scopeifname(env, iaObj, netifObj); - } - ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); - if (ibObj == NULL) { - free_netaddr(netaddrP); - return NULL; - } - (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); - (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); - (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); + if (iaObj == NULL) { + free_netaddr(netaddrPToFree); + return NULL; + } + ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); + if (ret == JNI_FALSE) { + free_netaddr(netaddrPToFree); + return NULL; } + scope = addrs->addr.him6.sin6_scope_id; + if (scope != 0) { /* zero is default value, no need to set */ + setInet6Address_scopeid(env, iaObj, scope); + setInet6Address_scopeifname(env, iaObj, netifObj); + } + ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); + if (ibObj == NULL) { + free_netaddr(netaddrPToFree); + return NULL; + } + (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); + (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); + (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); } (*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj); addrs = addrs->next; @@ -533,6 +553,8 @@ (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr); (*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr); + free_netaddr(netaddrPToFree); + /* * Windows doesn't have virtual interfaces, so child array * is always empty. @@ -572,7 +594,7 @@ } /* if found create a NetworkInterface */ - if (curr != NULL) {; + if (curr != NULL) { netifObj = createNetworkInterfaceXP(env, curr); } @@ -699,6 +721,7 @@ /* allocate a NetworkInterface array */ netIFArr = (*env)->NewObjectArray(env, count, cls, NULL); if (netIFArr == NULL) { + free_netif(ifList); return NULL; } @@ -713,6 +736,7 @@ netifObj = createNetworkInterfaceXP(env, curr); if (netifObj == NULL) { + free_netif(ifList); return NULL; }
--- a/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c Mon Oct 22 06:23:01 2018 +0100 @@ -441,7 +441,6 @@ "Protocol family not supported"); return; } - JNU_CHECK_EXCEPTION(env); if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); return; @@ -832,6 +831,7 @@ } if (IS_NULL(addressObj)) { JNU_ThrowNullPointerException(env, "Null address in peek()"); + return -1; } else { address = getInetAddress_addr(env, addressObj); JNU_CHECK_EXCEPTION_RETURN(env, -1); @@ -1147,11 +1147,23 @@ } if (n == -1) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return -1; } else if (n == -2) { JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", "operation interrupted"); + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return -1; } else if (n < 0) { NET_ThrowCurrent(env, "Datagram receive failed"); + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return -1; } else { jobject packetAddress; @@ -1914,7 +1926,7 @@ default : JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket option not supported by PlainDatagramSocketImp"); - break; + return; } @@ -2323,6 +2335,7 @@ if (NET_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ittl, sizeof (ittl)) < 0) { NET_ThrowCurrent(env, "set IP_MULTICAST_TTL failed"); + return; } } @@ -2513,6 +2526,9 @@ } else { ifindex = getIndexFromIf (env, niObj); if (ifindex == -1) { + if ((*env)->ExceptionOccurred(env)) { + return; + } NET_ThrowCurrent(env, "get ifindex failed"); return; }
--- a/src/windows/native/java/net/TwoStacksPlainSocketImpl.c Mon Oct 22 04:45:27 2018 +0100 +++ b/src/windows/native/java/net/TwoStacksPlainSocketImpl.c Mon Oct 22 06:23:01 2018 +0100 @@ -110,7 +110,7 @@ psi_portID = (*env)->GetFieldID(env, cls, "port", "I"); CHECK_NULL(psi_portID); psi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I"); - CHECK_NULL(psi_portID); + CHECK_NULL(psi_lastfdID); psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I"); CHECK_NULL(psi_localportID); psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); @@ -155,17 +155,17 @@ fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); if (IS_NULL(fd1Obj)) { + (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); + NET_SocketClose(fd); JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "null fd1 object"); - (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); - NET_SocketClose(fd); return; } fd1 = socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0); if (fd1 == -1) { - NET_ThrowCurrent(env, "create"); (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); NET_SocketClose(fd); + NET_ThrowCurrent(env, "create"); return; } else { /* Set socket attribute so it is not passed to any child process */ @@ -916,6 +916,7 @@ isRcvTimeoutSupported = JNI_FALSE; } else { NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO"); + return; } } if (fd1 != -1) {
--- a/src/windows/native/sun/security/mscapi/security.cpp Mon Oct 22 04:45:27 2018 +0100 +++ b/src/windows/native/sun/security/mscapi/security.cpp Mon Oct 22 06:23:01 2018 +0100 @@ -153,7 +153,6 @@ { HCRYPTPROV hCryptProv = NULL; - BYTE* pbData = NULL; jbyte* reseedBytes = NULL; jbyte* seedBytes = NULL; jbyteArray result = NULL; @@ -197,25 +196,17 @@ result = NULL; - } else if (length > 0) { - - pbData = new BYTE[length]; + } else { - if (::CryptGenRandom( - hCryptProv, - length, - pbData) == FALSE) { - - ThrowException(env, PROVIDER_EXCEPTION, GetLastError()); - __leave; + if (length > 0) { + seed = env->NewByteArray(length); + if (seed == NULL) { + __leave; + } + } else { + length = env->GetArrayLength(seed); } - result = env->NewByteArray(length); - env->SetByteArrayRegion(result, 0, length, (jbyte*) pbData); - - } else { // length == 0 - - length = env->GetArrayLength(seed); if ((seedBytes = env->GetByteArrayElements(seed, 0)) == NULL) { __leave; } @@ -240,9 +231,6 @@ if (reseedBytes) env->ReleaseByteArrayElements(seed, reseedBytes, JNI_ABORT); - if (pbData) - delete [] pbData; - if (seedBytes) env->ReleaseByteArrayElements(seed, seedBytes, 0); // update orig
--- a/test/lib/testlibrary/jdk/testlibrary/JarUtils.java Mon Oct 22 04:45:27 2018 +0100 +++ b/test/lib/testlibrary/jdk/testlibrary/JarUtils.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Oracle and/or its affiliates. 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 @@ -23,15 +23,17 @@ package jdk.testlibrary; -import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.Path; -import java.util.ArrayList; +import java.nio.file.Paths; import java.util.Enumeration; -import java.util.List; +import java.util.HashMap; +import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; @@ -42,31 +44,24 @@ */ public final class JarUtils { - /** * Create jar file with specified files. If a specified file does not exist, * a new jar entry will be created with the file name itself as the content. */ - public static void createJar(String dest, Path filesLocation, - String... fileNames) throws IOException { + public static void createJar(String dest, String... files) + throws IOException { try (JarOutputStream jos = new JarOutputStream( new FileOutputStream(dest), new Manifest())) { - for (String fileName : fileNames) { + for (String file : files) { System.out.println(String.format("Adding %s to %s", - fileName, dest)); + file, dest)); // add an archive entry, and write a file - jos.putNextEntry(new JarEntry(fileName)); - File file; - if (filesLocation != null) { - file = filesLocation.resolve(fileName).toFile(); - } else { - file = new File(fileName); - } + jos.putNextEntry(new JarEntry(file)); try (FileInputStream fis = new FileInputStream(file)) { - Utils.transferBetweenStreams(fis, jos); + Utils.transferTo(fis, jos); } catch (FileNotFoundException e) { - jos.write(fileName.getBytes()); + jos.write(file.getBytes()); } } } @@ -74,14 +69,6 @@ } /** - * Create jar file with specified files from current directory. - */ - public static void createJar(String dest, String... files) - throws IOException { - createJar(dest, null, files); - } - - /** * Add or remove specified files to existing jar file. If a specified file * to be updated or added does not exist, the jar entry will be created * with the file name itself as the content. @@ -96,70 +83,93 @@ */ public static void updateJar(String src, String dest, String... files) throws IOException { + Map<String,Object> changes = new HashMap<>(); + boolean update = true; + for (String file : files) { + if (file.equals("-")) { + update = false; + } else if (update) { + try { + Path p = Paths.get(file); + if (Files.exists(p)) { + changes.put(file, p); + } else { + changes.put(file, file); + } + } catch (InvalidPathException e) { + // Fallback if file not a valid Path. + changes.put(file, file); + } + } else { + changes.put(file, Boolean.FALSE); + } + } + updateJar(src, dest, changes); + } + + /** + * Update content of a jar file. + * + * @param src the original jar file name + * @param dest the new jar file name + * @param changes a map of changes, key is jar entry name, value is content. + * Value can be Path, byte[] or String. If key exists in + * src but value is Boolean FALSE. The entry is removed. + * Existing entries in src not a key is unmodified. + * @throws IOException + */ + public static void updateJar(String src, String dest, + Map<String,Object> changes) + throws IOException { + + // What if input changes is immutable? + changes = new HashMap<>(changes); + + System.out.printf("Creating %s from %s...\n", dest, src); try (JarOutputStream jos = new JarOutputStream( new FileOutputStream(dest))) { - // copy each old entry into destination unless the entry name - // is in the updated list - List<String> updatedFiles = new ArrayList<>(); try (JarFile srcJarFile = new JarFile(src)) { Enumeration<JarEntry> entries = srcJarFile.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String name = entry.getName(); - boolean found = false; - boolean update = true; - for (String file : files) { - if (file.equals("-")) { - update = false; - } else if (name.equals(file)) { - updatedFiles.add(file); - found = true; - break; - } - } - - if (found) { - if (update) { - System.out.println(String.format("Updating %s with %s", - dest, name)); - jos.putNextEntry(new JarEntry(name)); - try (FileInputStream fis = new FileInputStream(name)) { - Utils.transferBetweenStreams(fis, jos); - } catch (FileNotFoundException e) { - jos.write(name.getBytes()); - } - } else { - System.out.println(String.format("Removing %s from %s", - name, dest)); - } + if (changes.containsKey(name)) { + System.out.println(String.format("- Update %s", name)); + updateEntry(jos, name, changes.get(name)); + changes.remove(name); } else { - System.out.println(String.format("Copying %s to %s", - name, dest)); + System.out.println(String.format("- Copy %s", name)); jos.putNextEntry(entry); - Utils.transferBetweenStreams(srcJarFile. - getInputStream(entry), jos); + Utils.transferTo(srcJarFile.getInputStream(entry), jos); } } } - - // append new files - for (String file : files) { - if (file.equals("-")) { - break; - } - if (!updatedFiles.contains(file)) { - System.out.println(String.format("Adding %s with %s", - dest, file)); - jos.putNextEntry(new JarEntry(file)); - try (FileInputStream fis = new FileInputStream(file)) { - Utils.transferBetweenStreams(fis, jos); - } catch (FileNotFoundException e) { - jos.write(file.getBytes()); - } - } + for (Map.Entry<String, Object> e : changes.entrySet()) { + System.out.println(String.format("- Add %s", e.getKey())); + updateEntry(jos, e.getKey(), e.getValue()); } } System.out.println(); } -} \ No newline at end of file + + private static void updateEntry(JarOutputStream jos, String name, Object content) + throws IOException { + if (content instanceof Boolean) { + if (((Boolean) content).booleanValue()) { + throw new RuntimeException("Boolean value must be FALSE"); + } + } else { + jos.putNextEntry(new JarEntry(name)); + if (content instanceof Path) { + Utils.transferTo(Files.newInputStream((Path) content), jos); + } else if (content instanceof byte[]) { + jos.write((byte[]) content); + } else if (content instanceof String) { + jos.write(((String) content).getBytes()); + } else { + throw new RuntimeException("Unknown type " + content.getClass()); + } + } + } +}
--- a/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java Mon Oct 22 04:45:27 2018 +0100 +++ b/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java Mon Oct 22 06:23:01 2018 +0100 @@ -36,7 +36,7 @@ private final String stdout; private final String stderr; - private final int exitValue; + private final int exitValue; // useless now. output contains exit value. /** * Create an OutputAnalyzer, a utility class for verifying output and exit @@ -362,6 +362,21 @@ } /** + * Verify the exit value of the process + * + * @param notExpectedExitValue Unexpected exit value from process + * @throws RuntimeException If the exit value from the process did match the expected value + */ + public OutputAnalyzer shouldNotHaveExitValue(int notExpectedExitValue) { + if (getExitValue() == notExpectedExitValue) { + reportDiagnosticSummary(); + throw new RuntimeException("Unexpected to get exit value of [" + + notExpectedExitValue + "]\n"); + } + return this; + } + + /** * Report summary that will help to diagnose the problem Currently includes: * - standard input produced by the process under test - standard output - * exit code Note: the command line is printed by the ProcessTools
--- a/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Mon Oct 22 04:45:27 2018 +0100 +++ b/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. 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 @@ -25,6 +25,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.io.PrintStream; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; @@ -268,9 +269,31 @@ * @return The output from the process. */ public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Throwable { + return executeProcess(pb, null); + } + + /** + * Executes a process, pipe some text into its STDIN, waits for it + * to finish and returns the process output. The process will have exited + * before this method returns. + * @param pb The ProcessBuilder to execute. + * @param input The text to pipe into STDIN. Can be null. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeProcess(ProcessBuilder pb, String input) + throws Throwable { OutputAnalyzer output = null; + Process p = null; try { - output = new OutputAnalyzer(pb.start()); + p = pb.start(); + if (input != null) { + try (OutputStream os = p.getOutputStream(); + PrintStream ps = new PrintStream(os)) { + ps.print(input); + ps.flush(); + } + } + output = new OutputAnalyzer(p); return output; } catch (Throwable t) { System.out.println("executeProcess() failed: " + t);
--- a/test/lib/testlibrary/jdk/testlibrary/SecurityTools.java Mon Oct 22 04:45:27 2018 +0100 +++ b/test/lib/testlibrary/jdk/testlibrary/SecurityTools.java Mon Oct 22 06:23:01 2018 +0100 @@ -47,10 +47,7 @@ launcher.addToolArg(arg); } } - String[] cmds = launcher.getCommand(); - String cmdLine = joiner(" ", (Object[]) cmds); - System.out.println("Command line: [" + cmdLine + "]"); - return new ProcessBuilder(cmds); + return new ProcessBuilder(launcher.getCommand()); } // keytool @@ -67,7 +64,7 @@ pb.redirectInput(ProcessBuilder.Redirect.from(new File(RESPONSE_FILE))); try { - return ProcessTools.executeProcess(pb); + return execute(pb); } catch (Throwable t) { throw new RuntimeException("keytool failure: " + t); } finally { @@ -98,11 +95,20 @@ public static OutputAnalyzer jarsigner(List<String> args) throws Exception { + return execute(getProcessBuilder("jarsigner", args)); + } + + private static OutputAnalyzer execute(ProcessBuilder pb) throws Exception { try { - return ProcessTools.executeProcess( - getProcessBuilder("jarsigner", args)); + OutputAnalyzer oa = ProcessTools.executeCommand(pb); + System.out.println("Exit value: " + oa.getExitValue()); + return oa; } catch (Throwable t) { - throw new RuntimeException("jarsigner error: " + t); + if (t instanceof Exception) { + throw (Exception) t; + } else { + throw new Exception(t); + } } }
--- a/test/lib/testlibrary/jdk/testlibrary/Utils.java Mon Oct 22 04:45:27 2018 +0100 +++ b/test/lib/testlibrary/jdk/testlibrary/Utils.java Mon Oct 22 06:23:01 2018 +0100 @@ -35,6 +35,7 @@ import java.util.List; import java.util.Arrays; import java.util.Collections; +import java.util.Objects; import java.util.regex.Pattern; import java.util.regex.Matcher; import java.util.concurrent.TimeUnit; @@ -59,7 +60,6 @@ */ public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim(); - /** * Returns the value of 'test.timeout.factor' system property * converted to {@code double}. @@ -76,6 +76,9 @@ */ public static final long DEFAULT_TEST_TIMEOUT = TimeUnit.SECONDS.toMillis(120); + private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8; + private static final int DEFAULT_BUFFER_SIZE = 8192; + private Utils() { // Private constructor to prevent class instantiation } @@ -250,6 +253,40 @@ } /** + * Helper method to read all bytes from InputStream + * + * @param is InputStream to read from + * @return array of bytes + * @throws IOException + */ + public static byte[] readAllBytes(InputStream is) throws IOException { + byte[] buf = new byte[DEFAULT_BUFFER_SIZE]; + int capacity = buf.length; + int nread = 0; + int n; + for (;;) { + // read to EOF which may read more or less than initial buffer size + while ((n = is.read(buf, nread, capacity - nread)) > 0) + nread += n; + + // if the last call to read returned -1, then we're done + if (n < 0) + break; + + // need to allocate a larger buffer + if (capacity <= MAX_BUFFER_SIZE - capacity) { + capacity = capacity << 1; + } else { + if (capacity == MAX_BUFFER_SIZE) + throw new OutOfMemoryError("Required array size too large"); + capacity = MAX_BUFFER_SIZE; + } + buf = Arrays.copyOf(buf, capacity); + } + return (capacity == nread) ? buf : Arrays.copyOf(buf, nread); + } + + /** * Adjusts the provided timeout value for the TIMEOUT_FACTOR * @param tOut the timeout value to be adjusted * @return The timeout value adjusted for the value of "test.timeout.factor" @@ -286,7 +323,7 @@ * @throws NullPointerException if {@code in} or {@code out} is {@code null} * */ - public static long transferBetweenStreams(InputStream in, OutputStream out) + public static long transferTo(InputStream in, OutputStream out) throws IOException { long transferred = 0; byte[] buffer = new byte[BUFFER_SIZE];
--- a/test/sun/misc/JarIndex/metaInfFilenames/Basic.java Mon Oct 22 04:45:27 2018 +0100 +++ b/test/sun/misc/JarIndex/metaInfFilenames/Basic.java Mon Oct 22 06:23:01 2018 +0100 @@ -154,8 +154,7 @@ /* run javac <args> */ static void compile(String... args) { debug("Running: javac " + Arrays.toString(args)); - com.sun.tools.javac.main.Main compiler = new com.sun.tools.javac.main.Main("javac"); - if (compiler.compile(args) != 0) { + if (com.sun.tools.javac.Main.compile(args) != 0) { throw new RuntimeException("javac failed: args=" + Arrays.toString(args)); } } @@ -259,7 +258,7 @@ URLClassLoader loader = getLoader(baseURL); httpServer.reset(); - Class messageServiceClass = null; + Class<?> messageServiceClass = null; try { messageServiceClass = loader.loadClass(serviceClass); } catch (ClassNotFoundException cnfe) { @@ -267,7 +266,7 @@ throw new RuntimeException("Error in test: " + cnfe); } - Iterator<Class<?>> iterator = sun.misc.Service.providers(messageServiceClass, loader); + Iterator<?> iterator = sun.misc.Service.providers(messageServiceClass, loader); if (expectToFind && !iterator.hasNext()) { debug(messageServiceClass + " NOT found."); return false; @@ -301,7 +300,7 @@ URLClassLoader loader = getLoader(baseURL); httpServer.reset(); - Class messageServiceClass = null; + Class<?> messageServiceClass = null; try { messageServiceClass = loader.loadClass(serviceClass); } catch (ClassNotFoundException cnfe) { @@ -309,7 +308,7 @@ throw new RuntimeException("Error in test: " + cnfe); } - Iterator<Class<?>> iterator = (ServiceLoader.load(messageServiceClass, loader)).iterator(); + Iterator<?> iterator = (ServiceLoader.load(messageServiceClass, loader)).iterator(); if (expectToFind && !iterator.hasNext()) { debug(messageServiceClass + " NOT found."); return false; @@ -345,7 +344,7 @@ URLClassLoader loader = getLoader(baseURL); httpServer.reset(); - Class ADotAKlass = null; + Class<?> ADotAKlass = null; try { ADotAKlass = loader.loadClass("a.A"); } catch (ClassNotFoundException cnfe) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/ssl/CipherSuite/NoDesRC4CiphSuite.java Mon Oct 22 06:23:01 2018 +0100 @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8208350 + * @summary Disable all DES cipher suites + * @run main/othervm NoDesRC4CiphSuite + */ + +/* + * SunJSSE does not support dynamic system properties, no way to re-use + * system properties in samevm/agentvm mode. + */ + +import java.security.Security; +import javax.net.ssl.*; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.security.GeneralSecurityException; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +public class NoDesRC4CiphSuite { + + private static final boolean DEBUG = false; + + private static final byte RECTYPE_HS = 0x16; + private static final byte HSMSG_CLIHELLO = 0x01; + + // These are some groups of Cipher Suites by names and IDs + private static final List<Integer> DES_CS_LIST = Arrays.asList( + 0x0009, 0x0015, 0x0012, 0x001A, 0x0008, 0x0014, 0x0011, 0x0019 + ); + private static final String[] DES_CS_LIST_NAMES = new String[] { + "SSL_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_DSS_WITH_DES_CBC_SHA", + "SSL_DH_anon_WITH_DES_CBC_SHA", + "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA" + }; + private static final List<Integer> RC4_CS_LIST = Arrays.asList( + 0xC007, 0xC011, 0x0005, 0xC002, 0xC00C, 0x0004, 0xC016, 0x0018, + 0x0003, 0x0017 + ); + private static final String[] RC4_CS_LIST_NAMES = new String[] { + "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", + "TLS_ECDHE_RSA_WITH_RC4_128_SHA", + "SSL_RSA_WITH_RC4_128_SHA", + "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", + "TLS_ECDH_RSA_WITH_RC4_128_SHA", + "SSL_RSA_WITH_RC4_128_MD5", + "TLS_ECDH_anon_WITH_RC4_128_SHA", + "SSL_DH_anon_WITH_RC4_128_MD5", + "SSL_RSA_EXPORT_WITH_RC4_40_MD5", + "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5" + }; + + private static final ByteBuffer CLIOUTBUF = + ByteBuffer.wrap("Client Side".getBytes()); + + public static void main(String[] args) throws Exception { + boolean allGood = true; + String disAlg = Security.getProperty("jdk.tls.disabledAlgorithms"); + System.err.println("Disabled Algs: " + disAlg); + + // Disabled DES tests + allGood &= testDefaultCase(DES_CS_LIST); + allGood &= testEngAddDisabled(DES_CS_LIST_NAMES, DES_CS_LIST); + allGood &= testEngOnlyDisabled(DES_CS_LIST_NAMES); + + // Disabled RC4 tests + /* + RC4 is not yet disabled, as 8076221 has not been backported + allGood &= testDefaultCase(RC4_CS_LIST); + allGood &= testEngAddDisabled(RC4_CS_LIST_NAMES, RC4_CS_LIST); + allGood &= testEngOnlyDisabled(RC4_CS_LIST_NAMES); + */ + + if (allGood) { + System.err.println("All tests passed"); + } else { + throw new RuntimeException("One or more tests failed"); + } + } + + /** + * Create an engine with the default set of cipher suites enabled and make + * sure none of the disabled suites are present in the client hello. + * + * @param disabledSuiteIds the {@code List} of disabled cipher suite IDs + * to be checked for. + * + * @return true if the test passed (No disabled suites), false otherwise + */ + private static boolean testDefaultCase(List<Integer> disabledSuiteIds) + throws Exception { + System.err.println("\nTest: Default SSLEngine suite set"); + SSLEngine ssle = makeEngine(); + if (DEBUG) { + listCiphers("Suite set upon creation", ssle); + } + SSLEngineResult clientResult; + ByteBuffer cTOs = makeClientBuf(ssle); + clientResult = ssle.wrap(CLIOUTBUF, cTOs); + if (DEBUG) { + dumpResult("ClientHello: ", clientResult); + } + cTOs.flip(); + boolean foundSuite = areSuitesPresentCH(cTOs, disabledSuiteIds); + if (foundSuite) { + System.err.println("FAIL: Found disabled suites!"); + return false; + } else { + System.err.println("PASS: No disabled suites found."); + return true; + } + } + + /** + * Create an engine and set only disabled cipher suites. + * The engine should not create the client hello message since the only + * available suites to assert in the client hello are disabled ones. + * + * @param disabledSuiteNames an array of cipher suite names that + * should be disabled cipher suites. + * + * @return true if the engine throws SSLHandshakeException during client + * hello creation, false otherwise. + */ + private static boolean testEngOnlyDisabled(String[] disabledSuiteNames) + throws Exception { + System.err.println( + "\nTest: SSLEngine configured with only disabled suites"); + try { + SSLEngine ssle = makeEngine(); + ssle.setEnabledCipherSuites(disabledSuiteNames); + if (DEBUG) { + listCiphers("Suite set upon creation", ssle); + } + SSLEngineResult clientResult; + ByteBuffer cTOs = makeClientBuf(ssle); + clientResult = ssle.wrap(CLIOUTBUF, cTOs); + if (DEBUG) { + dumpResult("ClientHello: ", clientResult); + } + cTOs.flip(); + } catch (SSLHandshakeException shse) { + System.err.println("PASS: Caught expected exception: " + shse); + return true; + } + System.err.println("FAIL: Expected SSLHandshakeException not thrown"); + return false; + } + + /** + * Create an engine and add some disabled suites to the default + * set of cipher suites. Make sure none of the disabled suites show up + * in the client hello even though they were explicitly added. + * + * @param disabledSuiteNames an array of cipher suite names that + * should be disabled cipher suites. + * @param disabledIds the {@code List} of disabled cipher suite IDs + * to be checked for. + * + * @return true if the test passed (No disabled suites), false otherwise + */ + private static boolean testEngAddDisabled(String[] disabledNames, + List<Integer> disabledIds) throws Exception { + System.err.println("\nTest: SSLEngine with disabled suites added"); + SSLEngine ssle = makeEngine(); + + // Add disabled suites to the existing engine's set of enabled suites + String[] initialSuites = ssle.getEnabledCipherSuites(); + String[] plusDisSuites = Arrays.copyOf(initialSuites, + initialSuites.length + disabledNames.length); + System.arraycopy(disabledNames, 0, plusDisSuites, + initialSuites.length, disabledNames.length); + ssle.setEnabledCipherSuites(plusDisSuites); + + if (DEBUG) { + listCiphers("Suite set upon creation", ssle); + } + SSLEngineResult clientResult; + ByteBuffer cTOs = makeClientBuf(ssle); + clientResult = ssle.wrap(CLIOUTBUF, cTOs); + if (DEBUG) { + dumpResult("ClientHello: ", clientResult); + } + cTOs.flip(); + boolean foundDisabled = areSuitesPresentCH(cTOs, disabledIds); + if (foundDisabled) { + System.err.println("FAIL: Found disabled suites!"); + return false; + } else { + System.err.println("PASS: No disabled suites found."); + return true; + } + } + + private static SSLEngine makeEngine() throws GeneralSecurityException { + SSLContext ctx = SSLContext.getInstance("TLSv1.2"); + ctx.init(null, null, null); + return ctx.createSSLEngine(); + } + + private static ByteBuffer makeClientBuf(SSLEngine ssle) { + ssle.setUseClientMode(true); + ssle.setNeedClientAuth(false); + SSLSession sess = ssle.getSession(); + ByteBuffer cTOs = ByteBuffer.allocateDirect(sess.getPacketBufferSize()); + return cTOs; + } + + private static void listCiphers(String prefix, SSLEngine ssle) { + System.err.println(prefix + "\n---------------"); + String[] suites = ssle.getEnabledCipherSuites(); + for (String suite : suites) { + System.err.println(suite); + } + System.err.println("---------------"); + } + + /** + * Walk a TLS 1.2 or earlier ClientHello looking for any of the suites + * in the suiteIdList. + * + * @param clientHello a ByteBuffer containing the ClientHello message as + * a complete TLS record. The position of the buffer should be + * at the first byte of the TLS record header. + * @param suiteIdList a List of integer values corresponding to + * TLS cipher suite identifiers. + * + * @return true if at least one of the suites in {@code suiteIdList} + * is found in the ClientHello's cipher suite list + * + * @throws IOException if the data in the {@code clientHello} + * buffer is not a TLS handshake message or is not a client hello. + */ + private static boolean areSuitesPresentCH(ByteBuffer clientHello, + List<Integer> suiteIdList) throws IOException { + byte val; + + // Process the TLS Record + val = clientHello.get(); + if (val != RECTYPE_HS) { + throw new IOException( + "Not a handshake record, type = " + val); + } + + // Just skip over the version and length + clientHello.position(clientHello.position() + 4); + + // Check the handshake message type + val = clientHello.get(); + if (val != HSMSG_CLIHELLO) { + throw new IOException( + "Not a ClientHello handshake message, type = " + val); + } + + // Skip over the length + clientHello.position(clientHello.position() + 3); + + // Skip over the protocol version (2) and random (32); + clientHello.position(clientHello.position() + 34); + + // Skip past the session ID (variable length <= 32) + int len = byteToUnsignedInt(clientHello.get()); + if (len > 32) { + throw new IOException("Session ID is too large, len = " + len); + } + clientHello.position(clientHello.position() + len); + + // Finally, we are at the cipher suites. Walk the list and place them + // into a List. + int csLen = shortToUnsignedInt(clientHello.getShort()); + if (csLen % 2 != 0) { + throw new IOException("CipherSuite length is invalid, len = " + + csLen); + } + int csCount = csLen / 2; + List<Integer> csSuiteList = new ArrayList<>(csCount); + log("Found following suite IDs in hello:"); + for (int i = 0; i < csCount; i++) { + int curSuite = shortToUnsignedInt(clientHello.getShort()); + log(String.format("Suite ID: 0x%04x", curSuite)); + csSuiteList.add(curSuite); + } + + // Now check to see if any of the suites passed in match what is in + // the suite list. + boolean foundMatch = false; + for (Integer cs : suiteIdList) { + if (csSuiteList.contains(cs)) { + System.err.format("Found match for suite ID 0x%04x\n", cs); + foundMatch = true; + break; + } + } + + // We don't care about the rest of the ClientHello message. + // Rewind and return whether we found a match or not. + clientHello.rewind(); + return foundMatch; + } + + private static void dumpResult(String str, SSLEngineResult result) { + System.err.println("The format of the SSLEngineResult is: \n" + + "\t\"getStatus() / getHandshakeStatus()\" +\n" + + "\t\"bytesConsumed() / bytesProduced()\"\n"); + HandshakeStatus hsStatus = result.getHandshakeStatus(); + System.err.println(str + result.getStatus() + "/" + hsStatus + ", " + + result.bytesConsumed() + "/" + result.bytesProduced() + " bytes"); + if (hsStatus == HandshakeStatus.FINISHED) { + System.err.println("\t...ready for application data"); + } + } + + private static void log(String str) { + if (DEBUG) { + System.err.println(str); + } + } + + /** + * Converts the argument to an {@code int} by an unsigned + * conversion. In an unsigned conversion to an {@code int}, the + * high-order 24 bits of the {@code int} are zero and the + * low-order 8 bits are equal to the bits of the {@code byte} argument. + * + * Consequently, zero and positive {@code byte} values are mapped + * to a numerically equal {@code int} value and negative {@code + * byte} values are mapped to an {@code int} value equal to the + * input plus 2<sup>8</sup>. + * + * @param x the value to convert to an unsigned {@code int} + * @return the argument converted to {@code int} by an unsigned + * conversion + * @since 1.8 + */ + private static int byteToUnsignedInt(byte x) { + return ((int) x) & 0xff; + } + + /** + * Converts the argument to an {@code int} by an unsigned + * conversion. In an unsigned conversion to an {@code int}, the + * high-order 16 bits of the {@code int} are zero and the + * low-order 16 bits are equal to the bits of the {@code short} argument. + * + * Consequently, zero and positive {@code short} values are mapped + * to a numerically equal {@code int} value and negative {@code + * short} values are mapped to an {@code int} value equal to the + * input plus 2<sup>16</sup>. + * + * @param x the value to convert to an unsigned {@code int} + * @return the argument converted to {@code int} by an unsigned + * conversion + * @since 1.8 + */ + private static int shortToUnsignedInt(short x) { + return ((int) x) & 0xffff; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/ssl/HandshakeHash/DigestBase.java Mon Oct 22 06:23:01 2018 +0100 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.*; + +class DigestBase extends MessageDigestSpi { + + private MessageDigest digest = null; + + public DigestBase(String alg, String provider) throws Exception { + digest = MessageDigest.getInstance(alg, provider); + } + + @Override + protected void engineUpdate(byte input) { + digest.update(input); + } + + @Override + protected void engineUpdate(byte[] input, int offset, int len) { + digest.update(input, offset, len); + } + + @Override + protected byte[] engineDigest() { + return digest.digest(); + } + + @Override + protected void engineReset() { + digest.reset(); + } + + public static final class MD5 extends DigestBase { + public MD5() throws Exception { + super("MD5", "SUN"); + } + } + + public static final class SHA extends DigestBase { + public SHA() throws Exception { + super("SHA", "SUN"); + } + } + + public static final class SHA256 extends DigestBase { + public SHA256() throws Exception { + super("SHA-256", "SUN"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/ssl/HandshakeHash/HandshakeHashCloneExhaustion.java Mon Oct 22 06:23:01 2018 +0100 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// +// Please run in othervm mode. SunJSSE does not support dynamic system +// properties, no way to re-use system properties in samevm/agentvm mode. +// + +/* + * @test + * @bug 8148421 8193683 + * @summary Transport Layer Security (TLS) Session Hash and Extended + * Master Secret Extension + * @summary Increase the number of clones in the CloneableDigest + * @library /javax/net/ssl/templates + * @compile DigestBase.java + * @run main/othervm HandshakeHashCloneExhaustion + * TLSv1.1 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + */ + +import java.io.InputStream; +import java.io.OutputStream; +import java.security.MessageDigest; +import java.security.Security; +import javax.net.ssl.SSLSocket; + +public class HandshakeHashCloneExhaustion extends SSLSocketTemplate { + + private static String[] protocol; + private static String[] ciphersuite; + private static String[] mds = { "SHA", "MD5", "SHA-256" }; + + /* + * ================== + * Run the test case. + */ + public static void main(String[] args) throws Exception { + // Add in a non-cloneable MD5/SHA1/SHA-256 implementation + Security.insertProviderAt(new MyProvider(), 1); + // make sure our provider is functioning + for (String s : mds) { + MessageDigest md = MessageDigest.getInstance(s); + String p = md.getProvider().getName(); + if (!p.equals("MyProvider")) { + throw new RuntimeException("Unexpected provider: " + p); + } + } + + if (args.length != 2) { + throw new Exception( + "Usage: HandshakeHashCloneExhaustion protocol ciphersuite"); + } + + System.out.println("Testing: " + args[0] + " " + args[1]); + protocol = new String [] { args[0] }; + ciphersuite = new String[] { args[1] }; + + (new HandshakeHashCloneExhaustion()).run(); + } + + @Override + protected void runServerApplication(SSLSocket socket) throws Exception { + socket.setNeedClientAuth(true); + socket.setEnabledProtocols(protocol); + socket.setEnabledCipherSuites(ciphersuite); + + // here comes the test logic + InputStream sslIS = socket.getInputStream(); + OutputStream sslOS = socket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); + } + + @Override + protected void runClientApplication(SSLSocket socket) throws Exception { + InputStream sslIS = socket.getInputStream(); + OutputStream sslOS = socket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/ssl/HandshakeHash/MyProvider.java Mon Oct 22 06:23:01 2018 +0100 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.*; + +public final class MyProvider extends Provider { + + public MyProvider() { + super("MyProvider", 1.0d, + "Test Provider: SHA1/MD5/SHA256 exhaustion testing"); + put("MessageDigest.SHA", "DigestBase$SHA"); + put("MessageDigest.MD5", "DigestBase$MD5"); + put("MessageDigest.SHA-256", "DigestBase$SHA256"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ClientHandshaker/LengthCheckTest.java Mon Oct 22 06:23:01 2018 +0100 @@ -0,0 +1,855 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8044860 8074462 + * @summary Vectors and fixed length fields should be verified + * for allowed sizes. + * @run main/othervm LengthCheckTest + */ + +/** + * A SSLEngine usage example which simplifies the presentation + * by removing the I/O and multi-threading concerns. + * + * The test creates two SSLEngines, simulating a client and server. + * The "transport" layer consists two byte buffers: think of them + * as directly connected pipes. + * + * Note, this is a *very* simple example: real code will be much more + * involved. For example, different threading and I/O models could be + * used, transport mechanisms could close unexpectedly, and so on. + * + * When this application runs, notice that several messages + * (wrap/unwrap) pass before any application data is consumed or + * produced. (For more information, please see the SSL/TLS + * specifications.) There may several steps for a successful handshake, + * so it's typical to see the following series of operations: + * + * client server message + * ====== ====== ======= + * wrap() ... ClientHello + * ... unwrap() ClientHello + * ... wrap() ServerHello/Certificate + * unwrap() ... ServerHello/Certificate + * wrap() ... ClientKeyExchange + * wrap() ... ChangeCipherSpec + * wrap() ... Finished + * ... unwrap() ClientKeyExchange + * ... unwrap() ChangeCipherSpec + * ... unwrap() Finished + * ... wrap() ChangeCipherSpec + * ... wrap() Finished + * unwrap() ... ChangeCipherSpec + * unwrap() ... Finished + */ + +import javax.net.ssl.*; +import javax.net.ssl.SSLEngineResult.*; +import java.io.*; +import java.security.*; +import java.nio.*; +import java.util.List; +import java.util.ArrayList; +import sun.security.ssl.ProtocolVersion; + +public class LengthCheckTest { + + /* + * Enables logging of the SSLEngine operations. + */ + private static final boolean logging = true; + + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=all + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + private static final boolean dumpBufs = true; + + private final SSLContext sslc; + + private SSLEngine clientEngine; // client Engine + private ByteBuffer clientOut; // write side of clientEngine + private ByteBuffer clientIn; // read side of clientEngine + + private SSLEngine serverEngine; // server Engine + private ByteBuffer serverOut; // write side of serverEngine + private ByteBuffer serverIn; // read side of serverEngine + + private HandshakeTest handshakeTest; + + /* + * For data transport, this example uses local ByteBuffers. This + * isn't really useful, but the purpose of this example is to show + * SSLEngine concepts, not how to do network transport. + */ + private ByteBuffer cTOs; // "reliable" transport client->server + private ByteBuffer sTOc; // "reliable" transport server->client + + /* + * The following is to set up the keystores. + */ + private static final String pathToStores = "/../../../../../../../etc"; + private static final String keyStoreFile = "keystore"; + private static final String trustStoreFile = "truststore"; + private static final String passwd = "passphrase"; + + private static final String keyFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + keyStoreFile; + private static final String trustFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + trustStoreFile; + + // Define a few basic TLS record and message types we might need + private static final int TLS_RECTYPE_CCS = 0x14; + private static final int TLS_RECTYPE_ALERT = 0x15; + private static final int TLS_RECTYPE_HANDSHAKE = 0x16; + private static final int TLS_RECTYPE_APPDATA = 0x17; + + private static final int TLS_HS_HELLO_REQUEST = 0x00; + private static final int TLS_HS_CLIENT_HELLO = 0x01; + private static final int TLS_HS_SERVER_HELLO = 0x02; + private static final int TLS_HS_CERTIFICATE = 0x0B; + private static final int TLS_HS_SERVER_KEY_EXCHG = 0x0C; + private static final int TLS_HS_CERT_REQUEST = 0x0D; + private static final int TLS_HS_SERVER_HELLO_DONE = 0x0E; + private static final int TLS_HS_CERT_VERIFY = 0x0F; + private static final int TLS_HS_CLIENT_KEY_EXCHG = 0x10; + private static final int TLS_HS_FINISHED = 0x14; + + // We're not going to define all the alert types in TLS, just + // the ones we think we'll need to reference by name. + private static final int TLS_ALERT_LVL_WARNING = 0x01; + private static final int TLS_ALERT_LVL_FATAL = 0x02; + + private static final int TLS_ALERT_UNEXPECTED_MSG = 0x0A; + private static final int TLS_ALERT_HANDSHAKE_FAILURE = 0x28; + private static final int TLS_ALERT_INTERNAL_ERROR = 0x50; + + public interface HandshakeTest { + void execTest() throws Exception; + } + + public final HandshakeTest servSendLongID = new HandshakeTest() { + @Override + public void execTest() throws Exception { + boolean gotException = false; + SSLEngineResult clientResult; // results from client's last op + SSLEngineResult serverResult; // results from server's last op + + log("\n==== Test: Client receives 64-byte session ID ===="); + + // Send Client Hello + clientResult = clientEngine.wrap(clientOut, cTOs); + log("client wrap: ", clientResult); + runDelegatedTasks(clientResult, clientEngine); + cTOs.flip(); + dumpByteBuffer("CLIENT-TO-SERVER", cTOs); + + // Server consumes Client Hello + serverResult = serverEngine.unwrap(cTOs, serverIn); + log("server unwrap: ", serverResult); + runDelegatedTasks(serverResult, serverEngine); + cTOs.compact(); + + // Server generates ServerHello/Cert/Done record + serverResult = serverEngine.wrap(serverOut, sTOc); + log("server wrap: ", serverResult); + runDelegatedTasks(serverResult, serverEngine); + sTOc.flip(); + + // Intercept the ServerHello messages and instead send + // one that has a 64-byte session ID. + if (isTlsMessage(sTOc, TLS_RECTYPE_HANDSHAKE, + TLS_HS_SERVER_HELLO)) { + ArrayList<ByteBuffer> recList = splitRecord(sTOc); + + // Use the original ServerHello as a template to craft one + // with a longer-than-allowed session ID. + ByteBuffer servHelloBuf = + createEvilServerHello(recList.get(0), 64); + + recList.set(0, servHelloBuf); + + // Now send each ByteBuffer (each being a complete + // TLS record) into the client-side unwrap. + for (ByteBuffer bBuf : recList) { + dumpByteBuffer("SERVER-TO-CLIENT", bBuf); + try { + clientResult = clientEngine.unwrap(bBuf, clientIn); + } catch (SSLProtocolException e) { + log("Received expected SSLProtocolException: " + e); + gotException = true; + } + log("client unwrap: ", clientResult); + runDelegatedTasks(clientResult, clientEngine); + } + } else { + dumpByteBuffer("SERVER-TO-CLIENT", sTOc); + log("client unwrap: ", clientResult); + runDelegatedTasks(clientResult, clientEngine); + } + sTOc.compact(); + + // The Client should now send a TLS Alert + clientResult = clientEngine.wrap(clientOut, cTOs); + log("client wrap: ", clientResult); + runDelegatedTasks(clientResult, clientEngine); + cTOs.flip(); + dumpByteBuffer("CLIENT-TO-SERVER", cTOs); + + // At this point we can verify that both an exception + // was thrown and the proper action (a TLS alert) was + // sent back to the server. + if (gotException == false || + !isTlsMessage(cTOs, TLS_RECTYPE_ALERT, TLS_ALERT_LVL_FATAL, + TLS_ALERT_UNEXPECTED_MSG)) { + throw new SSLException( + "Client failed to throw Alert:fatal:internal_error"); + } + } + }; + + public final HandshakeTest clientSendLongID = new HandshakeTest() { + @Override + public void execTest() throws Exception { + boolean gotException = false; + SSLEngineResult clientResult; // results from client's last op + SSLEngineResult serverResult; // results from server's last op + + log("\n==== Test: Server receives 64-byte session ID ===="); + + // Send Client Hello + ByteBuffer evilClientHello = createEvilClientHello(64); + dumpByteBuffer("CLIENT-TO-SERVER", evilClientHello); + + try { + // Server consumes Client Hello + serverResult = serverEngine.unwrap(evilClientHello, serverIn); + log("server unwrap: ", serverResult); + runDelegatedTasks(serverResult, serverEngine); + evilClientHello.compact(); + + // Under normal circumstances this should be a ServerHello + // But should throw an exception instead due to the invalid + // session ID. + serverResult = serverEngine.wrap(serverOut, sTOc); + log("server wrap: ", serverResult); + runDelegatedTasks(serverResult, serverEngine); + sTOc.flip(); + dumpByteBuffer("SERVER-TO-CLIENT", sTOc); + } catch (SSLProtocolException ssle) { + log("Received expected SSLProtocolException: " + ssle); + gotException = true; + } + + // We expect to see the server generate an alert here + serverResult = serverEngine.wrap(serverOut, sTOc); + log("server wrap: ", serverResult); + runDelegatedTasks(serverResult, serverEngine); + sTOc.flip(); + dumpByteBuffer("SERVER-TO-CLIENT", sTOc); + + // At this point we can verify that both an exception + // was thrown and the proper action (a TLS alert) was + // sent back to the client. + if (gotException == false || + !isTlsMessage(sTOc, TLS_RECTYPE_ALERT, TLS_ALERT_LVL_FATAL, + TLS_ALERT_UNEXPECTED_MSG)) { + throw new SSLException( + "Server failed to throw Alert:fatal:internal_error"); + } + } + }; + + + /* + * Main entry point for this test. + */ + public static void main(String args[]) throws Exception { + List<LengthCheckTest> ccsTests = new ArrayList<>(); + + if (debug) { + System.setProperty("javax.net.debug", "ssl"); + } + + ccsTests.add(new LengthCheckTest("ServSendLongID")); + ccsTests.add(new LengthCheckTest("ClientSendLongID")); + + for (LengthCheckTest test : ccsTests) { + test.runTest(); + } + + System.out.println("Test Passed."); + } + + /* + * Create an initialized SSLContext to use for these tests. + */ + public LengthCheckTest(String testName) throws Exception { + + KeyStore ks = KeyStore.getInstance("JKS"); + KeyStore ts = KeyStore.getInstance("JKS"); + + char[] passphrase = "passphrase".toCharArray(); + + ks.load(new FileInputStream(keyFilename), passphrase); + ts.load(new FileInputStream(trustFilename), passphrase); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, passphrase); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ts); + + SSLContext sslCtx = SSLContext.getInstance("TLS"); + + sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + sslc = sslCtx; + + switch (testName) { + case "ServSendLongID": + handshakeTest = servSendLongID; + break; + case "ClientSendLongID": + handshakeTest = clientSendLongID; + break; + default: + throw new IllegalArgumentException("Unknown test name: " + + testName); + } + } + + /* + * Run the test. + * + * Sit in a tight loop, both engines calling wrap/unwrap regardless + * of whether data is available or not. We do this until both engines + * report back they are closed. + * + * The main loop handles all of the I/O phases of the SSLEngine's + * lifetime: + * + * initial handshaking + * application data transfer + * engine closing + * + * One could easily separate these phases into separate + * sections of code. + */ + private void runTest() throws Exception { + boolean dataDone = false; + + createSSLEngines(); + createBuffers(); + + handshakeTest.execTest(); + } + + /* + * Using the SSLContext created during object creation, + * create/configure the SSLEngines we'll use for this test. + */ + private void createSSLEngines() throws Exception { + /* + * Configure the serverEngine to act as a server in the SSL/TLS + * handshake. Also, require SSL client authentication. + */ + serverEngine = sslc.createSSLEngine(); + serverEngine.setUseClientMode(false); + serverEngine.setNeedClientAuth(false); + + /* + * Similar to above, but using client mode instead. + */ + clientEngine = sslc.createSSLEngine("client", 80); + clientEngine.setUseClientMode(true); + + // In order to make a test that will be backwards compatible + // going back to JDK 5, force the handshake to be TLS 1.0 and + // use one of the older cipher suites. + clientEngine.setEnabledProtocols(new String[]{"TLSv1"}); + clientEngine.setEnabledCipherSuites( + new String[]{"TLS_RSA_WITH_AES_128_CBC_SHA"}); + } + + /* + * Create and size the buffers appropriately. + */ + private void createBuffers() { + + /* + * We'll assume the buffer sizes are the same + * between client and server. + */ + SSLSession session = clientEngine.getSession(); + int appBufferMax = session.getApplicationBufferSize(); + int netBufferMax = session.getPacketBufferSize(); + + /* + * We'll make the input buffers a bit bigger than the max needed + * size, so that unwrap()s following a successful data transfer + * won't generate BUFFER_OVERFLOWS. + * + * We'll use a mix of direct and indirect ByteBuffers for + * tutorial purposes only. In reality, only use direct + * ByteBuffers when they give a clear performance enhancement. + */ + clientIn = ByteBuffer.allocate(appBufferMax + 50); + serverIn = ByteBuffer.allocate(appBufferMax + 50); + + cTOs = ByteBuffer.allocateDirect(netBufferMax); + sTOc = ByteBuffer.allocateDirect(netBufferMax); + + clientOut = ByteBuffer.wrap("Hi Server, I'm Client".getBytes()); + serverOut = ByteBuffer.wrap("Hello Client, I'm Server".getBytes()); + } + + /* + * If the result indicates that we have outstanding tasks to do, + * go ahead and run them in this thread. + */ + private static void runDelegatedTasks(SSLEngineResult result, + SSLEngine engine) throws Exception { + + if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + log("\trunning delegated task..."); + runnable.run(); + } + HandshakeStatus hsStatus = engine.getHandshakeStatus(); + if (hsStatus == HandshakeStatus.NEED_TASK) { + throw new Exception( + "handshake shouldn't need additional tasks"); + } + log("\tnew HandshakeStatus: " + hsStatus); + } + } + + private static boolean isEngineClosed(SSLEngine engine) { + return (engine.isOutboundDone() && engine.isInboundDone()); + } + + /* + * Simple check to make sure everything came across as expected. + */ + private static void checkTransfer(ByteBuffer a, ByteBuffer b) + throws Exception { + a.flip(); + b.flip(); + + if (!a.equals(b)) { + throw new Exception("Data didn't transfer cleanly"); + } else { + log("\tData transferred cleanly"); + } + + a.position(a.limit()); + b.position(b.limit()); + a.limit(a.capacity()); + b.limit(b.capacity()); + } + + /* + * Logging code + */ + private static boolean resultOnce = true; + + private static void log(String str, SSLEngineResult result) { + if (!logging) { + return; + } + if (resultOnce) { + resultOnce = false; + System.out.println("The format of the SSLEngineResult is: \n" + + "\t\"getStatus() / getHandshakeStatus()\" +\n" + + "\t\"bytesConsumed() / bytesProduced()\"\n"); + } + HandshakeStatus hsStatus = result.getHandshakeStatus(); + log(str + + result.getStatus() + "/" + hsStatus + ", " + + result.bytesConsumed() + "/" + result.bytesProduced() + + " bytes"); + if (hsStatus == HandshakeStatus.FINISHED) { + log("\t...ready for application data"); + } + } + + private static void log(String str) { + if (logging) { + System.out.println(str); + } + } + + /** + * Split a record consisting of multiple TLS handshake messages + * into individual TLS records, each one in a ByteBuffer of its own. + * + * @param tlsRecord A ByteBuffer containing the tls record data. + * The position of the buffer should be at the first byte + * in the TLS record data. + * + * @return An ArrayList consisting of one or more ByteBuffers. Each + * ByteBuffer will contain a single TLS record with one message. + * That message will be taken from the input record. The order + * of the messages in the ArrayList will be the same as they + * were in the input record. + */ + private ArrayList<ByteBuffer> splitRecord(ByteBuffer tlsRecord) { + SSLSession session = clientEngine.getSession(); + int netBufferMax = session.getPacketBufferSize(); + ArrayList<ByteBuffer> recordList = new ArrayList<>(); + + if (tlsRecord.hasRemaining()) { + int type = byteToUnsignedInt(tlsRecord.get()); + byte ver_major = tlsRecord.get(); + byte ver_minor = tlsRecord.get(); + int recLen = shortToUnsignedInt(tlsRecord.getShort()); + byte[] newMsgData = null; + while (tlsRecord.hasRemaining()) { + ByteBuffer newRecord = ByteBuffer.allocateDirect(netBufferMax); + switch (type) { + case TLS_RECTYPE_CCS: + case TLS_RECTYPE_ALERT: + case TLS_RECTYPE_APPDATA: + // None of our tests have multiple non-handshake + // messages coalesced into a single record. + break; + case TLS_RECTYPE_HANDSHAKE: + newMsgData = getHandshakeMessage(tlsRecord); + break; + } + + // Put a new TLS record on the destination ByteBuffer + newRecord.put((byte)type); + newRecord.put(ver_major); + newRecord.put(ver_minor); + newRecord.putShort((short)newMsgData.length); + + // Now add the message content itself and attach to the + // returned ArrayList + newRecord.put(newMsgData); + newRecord.flip(); + recordList.add(newRecord); + } + } + + return recordList; + } + + private static ByteBuffer createEvilClientHello(int sessIdLen) { + ByteBuffer newRecord = ByteBuffer.allocateDirect(4096); + + // Lengths will initially be place holders until we determine the + // finished length of the ByteBuffer. Then we'll go back and scribble + // in the correct lengths. + + newRecord.put((byte)TLS_RECTYPE_HANDSHAKE); // Record type + newRecord.putShort((short)0x0301); // Protocol (TLS 1.0) + newRecord.putShort((short)0); // Length place holder + + newRecord.putInt(TLS_HS_CLIENT_HELLO << 24); // HS type and length + newRecord.putShort((short)0x0301); + newRecord.putInt((int)(System.currentTimeMillis() / 1000)); + SecureRandom sr = new SecureRandom(); + byte[] randBuf = new byte[28]; + sr.nextBytes(randBuf); + newRecord.put(randBuf); // Client Random + newRecord.put((byte)sessIdLen); // Session ID length + if (sessIdLen > 0) { + byte[] sessId = new byte[sessIdLen]; + sr.nextBytes(sessId); + newRecord.put(sessId); // Session ID + } + newRecord.putShort((short)2); // 2 bytes of ciphers + newRecord.putShort((short)0x002F); // TLS_RSA_AES_CBC_SHA + newRecord.putShort((short)0x0100); // only null compression + newRecord.putShort((short)5); // 5 bytes of extensions + newRecord.putShort((short)0xFF01); // Renegotiation info + newRecord.putShort((short)1); + newRecord.put((byte)0); // No reneg info exts + + // Go back and fill in the correct length values for the record + // and handshake message headers. + int recordLength = newRecord.position(); + newRecord.putShort(3, (short)(recordLength - 5)); + int newTypeAndLen = (newRecord.getInt(5) & 0xFF000000) | + ((recordLength - 9) & 0x00FFFFFF); + newRecord.putInt(5, newTypeAndLen); + + newRecord.flip(); + return newRecord; + } + + private static ByteBuffer createEvilServerHello(ByteBuffer origHello, + int newSessIdLen) { + if (newSessIdLen < 0 || newSessIdLen > Byte.MAX_VALUE) { + throw new RuntimeException("Length must be 0 <= X <= 127"); + } + + ByteBuffer newRecord = ByteBuffer.allocateDirect(4096); + // Copy the bytes from the old hello to the new up to the session ID + // field. We will go back later and fill in a new length field in + // the record header. This includes the record header (5 bytes), the + // Handshake message header (4 bytes), protocol version (2 bytes), + // and the random (32 bytes). + ByteBuffer scratchBuffer = origHello.slice(); + scratchBuffer.limit(43); + newRecord.put(scratchBuffer); + + // Advance the position in the originial hello buffer past the + // session ID. + origHello.position(43); + int origIDLen = byteToUnsignedInt(origHello.get()); + if (origIDLen > 0) { + // Skip over the session ID + origHello.position(origHello.position() + origIDLen); + } + + // Now add our own sessionID to the new record + SecureRandom sr = new SecureRandom(); + byte[] sessId = new byte[newSessIdLen]; + sr.nextBytes(sessId); + newRecord.put((byte)newSessIdLen); + newRecord.put(sessId); + + // Create another slice in the original buffer, based on the position + // past the session ID. Copy the remaining bytes into the new + // hello buffer. Then go back and fix up the length + newRecord.put(origHello.slice()); + + // Go back and fill in the correct length values for the record + // and handshake message headers. + int recordLength = newRecord.position(); + newRecord.putShort(3, (short)(recordLength - 5)); + int newTypeAndLen = (newRecord.getInt(5) & 0xFF000000) | + ((recordLength - 9) & 0x00FFFFFF); + newRecord.putInt(5, newTypeAndLen); + + newRecord.flip(); + return newRecord; + } + + /** + * Look at an incoming TLS record and see if it is the desired + * record type, and where appropriate the correct subtype. + * + * @param srcRecord The input TLS record to be evaluated. This + * method will only look at the leading message if multiple + * TLS handshake messages are coalesced into a single record. + * @param reqRecType The requested TLS record type + * @param recParams Zero or more integer sub type fields. For CCS + * and ApplicationData, no params are used. For handshake records, + * one value corresponding to the HandshakeType is required. + * For Alerts, two values corresponding to AlertLevel and + * AlertDescription are necessary. + * + * @return true if the proper handshake message is the first one + * in the input record, false otherwise. + */ + private boolean isTlsMessage(ByteBuffer srcRecord, int reqRecType, + int... recParams) { + boolean foundMsg = false; + + if (srcRecord.hasRemaining()) { + srcRecord.mark(); + + // Grab the fields from the TLS Record + int recordType = byteToUnsignedInt(srcRecord.get()); + byte ver_major = srcRecord.get(); + byte ver_minor = srcRecord.get(); + int recLen = shortToUnsignedInt(srcRecord.getShort()); + + if (recordType == reqRecType) { + // For any zero-length recParams, making sure the requested + // type is sufficient. + if (recParams.length == 0) { + foundMsg = true; + } else { + switch (recordType) { + case TLS_RECTYPE_CCS: + case TLS_RECTYPE_APPDATA: + // We really shouldn't find ourselves here, but + // if someone asked for these types and had more + // recParams we can ignore them. + foundMsg = true; + break; + case TLS_RECTYPE_ALERT: + // Needs two params, AlertLevel and AlertDescription + if (recParams.length != 2) { + throw new RuntimeException( + "Test for Alert requires level and desc."); + } else { + int level = byteToUnsignedInt(srcRecord.get()); + int desc = byteToUnsignedInt(srcRecord.get()); + if (level == recParams[0] && + desc == recParams[1]) { + foundMsg = true; + } + } + break; + case TLS_RECTYPE_HANDSHAKE: + // Needs one parameter, HandshakeType + if (recParams.length != 1) { + throw new RuntimeException( + "Test for Handshake requires only HS type"); + } else { + // Go into the first handhshake message in the + // record and grab the handshake message header. + // All we need to do is parse out the leading + // byte. + int msgHdr = srcRecord.getInt(); + int msgType = (msgHdr >> 24) & 0x000000FF; + if (msgType == recParams[0]) { + foundMsg = true; + } + } + break; + } + } + } + + srcRecord.reset(); + } + + return foundMsg; + } + + private byte[] getHandshakeMessage(ByteBuffer srcRecord) { + // At the start of this routine, the position should be lined up + // at the first byte of a handshake message. Mark this location + // so we can return to it after reading the type and length. + srcRecord.mark(); + int msgHdr = srcRecord.getInt(); + int type = (msgHdr >> 24) & 0x000000FF; + int length = msgHdr & 0x00FFFFFF; + + // Create a byte array that has enough space for the handshake + // message header and body. + byte[] data = new byte[length + 4]; + srcRecord.reset(); + srcRecord.get(data, 0, length + 4); + + return (data); + } + + /** + * Hex-dumps a ByteBuffer to stdout. + */ + private static void dumpByteBuffer(String header, ByteBuffer bBuf) { + if (dumpBufs == false) { + return; + } + + int bufLen = bBuf.remaining(); + if (bufLen > 0) { + bBuf.mark(); + + // We expect the position of the buffer to be at the + // beginning of a TLS record. Get the type, version and length. + int type = byteToUnsignedInt(bBuf.get()); + int ver_major = byteToUnsignedInt(bBuf.get()); + int ver_minor = byteToUnsignedInt(bBuf.get()); + int recLen = shortToUnsignedInt(bBuf.getShort()); + ProtocolVersion pv = ProtocolVersion.valueOf(ver_major, ver_minor); + + log("===== " + header + " (" + tlsRecType(type) + " / " + + pv + " / " + bufLen + " bytes) ====="); + bBuf.reset(); + for (int i = 0; i < bufLen; i++) { + if (i != 0 && i % 16 == 0) { + System.out.print("\n"); + } + System.out.format("%02X ", bBuf.get(i)); + } + log("\n==============================================="); + bBuf.reset(); + } + } + + private static String tlsRecType(int type) { + switch (type) { + case 20: + return "Change Cipher Spec"; + case 21: + return "Alert"; + case 22: + return "Handshake"; + case 23: + return "Application Data"; + default: + return ("Unknown (" + type + ")"); + } + } + + /** + * Converts the argument to an {@code int} by an unsigned + * conversion. In an unsigned conversion to an {@code int}, the + * high-order 24 bits of the {@code int} are zero and the + * low-order 8 bits are equal to the bits of the {@code byte} argument. + * + * Consequently, zero and positive {@code byte} values are mapped + * to a numerically equal {@code int} value and negative {@code + * byte} values are mapped to an {@code int} value equal to the + * input plus 2<sup>8</sup>. + * + * @param x the value to convert to an unsigned {@code int} + * @return the argument converted to {@code int} by an unsigned + * conversion + * @since 1.8 + */ + private static int byteToUnsignedInt(byte x) { + return ((int) x) & 0xff; + } + + /** + * Converts the argument to an {@code int} by an unsigned + * conversion. In an unsigned conversion to an {@code int}, the + * high-order 16 bits of the {@code int} are zero and the + * low-order 16 bits are equal to the bits of the {@code short} argument. + * + * Consequently, zero and positive {@code short} values are mapped + * to a numerically equal {@code int} value and negative {@code + * short} values are mapped to an {@code int} value equal to the + * input plus 2<sup>16</sup>. + * + * @param x the value to convert to an unsigned {@code int} + * @return the argument converted to {@code int} by an unsigned + * conversion + * @since 1.8 + */ + private static int shortToUnsignedInt(short x) { + return ((int) x) & 0xffff; + } + +}
--- a/test/sun/security/tools/jarsigner/TimestampCheck.java Mon Oct 22 04:45:27 2018 +0100 +++ b/test/sun/security/tools/jarsigner/TimestampCheck.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. 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 @@ -22,6 +22,8 @@ */ import com.sun.net.httpserver.*; + +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; @@ -36,16 +38,21 @@ import java.security.PrivateKey; import java.security.Signature; import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; import sun.misc.IOUtils; -import jdk.testlibrary.*; +import jdk.testlibrary.SecurityTools; +import jdk.testlibrary.OutputAnalyzer; import jdk.testlibrary.JarUtils; import sun.security.pkcs.ContentInfo; import sun.security.pkcs.PKCS7; @@ -58,9 +65,12 @@ import sun.security.x509.AlgorithmId; import sun.security.x509.X500Name; +import jdk.testlibrary.Utils; + /* * @test * @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 8169688 8171121 + * 8180289 * @summary checking response of timestamp * @modules java.base/sun.security.pkcs * java.base/sun.security.timestamp @@ -68,7 +78,7 @@ * java.base/sun.security.util * java.base/sun.security.tools.keytool * @library /lib/testlibrary - * @run main/timeout=600 TimestampCheck + * @run main/othervm/timeout=600 TimestampCheck */ public class TimestampCheck { @@ -114,12 +124,12 @@ */ byte[] sign(byte[] input, String path) throws Exception { DerValue value = new DerValue(input); - System.err.println("\nIncoming Request\n==================="); - System.err.println("Version: " + value.data.getInteger()); + System.out.println("\nIncoming Request\n==================="); + System.out.println("Version: " + value.data.getInteger()); DerValue messageImprint = value.data.getDerValue(); AlgorithmId aid = AlgorithmId.parse( messageImprint.data.getDerValue()); - System.err.println("AlgorithmId: " + aid); + System.out.println("AlgorithmId: " + aid); ObjectIdentifier policyId = new ObjectIdentifier(defaultPolicyId); BigInteger nonce = null; @@ -127,25 +137,24 @@ DerValue v = value.data.getDerValue(); if (v.tag == DerValue.tag_Integer) { nonce = v.getBigInteger(); - System.err.println("nonce: " + nonce); + System.out.println("nonce: " + nonce); } else if (v.tag == DerValue.tag_Boolean) { - System.err.println("certReq: " + v.getBoolean()); + System.out.println("certReq: " + v.getBoolean()); } else if (v.tag == DerValue.tag_ObjectId) { policyId = v.getOID(); - System.err.println("PolicyID: " + policyId); + System.out.println("PolicyID: " + policyId); } } - System.err.println("\nResponse\n==================="); + System.out.println("\nResponse\n==================="); FileInputStream is = new FileInputStream(keystore); KeyStore ks = KeyStore.getInstance("JCEKS"); ks.load(is, "changeit".toCharArray()); is.close(); - String alias = "ts"; - if (path.startsWith("bad") || path.equals("weak")) { - alias = "ts" + path; - } + // If path starts with "ts", use the TSA it points to. + // Otherwise, always use "ts". + String alias = path.startsWith("ts") ? path : "ts"; if (path.equals("diffpolicy")) { policyId = new ObjectIdentifier(defaultPolicyId); @@ -196,6 +205,9 @@ tst.putInteger(1); Calendar cal = Calendar.getInstance(); + if (path.equals("tsold")) { + cal.add(Calendar.DAY_OF_MONTH, -20); + } tst.putGeneralizedTime(cal.getTime()); if (path.equals("diffnonce")) { @@ -223,10 +235,10 @@ "1.2.840.113549.1.9.16.1.4"), new DerValue(tstInfo2.toByteArray())); - System.err.println("Signing..."); - System.err.println(new X500Name(signer + System.out.println("Signing..."); + System.out.println(new X500Name(signer .getIssuerX500Principal().getName())); - System.err.println(signer.getSerialNumber()); + System.out.println(signer.getSerialNumber()); SignerInfo signerInfo = new SignerInfo( new X500Name(signer.getIssuerX500Principal().getName()), @@ -299,24 +311,52 @@ prepare(); - try (Handler tsa = Handler.init(0, "tsks");) { + try (Handler tsa = Handler.init(0, "ks");) { tsa.start(); int port = tsa.getPort(); host = "http://localhost:" + port + "/"; if (args.length == 0) { // Run this test - sign("none") + + sign("normal") + .shouldNotContain("Warning") + .shouldHaveExitValue(0); + + verify("normal.jar") + .shouldNotContain("Warning") + .shouldHaveExitValue(0); + + // Simulate signing at a previous date: + // 1. tsold will create a timestamp of 20 days ago. + // 2. oldsigner expired 10 days ago. + // jarsigner will show a warning at signing. + signVerbose("tsold", "unsigned.jar", "tsold.jar", "oldsigner") + .shouldHaveExitValue(4); + + // It verifies perfectly. + verify("tsold.jar", "-verbose", "-certs") + .shouldNotContain("Warning") + .shouldHaveExitValue(0); + + signVerbose(null, "unsigned.jar", "none.jar", "signer") .shouldContain("is not timestamped") .shouldHaveExitValue(0); - sign("badku") - .shouldHaveExitValue(0); + signVerbose(null, "unsigned.jar", "badku.jar", "badku") + .shouldHaveExitValue(8); checkBadKU("badku.jar"); - sign("normal") - .shouldNotContain("is not timestamped") - .shouldHaveExitValue(0); + // 8180289: unvalidated TSA cert chain + sign("tsnoca") + .shouldContain("TSA certificate chain is invalid") + .shouldHaveExitValue(64); + + verify("tsnoca.jar", "-verbose", "-certs") + .shouldHaveExitValue(64) + .shouldContain("jar verified") + .shouldContain("Invalid TSA certificate chain") + .shouldContain("TSA certificate chain is invalid"); sign("nononce") .shouldHaveExitValue(1); @@ -328,11 +368,11 @@ .shouldHaveExitValue(1); sign("fullchain") .shouldHaveExitValue(0); // Success, 6543440 solved. - sign("bad1") + sign("tsbad1") .shouldHaveExitValue(1); - sign("bad2") + sign("tsbad2") .shouldHaveExitValue(1); - sign("bad3") + sign("tsbad3") .shouldHaveExitValue(1); sign("nocert") .shouldHaveExitValue(1); @@ -344,119 +384,171 @@ sign("diffpolicy", "-tsapolicyid", "1.2.3") .shouldHaveExitValue(1); - sign("tsaalg", "-tsadigestalg", "SHA") + sign("sha1alg", "-tsadigestalg", "SHA") .shouldHaveExitValue(0); - checkTimestamp("tsaalg.jar", defaultPolicyId, "SHA-1"); + checkTimestamp("sha1alg.jar", defaultPolicyId, "SHA-1"); - sign("weak", "-digestalg", "MD5", + sign("tsweak", "-digestalg", "MD5", "-sigalg", "MD5withRSA", "-tsadigestalg", "MD5") - .shouldHaveExitValue(0); - checkWeak("weak.jar"); + .shouldHaveExitValue(68); + checkWeak("tsweak.jar"); + + signVerbose("tsweak", "unsigned.jar", "tsweak2.jar", "signer") + .shouldHaveExitValue(64) + .shouldContain("TSA certificate chain is invalid"); - signWithAliasAndTsa("halfWeak", "old.jar", "old", "-digestalg", "MD5") - .shouldHaveExitValue(0); + // Weak timestamp is an error and jar treated unsigned + verify("tsweak2.jar", "-verbose") + .shouldHaveExitValue(16) + .shouldContain("treated as unsigned") + .shouldMatch("Timestamp.*512.*weak"); + + signVerbose("normal", "unsigned.jar", "halfWeak.jar", "signer", + "-digestalg", "MD5") + .shouldHaveExitValue(4); checkHalfWeak("halfWeak.jar"); // sign with DSA key - signWithAliasAndTsa("sign1", "old.jar", "dsakey") + signVerbose("normal", "unsigned.jar", "sign1.jar", "dsakey") .shouldHaveExitValue(0); // sign with RSAkeysize < 1024 - signWithAliasAndTsa("sign2", "sign1.jar", "weakkeysize") - .shouldHaveExitValue(0); + signVerbose("normal", "sign1.jar", "sign2.jar", "weakkeysize") + .shouldHaveExitValue(4); checkMultiple("sign2.jar"); // When .SF or .RSA is missing or invalid checkMissingOrInvalidFiles("normal.jar"); + + if (Files.exists(Paths.get("ts2.cert"))) { + checkInvalidTsaCertKeyUsage(); + } } else { // Run as a standalone server - System.err.println("Press Enter to quit server"); + System.out.println("Press Enter to quit server"); System.in.read(); } } } + private static void checkInvalidTsaCertKeyUsage() throws Exception { + + // Hack: Rewrite the TSA cert inside normal.jar into ts2.jar. + + // Both the cert and the serial number must be rewritten. + byte[] tsCert = Files.readAllBytes(Paths.get("ts.cert")); + byte[] ts2Cert = Files.readAllBytes(Paths.get("ts2.cert")); + byte[] tsSerial = getCert(tsCert) + .getSerialNumber().toByteArray(); + byte[] ts2Serial = getCert(ts2Cert) + .getSerialNumber().toByteArray(); + + byte[] oldBlock; + try (JarFile normal = new JarFile("normal.jar")) { + oldBlock = Utils.readAllBytes(normal.getInputStream( + normal.getJarEntry("META-INF/SIGNER.RSA"))); + } + + JarUtils.updateJar("normal.jar", "ts2.jar", + mapOf("META-INF/SIGNER.RSA", + updateBytes(updateBytes(oldBlock, tsCert, ts2Cert), + tsSerial, ts2Serial))); + + verify("ts2.jar", "-verbose", "-certs") + .shouldHaveExitValue(64) + .shouldContain("jar verified") + .shouldContain("Invalid TSA certificate chain: Extended key usage does not permit use for TSA server"); + } + + public static X509Certificate getCert(byte[] data) + throws CertificateException, IOException { + return (X509Certificate) + CertificateFactory.getInstance("X.509") + .generateCertificate(new ByteArrayInputStream(data)); + } + + private static byte[] updateBytes(byte[] old, byte[] from, byte[] to) { + int pos = 0; + while (true) { + if (pos + from.length > old.length) { + return null; + } + if (Arrays.equals(Arrays.copyOfRange(old, pos, pos+from.length), from)) { + byte[] result = old.clone(); + System.arraycopy(to, 0, result, pos, from.length); + return result; + } + pos++; + } + } + private static void checkMissingOrInvalidFiles(String s) throws Throwable { - JarUtils.updateJar(s, "1.jar", "-", "META-INF/OLD.SF"); + + JarUtils.updateJar(s, "1.jar", mapOf("META-INF/SIGNER.SF", Boolean.FALSE)); verify("1.jar", "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") - .shouldContain("Missing signature-related file META-INF/OLD.SF"); - JarUtils.updateJar(s, "2.jar", "-", "META-INF/OLD.RSA"); + .shouldContain("Missing signature-related file META-INF/SIGNER.SF"); + JarUtils.updateJar(s, "2.jar", mapOf("META-INF/SIGNER.RSA", Boolean.FALSE)); verify("2.jar", "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") - .shouldContain("Missing block file for signature-related file META-INF/OLD.SF"); - JarUtils.updateJar(s, "3.jar", "META-INF/OLD.SF"); + .shouldContain("Missing block file for signature-related file META-INF/SIGNER.SF"); + JarUtils.updateJar(s, "3.jar", mapOf("META-INF/SIGNER.SF", "dummy")); verify("3.jar", "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") - .shouldContain("Unparsable signature-related file META-INF/OLD.SF"); - JarUtils.updateJar(s, "4.jar", "META-INF/OLD.RSA"); + .shouldContain("Unparsable signature-related file META-INF/SIGNER.SF"); + JarUtils.updateJar(s, "4.jar", mapOf("META-INF/SIGNER.RSA", "dummy")); verify("4.jar", "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") - .shouldContain("Unparsable signature-related file META-INF/OLD.RSA"); + .shouldContain("Unparsable signature-related file META-INF/SIGNER.RSA"); } static OutputAnalyzer jarsigner(List<String> extra) - throws Throwable { - JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner") - .addVMArg("-Duser.language=en") - .addVMArg("-Duser.country=US") - .addToolArg("-keystore") - .addToolArg("tsks") - .addToolArg("-storepass") - .addToolArg("changeit"); - for (String s : extra) { - if (s.startsWith("-J")) { - launcher.addVMArg(s.substring(2)); - } else { - launcher.addToolArg(s); - } - } - System.err.println("COMMAND: "); - for (String cmd : launcher.getCommand()) { - System.err.print(cmd + " "); - } - System.err.println(); - return ProcessTools.executeCommand(launcher.getCommand()); + throws Exception { + List<String> args = new ArrayList<>( + listOf("-keystore", "ks", "-storepass", "changeit")); + args.addAll(extra); + return SecurityTools.jarsigner(args); } static OutputAnalyzer verify(String file, String... extra) - throws Throwable { + throws Exception { List<String> args = new ArrayList<>(); args.add("-verify"); + args.add("-strict"); args.add(file); args.addAll(Arrays.asList(extra)); return jarsigner(args); } - static void checkBadKU(String file) throws Throwable { + static void checkBadKU(String file) throws Exception { System.err.println("BadKU: " + file); verify(file) - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") .shouldContain("re-run jarsigner with debug enabled"); verify(file, "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("Signed by") .shouldContain("treated as unsigned") .shouldContain("re-run jarsigner with debug enabled"); verify(file, "-J-Djava.security.debug=jar") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("SignatureException: Key usage restricted") .shouldContain("treated as unsigned") .shouldContain("re-run jarsigner with debug enabled"); } - static void checkWeak(String file) throws Throwable { + static void checkWeak(String file) throws Exception { verify(file) - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") .shouldMatch("weak algorithm that is now disabled.") .shouldMatch("Re-run jarsigner with the -verbose option for more details"); verify(file, "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") .shouldMatch("weak algorithm that is now disabled by") .shouldMatch("Digest algorithm: .*weak") @@ -465,18 +557,18 @@ .shouldNotMatch("Timestamp signature algorithm: .*weak.*weak") .shouldMatch("Timestamp signature algorithm: .*key.*weak"); verify(file, "-J-Djava.security.debug=jar") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldMatch("SignatureException:.*disabled"); } - static void checkHalfWeak(String file) throws Throwable { + static void checkHalfWeak(String file) throws Exception { verify(file) - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") .shouldMatch("weak algorithm that is now disabled.") .shouldMatch("Re-run jarsigner with the -verbose option for more details"); verify(file, "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") .shouldMatch("weak algorithm that is now disabled by") .shouldMatch("Digest algorithm: .*weak") @@ -486,7 +578,7 @@ .shouldNotMatch("Timestamp signature algorithm: .*key.*weak"); } - static void checkMultiple(String file) throws Throwable { + static void checkMultiple(String file) throws Exception { verify(file) .shouldHaveExitValue(0) .shouldContain("jar verified"); @@ -503,7 +595,7 @@ static void checkTimestamp(String file, String policyId, String digestAlg) throws Exception { try (JarFile jf = new JarFile(file)) { - JarEntry je = jf.getJarEntry("META-INF/OLD.RSA"); + JarEntry je = jf.getJarEntry("META-INF/SIGNER.RSA"); try (InputStream is = jf.getInputStream(je)) { byte[] content = IOUtils.readFully(is, -1, true); PKCS7 p7 = new PKCS7(content); @@ -529,26 +621,38 @@ static int which = 0; /** + * Sign with a TSA path. Always use alias "signer" to sign "unsigned.jar". + * The signed jar name is always path.jar. + * * @param extra more args given to jarsigner */ static OutputAnalyzer sign(String path, String... extra) - throws Throwable { - String alias = path.equals("badku") ? "badku" : "old"; - return signWithAliasAndTsa(path, "old.jar", alias, extra); + throws Exception { + return signVerbose( + path, + "unsigned.jar", + path + ".jar", + "signer", + extra); } - static OutputAnalyzer signWithAliasAndTsa (String path, String jar, - String alias, String...extra) throws Throwable { + static OutputAnalyzer signVerbose( + String path, // TSA URL path + String oldJar, + String newJar, + String alias, // signer + String...extra) throws Exception { which++; - System.err.println("\n>> Test #" + which + ": " + Arrays.toString(extra)); + System.out.println("\n>> Test #" + which); List<String> args = new ArrayList<>(); - args.add("-J-Djava.security.egd=file:/dev/./urandom"); + args.add("-strict"); + args.add("-verbose"); args.add("-debug"); args.add("-signedjar"); - args.add(path + ".jar"); - args.add(jar); + args.add(newJar); + args.add(oldJar); args.add(alias); - if (!path.equals("none") && !path.equals("badku")) { + if (path != null) { args.add("-tsa"); args.add(host + path); } @@ -557,24 +661,54 @@ } static void prepare() throws Exception { - jdk.testlibrary.JarUtils.createJar("old.jar", "A"); - Files.deleteIfExists(Paths.get("tsks")); - keytool("-alias ca -genkeypair -ext bc -dname CN=CA"); - keytool("-alias old -genkeypair -dname CN=old"); + JarUtils.createJar("unsigned.jar", "A"); + Files.deleteIfExists(Paths.get("ks")); + keytool("-alias signer -genkeypair -ext bc -dname CN=signer"); + keytool("-alias oldsigner -genkeypair -dname CN=oldsigner"); keytool("-alias dsakey -genkeypair -keyalg DSA -dname CN=dsakey"); keytool("-alias weakkeysize -genkeypair -keysize 512 -dname CN=weakkeysize"); keytool("-alias badku -genkeypair -dname CN=badku"); keytool("-alias ts -genkeypair -dname CN=ts"); - keytool("-alias tsweak -genkeypair -keysize 512 -dname CN=tsbad1"); + keytool("-alias tsold -genkeypair -dname CN=tsold"); + keytool("-alias tsweak -genkeypair -keysize 512 -dname CN=tsweak"); keytool("-alias tsbad1 -genkeypair -dname CN=tsbad1"); keytool("-alias tsbad2 -genkeypair -dname CN=tsbad2"); keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3"); + keytool("-alias tsnoca -genkeypair -dname CN=tsnoca"); - gencert("old"); + // tsnoca's issuer will be removed from keystore later + keytool("-alias ca -genkeypair -ext bc -dname CN=CA"); + gencert("tsnoca", "-ext eku:critical=ts"); + keytool("-delete -alias ca"); + keytool("-alias ca -genkeypair -ext bc -dname CN=CA -startdate -40d"); + + gencert("signer"); + gencert("oldsigner", "-startdate -30d -validity 20"); gencert("dsakey"); gencert("weakkeysize"); gencert("badku", "-ext ku:critical=keyAgreement"); gencert("ts", "-ext eku:critical=ts"); + + + for (int i = 0; i < 5; i++) { + // Issue another cert for "ts" with a different EKU. + // Length might be different because serial number is + // random. Try several times until a cert with the same + // length is generated so we can substitute ts.cert + // embedded in the PKCS7 block with ts2.cert. + // If cannot create one, related test will be ignored. + keytool("-gencert -alias ca -infile ts.req -outfile ts2.cert " + + "-ext eku:critical=1.3.6.1.5.5.7.3.9"); + if (Files.size(Paths.get("ts.cert")) != Files.size(Paths.get("ts2.cert"))) { + Files.delete(Paths.get("ts2.cert")); + System.out.println("Warning: cannot create same length"); + } else { + break; + } + } + + gencert("tsold", "-ext eku:critical=ts -startdate -40d -validity 45"); + gencert("tsweak", "-ext eku:critical=ts"); gencert("tsbad1"); gencert("tsbad2", "-ext eku=ts"); @@ -593,8 +727,16 @@ } static void keytool(String cmd) throws Exception { - cmd = "-keystore tsks -storepass changeit -keypass changeit " + + cmd = "-keystore ks -storepass changeit -keypass changeit " + "-keyalg rsa -validity 200 " + cmd; sun.security.tools.keytool.Main.main(cmd.split(" ")); } + + static <K> Map<K,Object> mapOf(K k1, Object v1) { + return Collections.singletonMap(k1, v1); + } + + static <E> List<E> listOf(E... elements) { + return Arrays.asList(elements); + } }
--- a/test/sun/security/tools/jarsigner/TsacertOptionTest.java Mon Oct 22 04:45:27 2018 +0100 +++ b/test/sun/security/tools/jarsigner/TsacertOptionTest.java Mon Oct 22 06:23:01 2018 +0100 @@ -46,6 +46,7 @@ + ".txt"; private static final String PASSWORD = "changeit"; private static final String KEYSTORE = "ks.jks"; + private static final String CA_KEY_ALIAS = "ca"; private static final String SIGNING_KEY_ALIAS = "sign_alias"; private static final String TSA_KEY_ALIAS = "ts"; private static final String KEY_ALG = "RSA"; @@ -73,20 +74,52 @@ // look for free network port for TSA service int port = jdk.testlibrary.Utils.getFreePort(); - String host = jdk.testlibrary.Utils.getHostname(); + String host = "127.0.0.1"; String tsaUrl = "http://" + host + ":" + port; // create key pair for jar signing ProcessTools.executeCommand(KEYTOOL, "-genkey", + "-alias", CA_KEY_ALIAS, + "-keyalg", KEY_ALG, + "-keysize", Integer.toString(KEY_SIZE), + "-keystore", KEYSTORE, + "-storepass", PASSWORD, + "-keypass", PASSWORD, + "-dname", "CN=CA", + "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0); + ProcessTools.executeCommand(KEYTOOL, + "-genkey", "-alias", SIGNING_KEY_ALIAS, "-keyalg", KEY_ALG, "-keysize", Integer.toString(KEY_SIZE), "-keystore", KEYSTORE, "-storepass", PASSWORD, "-keypass", PASSWORD, - "-dname", "CN=Test", - "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0); + "-dname", "CN=Test").shouldHaveExitValue(0); + ProcessTools.executeCommand(KEYTOOL, + "-certreq", + "-alias", SIGNING_KEY_ALIAS, + "-keystore", KEYSTORE, + "-storepass", PASSWORD, + "-keypass", PASSWORD, + "-file", "certreq").shouldHaveExitValue(0); + ProcessTools.executeCommand(KEYTOOL, + "-gencert", + "-alias", CA_KEY_ALIAS, + "-keystore", KEYSTORE, + "-storepass", PASSWORD, + "-keypass", PASSWORD, + "-validity", Integer.toString(VALIDITY), + "-infile", "certreq", + "-outfile", "cert").shouldHaveExitValue(0); + ProcessTools.executeCommand(KEYTOOL, + "-importcert", + "-alias", SIGNING_KEY_ALIAS, + "-keystore", KEYSTORE, + "-storepass", PASSWORD, + "-keypass", PASSWORD, + "-file", "cert").shouldHaveExitValue(0); // create key pair for TSA service // SubjectInfoAccess extension contains URL to TSA service
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/tools/jarsigner/Warning.java Mon Oct 22 06:23:01 2018 +0100 @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.testlibrary.JDKToolLauncher; +import jdk.testlibrary.JarUtils; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; + +/** + * @test + * @bug 8024302 8026037 8130132 + * @summary warnings, errors and -strict + * @library /lib/testlibrary + */ +public class Warning { + + public static void main(String[] args) throws Throwable { + + Files.deleteIfExists(Paths.get("ks")); + + newCert("ca", "-validity 365000"); + + recreateJar(); + + newCert("a"); + run("jarsigner", "a.jar a") + .shouldContain("is self-signed"); + run("jarsigner", "a.jar a -strict") + .shouldContain("is self-signed") + .shouldHaveExitValue(4); + // Trusted entry can be self-signed without a warning + run("jarsigner", "-verify a.jar") + .shouldNotContain("is self-signed") + .shouldNotContain("not signed by alias in this keystore"); + run("keytool", "-delete -alias a"); + // otherwise a warning will be shown + run("jarsigner", "-verify a.jar") + .shouldContain("is self-signed") + .shouldContain("not signed by alias in this keystore"); + + recreateJar(); + + newCert("b"); + issueCert("b"); + run("jarsigner", "a.jar b") + .shouldNotContain("is self-signed"); + run("jarsigner", "-verify a.jar") + .shouldNotContain("is self-signed"); + + run("jarsigner", "a.jar b -digestalg MD5") + .shouldContain("-digestalg option is considered a security risk."); + run("jarsigner", "a.jar b -digestalg MD5 -strict") + .shouldHaveExitValue(4) + .shouldContain("-digestalg option is considered a security risk."); + run("jarsigner", "a.jar b -sigalg MD5withRSA") + .shouldContain("-sigalg option is considered a security risk"); + + issueCert("b", "-sigalg MD5withRSA"); + run("jarsigner", "a.jar b") + .shouldMatch("chain is invalid. Reason:.*MD5withRSA"); + + recreateJar(); + + newCert("c", "-keysize 512"); + issueCert("c"); + run("jarsigner", "a.jar c") + .shouldContain("chain is invalid. " + + "Reason: Algorithm constraints check failed"); + + recreateJar(); + + newCert("s1"); issueCert("s1", "-startdate 2000/01/01 -validity 36525"); + run("jarsigner", "a.jar s1") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp").shouldContain("2100-01-01") + .shouldNotContain("with signer errors"); + run("jarsigner", "a.jar s1 -strict") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp").shouldContain("2100-01-01") + .shouldNotContain("with signer errors"); + run("jarsigner", "a.jar s1 -verify") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp").shouldContain("2100-01-01") + .shouldNotContain("with signer errors"); + run("jarsigner", "a.jar s1 -verify -strict") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp").shouldContain("2100-01-01") + .shouldNotContain("with signer errors"); + + recreateJar(); + + newCert("s2"); issueCert("s2", "-validity 100"); + run("jarsigner", "a.jar s2") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp") + .shouldContain("will expire") + .shouldNotContain("with signer errors"); + run("jarsigner", "a.jar s2 -strict") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp") + .shouldContain("will expire") + .shouldNotContain("with signer errors"); + run("jarsigner", "a.jar s2 -verify") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp") + .shouldContain("will expire") + .shouldNotContain("with signer errors"); + run("jarsigner", "a.jar s2 -verify -strict") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp") + .shouldContain("will expire") + .shouldNotContain("with signer errors"); + + recreateJar(); + + newCert("s3"); issueCert("s3", "-startdate -200d -validity 100"); + run("jarsigner", "a.jar s3") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldContain("has expired") + .shouldNotContain("with signer errors") + .shouldNotContain("Error:"); + run("jarsigner", "a.jar s3 -strict") + .shouldHaveExitValue(4) + .shouldContain("with signer errors") + .shouldMatch("(?s).*Error:.*has expired.*Warning:.*"); + run("jarsigner", "a.jar s3 -verify") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("with signer errors") + .shouldNotContain("Error:"); + run("jarsigner", "a.jar s3 -verify -strict") + .shouldHaveExitValue(4) + .shouldContain("with signer errors") + .shouldMatch("(?s).*Error:.*has expired.*Warning:.*"); + } + + // Creates a new jar without signature + static void recreateJar() throws Exception { + JarUtils.createJar("a.jar", "ks"); + } + + // Creates a self-signed cert for alias with zero or more -genkey options + static void newCert(String alias, String... more) throws Throwable { + String args = "-genkeypair -alias " + alias + " -dname CN=" + alias; + for (String s: more) { + args += " " + s; + } + run("keytool", args).shouldHaveExitValue(0); + } + + // Asks ca to issue a cert to alias with zero or more -gencert options + static void issueCert(String alias, String...more) throws Throwable { + String req = run("keytool", "-certreq -alias " + alias) + .shouldHaveExitValue(0).getStdout(); + String args = "-gencert -alias ca -rfc"; + for (String s: more) { + args += " " + s; + } + String cert = run("keytool", args, req) + .shouldHaveExitValue(0).getStdout(); + run("keytool", "-import -alias " + alias, cert).shouldHaveExitValue(0); + } + + // Runs a java tool with command line arguments + static OutputAnalyzer run(String command, String args) + throws Throwable { + return run(command, args, null); + } + + // Runs a java tool with command line arguments and an optional input block + static OutputAnalyzer run(String command, String args, String input) + throws Throwable { + JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(command); + launcher.addVMArg("-Duser.language=en").addVMArg("-Duser.country=US"); + switch (command) { + case "keytool": + for (String s: new String[] { + "-keystore", "ks", "-storepass", "changeit", + "-storetype", "jks", + "-keypass", "changeit", "-keyalg", "rsa", "-debug"}) { + launcher.addToolArg(s); + } + break; + case "jarsigner": + for (String s: new String[] { + "-keystore", "ks", "-storepass", "changeit", + "-storetype", "jks"}) { + launcher.addToolArg(s); + } + break; + } + for (String arg: args.split(" ")) { + launcher.addToolArg(arg); + } + String[] cmd = launcher.getCommand(); + ProcessBuilder pb = new ProcessBuilder(cmd); + OutputAnalyzer out = ProcessTools.executeProcess(pb, input); + System.out.println("======================"); + System.out.println(Arrays.toString(cmd)); + String msg = " stdout: [" + out.getStdout() + "];\n" + + " stderr: [" + out.getStderr() + "]\n" + + " exitValue = " + out.getExitValue() + "\n"; + System.out.println(msg); + return out; + } +} +
--- a/test/sun/security/tools/jarsigner/checkusage.sh Mon Oct 22 04:45:27 2018 +0100 +++ b/test/sun/security/tools/jarsigner/checkusage.sh Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2017, Oracle and/or its affiliates. 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 @@ -91,7 +91,7 @@ #[ $RESULT = 0 ] || exit 2 # Test 3: When no keystore is specified, the error is only -# "chain not validated" +# "chain invalid" $JARSIGNER -strict -verify a.jar RESULT=$? @@ -99,7 +99,7 @@ #[ $RESULT = 4 ] || exit 3 # Test 4: When unrelated keystore is specified, the error is -# "chain not validated" and "not alias in keystore" +# "chain invalid" and "not alias in keystore" $JARSIGNER -keystore unrelated.jks -strict -verify a.jar RESULT=$?
--- a/test/sun/security/tools/jarsigner/concise_jarsigner.sh Mon Oct 22 04:45:27 2018 +0100 +++ b/test/sun/security/tools/jarsigner/concise_jarsigner.sh Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2014, Oracle and/or its affiliates. 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 @@ -22,10 +22,10 @@ # # @test -# @bug 6802846 +# @bug 6802846 8172529 # @summary jarsigner needs enhanced cert validation(options) # -# @run shell concise_jarsigner.sh +# @run shell/timeout=240 concise_jarsigner.sh # if [ "${TESTJAVA}" = "" ] ; then @@ -44,12 +44,15 @@ ;; esac -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore js.jks" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner -JAVAC=$TESTJAVA${FS}bin${FS}javac +TESTTOOLVMOPTS="$TESTTOOLVMOPTS -J-Duser.language=en -J-Duser.country=US" -rm js.jks +KS=js.ks +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS -keyalg rsa -keysize 1024" +JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -debug" +JAVAC="$TESTJAVA${FS}bin${FS}javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS}" + +rm $KS echo class A1 {} > A1.java echo class A2 {} > A2.java @@ -65,14 +68,14 @@ # First part: output format # ========================================================== -$KT -genkeypair -alias a1 -dname CN=a1 -validity 365 -$KT -genkeypair -alias a2 -dname CN=a2 -validity 365 +$KT -genkeypair -alias a1 -dname CN=a1 -validity 366 +$KT -genkeypair -alias a2 -dname CN=a2 -validity 366 # a.jar includes 8 unsigned, 2 signed by a1 and a2, 2 signed by a3 $JAR cvf a.jar A1.class A2.class -$JARSIGNER -keystore js.jks -storepass changeit a.jar a1 +$JARSIGNER -keystore $KS -storepass changeit a.jar a1 $JAR uvf a.jar A3.class A4.class -$JARSIGNER -keystore js.jks -storepass changeit a.jar a2 +$JARSIGNER -keystore $KS -storepass changeit a.jar a2 $JAR uvf a.jar A5.class A6.class # Verify OK @@ -84,15 +87,15 @@ [ $? = 20 ] || exit $LINENO # 16(hasUnsignedEntry) -$JARSIGNER -verify a.jar -strict -keystore js.jks +$JARSIGNER -verify a.jar -strict -keystore $KS -storepass changeit [ $? = 16 ] || exit $LINENO # 16(hasUnsignedEntry)+32(notSignedByAlias) -$JARSIGNER -verify a.jar a1 -strict -keystore js.jks +$JARSIGNER -verify a.jar a1 -strict -keystore $KS -storepass changeit [ $? = 48 ] || exit $LINENO # 16(hasUnsignedEntry) -$JARSIGNER -verify a.jar a1 a2 -strict -keystore js.jks +$JARSIGNER -verify a.jar a1 a2 -strict -keystore $KS -storepass changeit [ $? = 16 ] || exit $LINENO # 12 entries all together @@ -132,43 +135,52 @@ [ $LINES = 4 ] || exit $LINENO # ========================================================== -# Second part: exit code 2, 4, 8 +# Second part: exit code 2, 4, 8. # 16 and 32 already covered in the first part # ========================================================== -$KT -genkeypair -alias expired -dname CN=expired -startdate -10m -$KT -genkeypair -alias notyetvalid -dname CN=notyetvalid -startdate +1m -$KT -genkeypair -alias badku -dname CN=badku -ext KU=cRLSign -validity 365 -$KT -genkeypair -alias badeku -dname CN=badeku -ext EKU=sa -validity 365 -$KT -genkeypair -alias goodku -dname CN=goodku -ext KU=dig -validity 365 -$KT -genkeypair -alias goodeku -dname CN=goodeku -ext EKU=codesign -validity 365 +$KT -genkeypair -alias ca -dname CN=ca -ext bc -validity 365 +$KT -genkeypair -alias expired -dname CN=expired +$KT -certreq -alias expired | $KT -gencert -alias ca -startdate -10m | $KT -import -alias expired +$KT -genkeypair -alias notyetvalid -dname CN=notyetvalid +$KT -certreq -alias notyetvalid | $KT -gencert -alias ca -startdate +1m | $KT -import -alias notyetvalid +$KT -genkeypair -alias badku -dname CN=badku +$KT -certreq -alias badku | $KT -gencert -alias ca -ext KU=cRLSign -validity 365 | $KT -import -alias badku +$KT -genkeypair -alias badeku -dname CN=badeku +$KT -certreq -alias badeku | $KT -gencert -alias ca -ext EKU=sa -validity 365 | $KT -import -alias badeku +$KT -genkeypair -alias goodku -dname CN=goodku +$KT -certreq -alias goodku | $KT -gencert -alias ca -ext KU=dig -validity 365 | $KT -import -alias goodku +$KT -genkeypair -alias goodeku -dname CN=goodeku +$KT -certreq -alias goodeku | $KT -gencert -alias ca -ext EKU=codesign -validity 365 | $KT -import -alias goodeku -# badchain signed by ca, but ca is removed later -$KT -genkeypair -alias badchain -dname CN=badchain -validity 365 -$KT -genkeypair -alias ca -dname CN=ca -ext bc -validity 365 -$KT -certreq -alias badchain | $KT -gencert -alias ca -validity 365 | \ - $KT -importcert -alias badchain -$KT -delete -alias ca +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar expired +[ $? = 4 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar expired +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar notyetvalid [ $? = 4 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar notyetvalid -[ $? = 4 ] || exit $LINENO +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar badku +[ $? = 8 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badku +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar badeku [ $? = 8 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badeku -[ $? = 8 ] || exit $LINENO +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar goodku +[ $? = 0 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar goodku +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar goodeku [ $? = 0 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar goodeku -[ $? = 0 ] || exit $LINENO +# badchain signed by ca1, but ca1 is removed later +$KT -genkeypair -alias badchain -dname CN=badchain -validity 365 +$KT -genkeypair -alias ca1 -dname CN=ca1 -ext bc -validity 365 +$KT -certreq -alias badchain | $KT -gencert -alias ca1 -validity 365 | \ + $KT -importcert -alias badchain +# save ca1.cert for easy replay +$KT -exportcert -file ca1.cert -alias ca1 +$KT -delete -alias ca1 -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badchain +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar badchain [ $? = 4 ] || exit $LINENO $JARSIGNER -verify a.jar @@ -178,23 +190,55 @@ # Third part: -certchain test # ========================================================== -# altchain signed by ca2, but ca2 is removed later +# altchain signed by ca2 $KT -genkeypair -alias altchain -dname CN=altchain -validity 365 $KT -genkeypair -alias ca2 -dname CN=ca2 -ext bc -validity 365 $KT -certreq -alias altchain | $KT -gencert -alias ca2 -validity 365 -rfc > certchain $KT -exportcert -alias ca2 -rfc >> certchain -$KT -delete -alias ca2 -# Now altchain is still self-signed -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar altchain +# Self-signed cert does not work +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar altchain +[ $? = 4 ] || exit $LINENO + +# -certchain works +$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain [ $? = 0 ] || exit $LINENO -# If -certchain is used, then it's bad -$JARSIGNER -strict -keystore js.jks -storepass changeit -certchain certchain a.jar altchain +# if ca2 is removed, -certchain still work because altchain is a self-signed entry and +# it is trusted by jarsigner +# save ca2.cert for easy replay +$KT -exportcert -file ca2.cert -alias ca2 +$KT -delete -alias ca2 +$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain +[ $? = 0 ] || exit $LINENO + +# if cert is imported, -certchain won't work because this certificate entry is not trusted +$KT -importcert -file certchain -alias altchain -noprompt +$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain [ $? = 4 ] || exit $LINENO $JARSIGNER -verify a.jar [ $? = 0 ] || exit $LINENO +# ========================================================== +# 8172529 +# ========================================================== + +$KT -genkeypair -alias ee -dname CN=ee +$KT -genkeypair -alias caone -dname CN=caone +$KT -genkeypair -alias catwo -dname CN=catwo + +$KT -certreq -alias ee | $KT -gencert -alias catwo -rfc > ee.cert +$KT -certreq -alias catwo | $KT -gencert -alias caone -sigalg MD5withRSA -rfc > catwo.cert + +# This certchain contains a cross-signed weak catwo.cert +cat ee.cert catwo.cert | $KT -importcert -alias ee + +$JAR cvf a.jar A1.class +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar ee +[ $? = 0 ] || exit $LINENO +$JARSIGNER -strict -keystore $KS -storepass changeit -verify a.jar +[ $? = 0 ] || exit $LINENO + echo OK exit 0
--- a/test/sun/security/tools/jarsigner/ec.sh Mon Oct 22 04:45:27 2018 +0100 +++ b/test/sun/security/tools/jarsigner/ec.sh Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2012, Oracle and/or its affiliates. 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 @@ -53,10 +53,20 @@ echo A > A $JAR cvf $JFILE A -$KT -alias a -dname CN=a -keyalg ec -genkey -validity 300 || exit 11 -$KT -alias b -dname CN=b -keyalg ec -genkey -validity 300 || exit 12 -$KT -alias c -dname CN=c -keyalg ec -genkey -validity 300 || exit 13 +$KT -alias ca -dname CN=ca -keyalg ec -genkey -validity 300 || exit 11 + +$KT -alias a -dname CN=a -keyalg ec -genkey || exit 11 +$KT -alias a -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias a || exit 111 + +$KT -alias b -dname CN=b -keyalg ec -genkey || exit 12 +$KT -alias b -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias b || exit 121 + +# Ensure that key length is sufficient for the intended hash (SHA512withECDSA) +$KT -alias c -dname CN=c -keyalg ec -genkey -keysize 521 || exit 13 +$KT -alias c -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias c || exit 131 + $KT -alias x -dname CN=x -keyalg ec -genkey -validity 300 || exit 14 +$KT -alias x -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias x || exit 141 $JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 21 $JARSIGNER -keystore $KS -storepass changeit $JFILE b -debug -strict -sigalg SHA1withECDSA || exit 22
--- a/test/sun/security/tools/jarsigner/onlymanifest.sh Mon Oct 22 04:45:27 2018 +0100 +++ b/test/sun/security/tools/jarsigner/onlymanifest.sh Mon Oct 22 06:23:01 2018 +0100 @@ -57,12 +57,14 @@ echo "Key: Value" > manifest $JAR cvfm $JFILE manifest -$KT -alias a -dname CN=a -genkey -validity 300 || exit 1 -$JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 2 +$KT -alias ca -dname CN=ca -genkey -validity 300 || exit 1 +$KT -alias a -dname CN=a -genkey -validity 300 || exit 2 +$KT -alias a -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias a || exit 3 +$JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 4 $JARSIGNER -keystore $KS -storepass changeit -verify $JFILE a -debug -strict \ - > onlymanifest.out || exit 3 + > onlymanifest.out || exit 5 -grep unsigned onlymanifest.out && exit 4 +grep unsigned onlymanifest.out && exit 6 exit 0
--- a/test/sun/security/tools/jarsigner/warnings.sh Mon Oct 22 04:45:27 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -# -# Copyright (c) 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# @test -# @bug 8024302 -# @bug 8026037 -# @summary Clarify jar verifications -# - -if [ "${TESTJAVA}" = "" ] ; then - JAVAC_CMD=`which javac` - TESTJAVA=`dirname $JAVAC_CMD`/.. -fi - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - Windows_* ) - FS="\\" - ;; - * ) - FS="/" - ;; -esac - -KS=warnings.jks -JFILE=warnings.jar - -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit \ - -keystore $KS" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner -keystore $KS -storepass changeit" - -rm $KS 2> /dev/null - -LANG=C -export LANG - -echo 12345 > file - -ERR="" - -# Normal signer expiring on 2100-01-01 -$KT -alias s1 -dname CN=s1 -genkey -startdate 2000/01/01 -validity 36525 || ERR="$ERR keytool s1," -# Cert expiring soon, informational warning -$KT -alias s2 -dname CN=s2 -genkey -validity 100 || ERR="$ERR keytool s2," -# Cert expired, severe warning -$KT -alias s3 -dname CN=s3 -genkey -startdate -200d -validity 100 || ERR="$ERR keytool s3," - -# noTimestamp is informatiional warning and includes a date -$JAR cvf $JFILE file -$JARSIGNER $JFILE s1 > output1 || ERR="$ERR jarsigner s1," -$JARSIGNER -strict $JFILE s1 >> output1 || ERR="$ERR jarsigner s1 strict," -$JARSIGNER -verify $JFILE s1 >> output1 || ERR="$ERR jarsigner s1," -$JARSIGNER -verify -strict $JFILE s1 >> output1 || ERR="$ERR jarsigner s1 strict," - -cat output1 | grep Warning || ERR="$ERR s1 warning," -cat output1 | grep Error && ERR="$ERR s1 error," -cat output1 | grep timestamp | grep 2100-01-01 || ERR="$ERR s1 timestamp," -cat output1 | grep "with signer errors" && ERR="$ERR s1 err," - -# hasExpiringCert is informatiional warning -$JAR cvf $JFILE file -$JARSIGNER $JFILE s2 > output2 || ERR="$ERR jarsigner s2," -$JARSIGNER -strict $JFILE s2 >> output2 || ERR="$ERR jarsigner s2 strict," -$JARSIGNER -verify $JFILE s2 >> output2 || ERR="$ERR jarsigner s2," -$JARSIGNER -verify -strict $JFILE s2 >> output2 || ERR="$ERR jarsigner s2 strict," - -cat output2 | grep Warning || ERR="$ERR s2 warning," -cat output2 | grep Error && ERR="$ERR s2 error," -cat output2 | grep timestamp || ERR="$ERR s2 timestamp," -cat output2 | grep "will expire" || ERR="$ERR s2 expiring," -cat output2 | grep "with signer errors" && ERR="$ERR s2 err," - -# hasExpiredCert is severe warning -$JAR cvf $JFILE file -$JARSIGNER $JFILE s3 > output3 || ERR="$ERR jarsigner s3," -$JARSIGNER -strict $JFILE s3 > output3s && ERR="$ERR jarsigner s3 strict," -$JARSIGNER -verify $JFILE s3 >> output3 || ERR="$ERR jarsigner s3," -$JARSIGNER -verify -strict $JFILE s3 >> output3s && ERR="$ERR jarsigner s3 strict," - -# warning without -strict -cat output3 | grep Warning || ERR="$ERR s3 warning," -cat output3 | grep Error && ERR="$ERR s3 error," -cat output3 | grep "with signer errors" && ERR="$ERR s3 err," - -# error with -strict -cat output3s | grep Warning || ERR="$ERR s3s warning," -cat output3s | grep Error || ERR="$ERR s3s error," -cat output3s | grep "with signer errors" || ERR="$ERR s3 err," - -if [ "$ERR" = "" ]; then - exit 0 -else - echo "ERR is $ERR" - exit 1 -fi - -
--- a/test/sun/security/tools/jarsigner/warnings/Test.java Mon Oct 22 04:45:27 2018 +0100 +++ b/test/sun/security/tools/jarsigner/warnings/Test.java Mon Oct 22 06:23:01 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. 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 @@ -63,7 +63,7 @@ static final String CHAIN_NOT_VALIDATED_VERIFYING_WARNING = "This jar contains entries " - + "whose certificate chain is not validated."; + + "whose certificate chain is invalid."; static final String ALIAS_NOT_IN_STORE_VERIFYING_WARNING = "This jar contains signed entries " @@ -95,7 +95,7 @@ + "doesn't allow code signing."; static final String CHAIN_NOT_VALIDATED_SIGNING_WARNING - = "The signer's certificate chain is not validated."; + = "The signer's certificate chain is invalid."; static final String HAS_EXPIRING_CERT_SIGNING_WARNING = "The signer certificate will expire within six months.";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/tools/jarsigner/weaksize.sh Mon Oct 22 06:23:01 2018 +0100 @@ -0,0 +1,60 @@ +# +# Copyright (c) 2014, 2017, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 8044755 +# @summary Add a test for algorithm constraints check in jarsigner +# + +if [ "${TESTJAVA}" = "" ] ; then + JAVAC_CMD=`which javac` + TESTJAVA=`dirname $JAVAC_CMD`/.. +fi + +# The sigalg used is MD2withRSA, which is obsolete. + +KT="$TESTJAVA/bin/keytool ${TESTTOOLVMOPTS} -keystore ks + -storepass changeit -keypass changeit + -keyalg rsa -sigalg MD2withRSA -debug" +JS="$TESTJAVA/bin/jarsigner ${TESTTOOLVMOPTS} -keystore ks + -storepass changeit -strict -debug" +JAR="$TESTJAVA/bin/jar ${TESTTOOLVMOPTS}" + +rm ks 2> /dev/null + +$KT -genkeypair -alias ca -dname CN=CA -ext bc +$KT -genkeypair -alias signer -dname CN=Signer + +$KT -certreq -alias signer | \ + $KT -gencert -alias ca -ext ku=dS -rfc | \ + $KT -importcert -alias signer + +$JAR cvf a.jar ks + +# We always trust a TrustedCertificateEntry +$JS a.jar ca | grep "chain is invalid" && exit 1 + +# An end-entity cert must follow algorithm constraints +$JS a.jar signer | grep "chain is invalid" || exit 2 + +exit 0