Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-10 Thread Lance Andersen
On Thu, 10 Feb 2022 20:37:50 GMT, Sean Mullan  wrote:

>> Agree on returning null to maintain current behavior. I would also lean 
>> towards amending the specification to specify what has been long-standing 
>> behavior.
>
> If we had to do it over again, I do think throwing IAE is more appropriate 
> because this case would probably be due to a bug in the application code. Now 
> code has to defensively check for a null return value. I don't know, maybe we 
> don't want to modify the specification at this point and leave this as 
> undefined behavior.

> Agree on returning null to maintain current behavior. I would also lean 
> towards amending the specification to specify what has been long-standing 
> behavior.

I just updated the PR to return null

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-10 Thread Sean Mullan
On Thu, 10 Feb 2022 20:35:19 GMT, Sean Mullan  wrote:

>> So a bit more on this.  If the ZipEntry passed to `ZipFile::getInputStream` 
>> does not represent an entry within the current Zip/Jar,  
>> `ZipFile::getInputStream` will return a null for the InputStream:
>> 
>> 
>> @Test
>> public static void ZipFileZipEntryNullGetInputStreamTest() throws 
>> Exception {
>> try (ZipFile zf = new ZipFile(VALID_ENTRY_NAME_JAR.toFile())) {
>> var ze = new ZipEntry("org/gotham/Batcave.class");
>> var is = zf.getInputStream(ze);
>> // As the ZipEntry cannot be found, the returned InpuStream is 
>> null
>> assertNull(is);
>> }
>> }
>> 
>> 
>>   JarFile::getInputStream will also return null when the jar is not signed 
>> or we are not verifying the jar:
>> 
>> 
>>  @Test
>> public static void JarFileZipEntryNullGetInputStreamTest() throws 
>> Exception {
>> try (JarFile jf = new JarFile(VALID_ENTRY_NAME_JAR.toFile())) {
>> var ze = new ZipEntry("org/gotham/Batcave.class");
>> var is = jf.getInputStream(ze);
>> // As the ZipEntry cannot be found, the returned InpuStream is 
>> null
>> assertNull(is);
>> }
>> 
>> try (JarFile jf = new 
>> JarFile(SIGNED_INVALID_ENTRY_NAME_JAR.toFile(), false)) {
>> var ze = new ZipEntry("org/gotham/Batcave.class");
>> var is = jf.getInputStream(ze);
>> // As the ZipEntry cannot be found, the returned InpuStream is 
>> null
>> assertNull(is);
>> }
>> }
>> 
>> 
>> 
>> This behavior dates back to at least JDK 1.3
>> 
>> So I think we should return null  instead of throwing an Exception when the 
>> resulting ZipEntry is null that is returned from the call 
>> to`JarFile::getJarEntry` (which calls `ZipFile::getEntry`) for consistency 
>> with ZipFile and when the Jar is not signed or not verified.
>> 
>> I also noticed that `ZipFile::getInputStream` and `JarFile::getInputStream` 
>> do not mention that a null will be returned if the specified ZipEntry is not 
>> found within the Jar/Zip.  I guess I could open a CSR as part of this fix to 
>> clarify this 20+ year behavior.
>
> Agree on returning null to maintain current behavior. I would also lean 
> towards amending the specification to specify what has been long-standing 
> behavior.

If we had to do it over again, I do think throwing IAE is more appropriate 
because this case would probably be due to a bug in the application code. Now 
code has to defensively check for a null return value. I don't know, maybe we 
don't want to modify the specification at this point and leave this as 
undefined behavior.

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-10 Thread Sean Mullan
On Wed, 9 Feb 2022 21:16:08 GMT, Lance Andersen  wrote:

>>> Nit, add space after "if"
>> 
>> will fix
>
> So a bit more on this.  If the ZipEntry passed to `ZipFile::getInputStream` 
> does not represent an entry within the current Zip/Jar,  
> `ZipFile::getInputStream` will return a null for the InputStream:
> 
> 
> @Test
> public static void ZipFileZipEntryNullGetInputStreamTest() throws 
> Exception {
> try (ZipFile zf = new ZipFile(VALID_ENTRY_NAME_JAR.toFile())) {
> var ze = new ZipEntry("org/gotham/Batcave.class");
> var is = zf.getInputStream(ze);
> // As the ZipEntry cannot be found, the returned InpuStream is 
> null
> assertNull(is);
> }
> }
> 
> 
>   JarFile::getInputStream will also return null when the jar is not signed or 
> we are not verifying the jar:
> 
> 
>  @Test
> public static void JarFileZipEntryNullGetInputStreamTest() throws 
> Exception {
> try (JarFile jf = new JarFile(VALID_ENTRY_NAME_JAR.toFile())) {
> var ze = new ZipEntry("org/gotham/Batcave.class");
> var is = jf.getInputStream(ze);
> // As the ZipEntry cannot be found, the returned InpuStream is 
> null
> assertNull(is);
> }
> 
> try (JarFile jf = new JarFile(SIGNED_INVALID_ENTRY_NAME_JAR.toFile(), 
> false)) {
> var ze = new ZipEntry("org/gotham/Batcave.class");
> var is = jf.getInputStream(ze);
> // As the ZipEntry cannot be found, the returned InpuStream is 
> null
> assertNull(is);
> }
> }
> 
> 
> 
> This behavior dates back to at least JDK 1.3
> 
> So I think we should return null  instead of throwing an Exception when the 
> resulting ZipEntry is null that is returned from the call 
> to`JarFile::getJarEntry` (which calls `ZipFile::getEntry`) for consistency 
> with ZipFile and when the Jar is not signed or not verified.
> 
> I also noticed that `ZipFile::getInputStream` and `JarFile::getInputStream` 
> do not mention that a null will be returned if the specified ZipEntry is not 
> found within the Jar/Zip.  I guess I could open a CSR as part of this fix to 
> clarify this 20+ year behavior.

Agree on returning null to maintain current behavior. I would also lean towards 
amending the specification to specify what has been long-standing behavior.

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-09 Thread Lance Andersen
On Tue, 8 Feb 2022 18:06:04 GMT, Lance Andersen  wrote:

>>> ze can't be null here.
>> 
>> Actually it can be:  Consider the following:
>> 
>> 
>> try (JarFile jf = new JarFile(SIGNED_VALID_ENTRY_NAME_JAR.toFile(), 
>> true)) {
>> var ze = new ZipEntry("org/gotham/Batcave.class");
>> var ex= expectThrows(ZipException.class,
>> () -> jf.getInputStream(ze) );
>> // Validate that we receive the expected message from
>> // JarFile::verifiableEntry when ZipEntry::getName returns null
>> assertTrue( ex != null && ex.getMessage().equals("Error: 
>> ZipEntry should not be null!"));
>> }
>> 
>> 
>> The above code does generate the error.
>
>> Nit, add space after "if"
> 
> will fix

So a bit more on this.  If the ZipEntry passed to `ZipFile::getInputStream` 
does not represent an entry within the current Zip/Jar,  
`ZipFile::getInputStream` will return a null for the InputStream:


@Test
public static void ZipFileZipEntryNullGetInputStreamTest() throws Exception 
{
try (ZipFile zf = new ZipFile(VALID_ENTRY_NAME_JAR.toFile())) {
var ze = new ZipEntry("org/gotham/Batcave.class");
var is = zf.getInputStream(ze);
// As the ZipEntry cannot be found, the returned InpuStream is null
assertNull(is);
}
}


  JarFile::getInputStream will also return null when the jar is not signed or 
we are not verifying the jar:


 @Test
public static void JarFileZipEntryNullGetInputStreamTest() throws Exception 
{
try (JarFile jf = new JarFile(VALID_ENTRY_NAME_JAR.toFile())) {
var ze = new ZipEntry("org/gotham/Batcave.class");
var is = jf.getInputStream(ze);
// As the ZipEntry cannot be found, the returned InpuStream is null
assertNull(is);
}

try (JarFile jf = new JarFile(SIGNED_INVALID_ENTRY_NAME_JAR.toFile(), 
false)) {
var ze = new ZipEntry("org/gotham/Batcave.class");
var is = jf.getInputStream(ze);
// As the ZipEntry cannot be found, the returned InpuStream is null
assertNull(is);
}
}



This behavior dates back to at least JDK 1.3

So I think we should return null  instead of throwing an Exception when the 
resulting ZipEntry is null that is returned from the call 
to`JarFile::getJarEntry` (which calls `ZipFile::getEntry`) for consistency with 
ZipFile and when the Jar is not signed or not verified.

I also noticed that `ZipFile::getInputStream` and `JarFile::getInputStream` do 
not mention that a null will be returned if the specified ZipEntry is not found 
within the Jar/Zip.  I guess I could open a CSR as part of this fix to clarify 
this 20+ year behavior.

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-08 Thread Lance Andersen
On Tue, 8 Feb 2022 18:56:02 GMT, Alan Bateman  wrote:

>>> I'm almost tempted to have getInputStream(ZipEntry) be re-specified to 
>>> throw IAE if the zip entry name is null.
>> 
>> I personally think it is best to continue throw the NPE as that provides 
>> symmetry with ZipFile::getInputStream,  aligns with the current javadoc 
>> where a null parameter will throw an NPE unless specified elsewhere,  there 
>> are existing tests which check for an NPE if JarFile::getInpuStream(null) is 
>> called.
>
>> I personally think it is best to continue throw the NPE as that provides 
>> symmetry with ZipFile::getInputStream, aligns with the current javadoc where 
>> a null parameter will throw an NPE unless specified elsewhere, there are 
>> existing tests which check for an NPE if JarFile::getInpuStream(null) is 
>> called.
> 
> I think the scenario that we are discussing is where the parameter is not 
> null. It's the case where getInputStream(ZipEntry) is called with a ZipEntry 
> that reports its name as null. I don't think it is covered by existing 
> javadoc.

Ah, OK, sorry I was focused on the NPE and uber focused on the `ZipEntry` 
passed to `getInputStream`.

If you *prefer* an IAE, I can change that when `ZipEntry::getName` returns 
null.  I do think we are technically covered via `ZipException` which is 
defined : ` if a zip file format error has occurred` and unless something has 
gone amiss with the Zip/Jar LOC/CEN, you should expect a non-null value.

Please let me know your preference as if we go the IAE route, I will need to 
create a CSR which I was hoping to avoid

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-08 Thread Alan Bateman
On Tue, 8 Feb 2022 18:11:38 GMT, Lance Andersen  wrote:

> I personally think it is best to continue throw the NPE as that provides 
> symmetry with ZipFile::getInputStream, aligns with the current javadoc where 
> a null parameter will throw an NPE unless specified elsewhere, there are 
> existing tests which check for an NPE if JarFile::getInpuStream(null) is 
> called.

I think the scenario that we are discussing is where the parameter is not null. 
It's the case where getInputStream(ZipEntry) is called with a ZipEntry that 
reports its name as null. I don't think it is covered by existing javadoc.

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-08 Thread Lance Andersen
On Tue, 8 Feb 2022 18:05:25 GMT, Lance Andersen  wrote:

>> ze can't be null here.
>
>> ze can't be null here.
> 
> Actually it can be:  Consider the following:
> 
> 
> try (JarFile jf = new JarFile(SIGNED_VALID_ENTRY_NAME_JAR.toFile(), 
> true)) {
> var ze = new ZipEntry("org/gotham/Batcave.class");
> var ex= expectThrows(ZipException.class,
> () -> jf.getInputStream(ze) );
> // Validate that we receive the expected message from
> // JarFile::verifiableEntry when ZipEntry::getName returns null
> assertTrue( ex != null && ex.getMessage().equals("Error: ZipEntry 
> should not be null!"));
> }
> 
> 
> The above code does generate the error.

> Nit, add space after "if"

will fix

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-08 Thread Lance Andersen
On Tue, 8 Feb 2022 15:55:50 GMT, Alan Bateman  wrote:

> ze can't be null here.

Actually it can be:  Consider the following:


try (JarFile jf = new JarFile(SIGNED_VALID_ENTRY_NAME_JAR.toFile(), 
true)) {
var ze = new ZipEntry("org/gotham/Batcave.class");
var ex= expectThrows(ZipException.class,
() -> jf.getInputStream(ze) );
// Validate that we receive the expected message from
// JarFile::verifiableEntry when ZipEntry::getName returns null
assertTrue( ex != null && ex.getMessage().equals("Error: ZipEntry 
should not be null!"));
}


The above code does generate the error.

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-08 Thread Lance Andersen
On Tue, 8 Feb 2022 15:31:51 GMT, Sean Mullan  wrote:

>> Lance Andersen has updated the pull request incrementally with one 
>> additional commit since the last revision:
>> 
>>   Reduce Exception checking to JarFile::verifiableEntry
>
> src/java.base/share/classes/java/util/jar/JarFile.java line 874:
> 
>> 872: ze = getJarEntry(ze.getName());
>> 873: } else {
>> 874: throw new ZipException("Error: ZipEntry::getName returned 
>> null!");
> 
> I'd probably leave out the "Error:" and the "!".

OK, I can do that if you prefer.

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-08 Thread Lance Andersen
On Tue, 8 Feb 2022 18:06:52 GMT, Lance Andersen  wrote:

>> Ah, yes - good catch!
>
> Will do.

> I'm almost tempted to have getInputStream(ZipEntry) be re-specified to throw 
> IAE if the zip entry name is null.

I personally think it is best to continue throw the NPE as that provides 
symmetry with ZipFile::getInputStream,  aligns with the current javadoc where a 
null parameter will throw an NPE unless specified elsewhere,  there are 
existing tests which check for an NPE if JarFile::getInpuStream(null) is called.

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-08 Thread Lance Andersen
On Tue, 8 Feb 2022 16:15:20 GMT, Sean Mullan  wrote:

>> if ZipEntry is extended and getName() overridden then you can't trust the 
>> name. So I think you'll have extract the name rather than calling 
>> ZipEntry::getName twice. I'm almost tempted to have getInputStream(ZipEntry) 
>> be re-specified to throw IAE if the zip entry name is null.
>
> Ah, yes - good catch!

Will do.

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-08 Thread Sean Mullan
On Tue, 8 Feb 2022 15:57:00 GMT, Alan Bateman  wrote:

>> src/java.base/share/classes/java/util/jar/JarFile.java line 871:
>> 
>>> 869: }
>>> 870: // ZipEntry::getName should not return null
>>> 871: if(ze.getName() != null) {
>> 
>> Nit, add space after "if"
>
> if ZipEntry is extended and getName() overridden then you can't trust the 
> name. So I think you'll have extract the name rather than calling 
> ZipEntry::getName twice. I'm almost tempted to have getInputStream(ZipEntry) 
> be re-specified to throw IAE if the zip entry name is null.

Ah, yes - good catch!

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-08 Thread Alan Bateman
On Tue, 8 Feb 2022 15:27:46 GMT, Sean Mullan  wrote:

>> Lance Andersen has updated the pull request incrementally with one 
>> additional commit since the last revision:
>> 
>>   Reduce Exception checking to JarFile::verifiableEntry
>
> src/java.base/share/classes/java/util/jar/JarFile.java line 871:
> 
>> 869: }
>> 870: // ZipEntry::getName should not return null
>> 871: if(ze.getName() != null) {
> 
> Nit, add space after "if"

if ZipEntry is extended and getName() overridden then you can't trust the name. 
So I think you'll have extract the name rather than calling ZipEntry::getName 
twice. I'm almost tempted to have getInputStream(ZipEntry) be re-specified to 
throw IAE if the zip entry is null.

> src/java.base/share/classes/java/util/jar/JarFile.java line 877:
> 
>> 875: }
>> 876: // ZipEntry returned from JarFile::getJarEntry should not be 
>> null
>> 877: if(ze == null) {
> 
> Nit, add space after "if"

ze can't be null here.

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-08 Thread Sean Mullan
On Mon, 7 Feb 2022 23:02:54 GMT, Lance Andersen  wrote:

>> Hi all,
>> 
>> Please review the attached patch to address
>> 
>> - That JarFile::getInputStream did not check for a null ZipEntry passed as a 
>> parameter
>> - Have Zip/JarFile::getInputStream throw a ZipException in the event that an 
>> unexpected exception occurs
>> 
>> Mach5 tiers1-3 runs are clean as are the TCK java.util.zip and java.util.jar 
>> test runs
>> 
>> Best
>> Lance
>
> Lance Andersen has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Reduce Exception checking to JarFile::verifiableEntry

Marked as reviewed by mullan (Reviewer).

src/java.base/share/classes/java/util/jar/JarFile.java line 871:

> 869: }
> 870: // ZipEntry::getName should not return null
> 871: if(ze.getName() != null) {

Nit, add space after "if"

src/java.base/share/classes/java/util/jar/JarFile.java line 874:

> 872: ze = getJarEntry(ze.getName());
> 873: } else {
> 874: throw new ZipException("Error: ZipEntry::getName returned 
> null!");

I'd probably leave out the "Error:" and the "!".

src/java.base/share/classes/java/util/jar/JarFile.java line 877:

> 875: }
> 876: // ZipEntry returned from JarFile::getJarEntry should not be null
> 877: if(ze == null) {

Nit, add space after "if"

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-07 Thread Lance Andersen
On Mon, 7 Feb 2022 20:16:43 GMT, Lance Andersen  wrote:

>> If you are pretty sure the only other case are as above, I wonder if a 
>> simpler fix would be to change `verifiableEntry()` to check for these null 
>> cases and throw a `ZipException` which will get directly propagated by 
>> `getInputStream()`?
>
> I can certainly throw a ZipException from `verifiableEntry`. I am a bit 
> reluctant to not catch any other `Exception` and then throw a `ZipException` 
> from `getInputStream()` as it is certainly possible of encountering some 
> other issue due to some stray value in the CEN.
> 
> So I will update `verifiableEntry` to validate `ZipEntry` and` 
> ZipEntry::getName()` potential issues

Per an offline-discussion with Sean, I narrowed the Exception checking to 
JarFile::verifiableEntry.

-

PR: https://git.openjdk.java.net/jdk/pull/7348


Re: RFR: 8280409: JarFile::verifiableEntry can fail with NPE accessing ze.getName() [v2]

2022-02-07 Thread Lance Andersen
> Hi all,
> 
> Please review the attached patch to address
> 
> - That JarFile::getInputStream did not check for a null ZipEntry passed as a 
> parameter
> - Have Zip/JarFile::getInputStream throw a ZipException in the event that an 
> unexpected exception occurs
> 
> Mach5 tiers1-3 runs are clean as are the TCK java.util.zip and java.util.jar 
> test runs
> 
> Best
> Lance

Lance Andersen has updated the pull request incrementally with one additional 
commit since the last revision:

  Reduce Exception checking to JarFile::verifiableEntry

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/7348/files
  - new: https://git.openjdk.java.net/jdk/pull/7348/files/b50ebf05..6c75384a

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=7348=01
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=7348=00-01

  Stats: 162 lines in 3 files changed: 90 ins; 21 del; 51 mod
  Patch: https://git.openjdk.java.net/jdk/pull/7348.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/7348/head:pull/7348

PR: https://git.openjdk.java.net/jdk/pull/7348