undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
199
test/jdk/java/util/jar/Attributes/NullAndEmptyKeysAndValues.java
Normal file
199
test/jdk/java/util/jar/Attributes/NullAndEmptyKeysAndValues.java
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 2026, 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.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.jar.Attributes.Name;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8066619
|
||||
* @modules java.base/java.util.jar:+open
|
||||
* @run junit/othervm --enable-final-field-mutation=ALL-UNNAMED NullAndEmptyKeysAndValues
|
||||
* @summary Tests manifests with {@code null} and empty string {@code ""}
|
||||
* values as section name, header name, or value in both main and named
|
||||
* attributes sections.
|
||||
*/
|
||||
/*
|
||||
* Note to future maintainer:
|
||||
* In order to actually being able to test all the cases where key and values
|
||||
* are null normal manifest and attributes manipulation through their public
|
||||
* api is not sufficient but then there were these null checks there before
|
||||
* which may or may not have had their reason and this way it's ensured that
|
||||
* the behavior does not change with that respect.
|
||||
* Once module isolation is enforced some test cases will not any longer be
|
||||
* possible and those now tested situations will be guaranteed not to occur
|
||||
* any longer at all at which point the corresponding tests can be removed
|
||||
* safely without replacement unless of course another way is found inject the
|
||||
* tested null values.
|
||||
* Another trick to access package private class members could be to use
|
||||
* deserialization or adding a new class to the same package on the classpath.
|
||||
* Here is not important how the values are set to null because it shows that
|
||||
* the behavior remains unchanged.
|
||||
*/
|
||||
public class NullAndEmptyKeysAndValues {
|
||||
|
||||
static final String SOME_KEY = "some-key";
|
||||
static final String SOME_VALUE = "some value";
|
||||
static final String NULL_TEXT = "null";
|
||||
static final String EMPTY_STR = "";
|
||||
static final Name EMPTY_NAME = new Name("tmp") {{
|
||||
try {
|
||||
Field name = Name.class.getDeclaredField("name");
|
||||
name.setAccessible(true);
|
||||
name.set(this, EMPTY_STR);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}};
|
||||
|
||||
@Test
|
||||
public void testMainAttributesHeaderNameNull() throws Exception {
|
||||
Manifest mf = new Manifest();
|
||||
Field attr = mf.getClass().getDeclaredField("attr");
|
||||
attr.setAccessible(true);
|
||||
Attributes mainAtts = new Attributes() {{
|
||||
super.put(null, SOME_VALUE);
|
||||
}};
|
||||
attr.set(mf, mainAtts);
|
||||
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
||||
assertThrows(NullPointerException.class, () -> writeAndRead(mf));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMainAttributesHeaderNameEmpty() throws Exception {
|
||||
Manifest mf = new Manifest();
|
||||
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
||||
mf.getMainAttributes().put(EMPTY_NAME, SOME_VALUE);
|
||||
assertThrows(IOException.class, () -> writeAndRead(mf));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMainAttributesHeaderValueNull() throws Exception {
|
||||
Manifest mf = new Manifest();
|
||||
Field attr = mf.getClass().getDeclaredField("attr");
|
||||
attr.setAccessible(true);
|
||||
Attributes mainAtts = new Attributes() {{
|
||||
map.put(new Name(SOME_KEY), null);
|
||||
}};
|
||||
attr.set(mf, mainAtts);
|
||||
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
||||
mf = writeAndRead(mf);
|
||||
assertEquals(NULL_TEXT, mf.getMainAttributes().getValue(SOME_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMainAttributesHeaderValueEmpty() throws Exception {
|
||||
Manifest mf = new Manifest();
|
||||
Field attr = mf.getClass().getDeclaredField("attr");
|
||||
attr.setAccessible(true);
|
||||
Attributes mainAtts = new Attributes() {{
|
||||
map.put(new Name(SOME_KEY), EMPTY_STR);
|
||||
}};
|
||||
attr.set(mf, mainAtts);
|
||||
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
||||
mf = writeAndRead(mf);
|
||||
assertEquals(EMPTY_STR, mf.getMainAttributes().getValue(SOME_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSectionNameNull() throws IOException {
|
||||
Manifest mf = new Manifest();
|
||||
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
||||
mf.getEntries().put(null, new Attributes());
|
||||
mf = writeAndRead(mf);
|
||||
assertNotNull(mf.getEntries().get(NULL_TEXT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSectionNameEmpty() throws IOException {
|
||||
Manifest mf = new Manifest();
|
||||
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
||||
mf.getEntries().put(EMPTY_STR, new Attributes());
|
||||
mf = writeAndRead(mf);
|
||||
assertNotNull(mf.getEntries().get(EMPTY_STR));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamedSectionHeaderNameNull() throws IOException {
|
||||
Manifest mf = new Manifest();
|
||||
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
||||
mf.getEntries().put(SOME_KEY, new Attributes() {{
|
||||
map.put(null, SOME_VALUE);
|
||||
}});
|
||||
assertThrows(NullPointerException.class, () -> writeAndRead(mf));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamedSectionHeaderNameEmpty() throws IOException {
|
||||
Manifest mf = new Manifest();
|
||||
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
||||
mf.getEntries().put(SOME_KEY, new Attributes() {{
|
||||
map.put(EMPTY_NAME, SOME_VALUE);
|
||||
}});
|
||||
assertThrows(IOException.class, () -> writeAndRead(mf));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamedSectionHeaderValueNull() throws IOException {
|
||||
Manifest mf = new Manifest();
|
||||
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
||||
mf.getEntries().put(SOME_KEY, new Attributes() {{
|
||||
map.put(new Name(SOME_KEY), null);
|
||||
}});
|
||||
mf = writeAndRead(mf);
|
||||
assertEquals(NULL_TEXT, mf.getEntries().get(SOME_KEY).getValue(SOME_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamedSectionHeaderValueEmpty() throws IOException {
|
||||
Manifest mf = new Manifest();
|
||||
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
||||
mf.getEntries().put(SOME_KEY, new Attributes() {{
|
||||
map.put(new Name(SOME_KEY), EMPTY_STR);
|
||||
}});
|
||||
mf = writeAndRead(mf);
|
||||
assertEquals(EMPTY_STR, mf.getEntries().get(SOME_KEY).getValue(SOME_KEY));
|
||||
}
|
||||
|
||||
static Manifest writeAndRead(Manifest mf) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
mf.write(out);
|
||||
byte[] mfBytes = out.toByteArray();
|
||||
System.out.println("-".repeat(72));
|
||||
System.out.print(new String(mfBytes, UTF_8));
|
||||
System.out.println("-".repeat(72));
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(mfBytes);
|
||||
return new Manifest(in);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue