mirror of
https://github.com/openjdk/jdk15u.git
synced 2025-12-10 17:33:04 -06:00
Merge
This commit is contained in:
commit
bae72014c6
@ -596,7 +596,6 @@ ciKlass* ciEnv::get_klass_by_index(const constantPoolHandle& cpool,
|
||||
ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool,
|
||||
int pool_index, int cache_index,
|
||||
ciInstanceKlass* accessor) {
|
||||
bool ignore_will_link;
|
||||
EXCEPTION_CONTEXT;
|
||||
int index = pool_index;
|
||||
if (cache_index >= 0) {
|
||||
@ -668,8 +667,8 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool,
|
||||
return ciConstant(T_OBJECT, constant);
|
||||
}
|
||||
} else if (tag.is_klass() || tag.is_unresolved_klass()) {
|
||||
// 4881222: allow ldc to take a class type
|
||||
ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore_will_link, accessor);
|
||||
bool will_link;
|
||||
ciKlass* klass = get_klass_by_index_impl(cpool, index, will_link, accessor);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
record_out_of_memory_failure();
|
||||
@ -677,7 +676,8 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool,
|
||||
}
|
||||
assert (klass->is_instance_klass() || klass->is_array_klass(),
|
||||
"must be an instance or array klass ");
|
||||
return ciConstant(T_OBJECT, klass->java_mirror());
|
||||
ciInstance* mirror = (will_link ? klass->java_mirror() : get_unloaded_klass_mirror(klass));
|
||||
return ciConstant(T_OBJECT, mirror);
|
||||
} else if (tag.is_method_type()) {
|
||||
// must execute Java code to link this CP entry into cache[i].f1
|
||||
ciSymbol* signature = get_symbol(cpool->method_type_signature_at(index));
|
||||
@ -685,6 +685,7 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool,
|
||||
return ciConstant(T_OBJECT, ciobj);
|
||||
} else if (tag.is_method_handle()) {
|
||||
// must execute Java code to link this CP entry into cache[i].f1
|
||||
bool ignore_will_link;
|
||||
int ref_kind = cpool->method_handle_ref_kind_at(index);
|
||||
int callee_index = cpool->method_handle_klass_index_at(index);
|
||||
ciKlass* callee = get_klass_by_index_impl(cpool, callee_index, ignore_will_link, accessor);
|
||||
|
||||
@ -1716,9 +1716,32 @@ void LinkResolver::resolve_handle_call(CallInfo& result,
|
||||
assert(resolved_klass == SystemDictionary::MethodHandle_klass() ||
|
||||
resolved_klass == SystemDictionary::VarHandle_klass(), "");
|
||||
assert(MethodHandles::is_signature_polymorphic_name(link_info.name()), "");
|
||||
Handle resolved_appendix;
|
||||
Method* resolved_method = lookup_polymorphic_method(link_info, &resolved_appendix, CHECK);
|
||||
result.set_handle(resolved_klass, methodHandle(THREAD, resolved_method), resolved_appendix, CHECK);
|
||||
Handle resolved_appendix;
|
||||
Method* m = lookup_polymorphic_method(link_info, &resolved_appendix, CHECK);
|
||||
methodHandle resolved_method(THREAD, m);
|
||||
|
||||
if (link_info.check_access()) {
|
||||
Symbol* name = link_info.name();
|
||||
vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name);
|
||||
if (MethodHandles::is_signature_polymorphic_intrinsic(iid)) {
|
||||
// Check if method can be accessed by the referring class.
|
||||
// MH.linkTo* invocations are not rewritten to invokehandle.
|
||||
assert(iid == vmIntrinsicID::_invokeBasic, "%s", vmIntrinsics::name_at(iid));
|
||||
|
||||
Klass* current_klass = link_info.current_klass();
|
||||
assert(current_klass != NULL , "current_klass should not be null");
|
||||
check_method_accessability(current_klass,
|
||||
resolved_klass,
|
||||
resolved_method->method_holder(),
|
||||
resolved_method,
|
||||
CHECK);
|
||||
} else {
|
||||
// Java code is free to arbitrarily link signature-polymorphic invokers.
|
||||
assert(iid == vmIntrinsics::_invokeGeneric, "not an invoker: %s", vmIntrinsics::name_at(iid));
|
||||
assert(MethodHandles::is_signature_polymorphic_public_name(resolved_klass, name), "not public");
|
||||
}
|
||||
}
|
||||
result.set_handle(resolved_klass, resolved_method, resolved_appendix, CHECK);
|
||||
}
|
||||
|
||||
void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHandle& pool, int indy_index, TRAPS) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2022, 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
|
||||
@ -137,7 +137,7 @@ class HostPortrange {
|
||||
}
|
||||
this.ipv4 = this.literal = ipv4;
|
||||
if (ipv4) {
|
||||
byte[] ip = IPAddressUtil.textToNumericFormatV4(hoststr);
|
||||
byte[] ip = IPAddressUtil.validateNumericFormatV4(hoststr);
|
||||
if (ip == null) {
|
||||
throw new IllegalArgumentException("illegal IPv4 address");
|
||||
}
|
||||
|
||||
@ -1103,7 +1103,11 @@ public class InetAddress implements java.io.Serializable {
|
||||
private byte [] createAddressByteArray(String addrStr) {
|
||||
byte[] addrArray;
|
||||
// check if IPV4 address - most likely
|
||||
addrArray = IPAddressUtil.textToNumericFormatV4(addrStr);
|
||||
try {
|
||||
addrArray = IPAddressUtil.validateNumericFormatV4(addrStr);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
return null;
|
||||
}
|
||||
if (addrArray == null) {
|
||||
addrArray = IPAddressUtil.textToNumericFormatV6(addrStr);
|
||||
}
|
||||
@ -1322,13 +1326,19 @@ public class InetAddress implements java.io.Serializable {
|
||||
}
|
||||
|
||||
// if host is an IP address, we won't do further lookup
|
||||
if (Character.digit(host.charAt(0), 16) != -1
|
||||
if (IPAddressUtil.digit(host.charAt(0), 16) != -1
|
||||
|| (host.charAt(0) == ':')) {
|
||||
byte[] addr = null;
|
||||
byte[] addr;
|
||||
int numericZone = -1;
|
||||
String ifname = null;
|
||||
// see if it is IPv4 address
|
||||
addr = IPAddressUtil.textToNumericFormatV4(host);
|
||||
try {
|
||||
addr = IPAddressUtil.validateNumericFormatV4(host);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
var uhe = new UnknownHostException(host);
|
||||
uhe.initCause(iae);
|
||||
throw uhe;
|
||||
}
|
||||
if (addr == null) {
|
||||
// This is supposed to be an IPv6 literal
|
||||
// Check if a numeric or string zone id is present
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2022, 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
|
||||
@ -469,7 +469,7 @@ public final class SocketPermission extends Permission
|
||||
if (!host.isEmpty()) {
|
||||
// see if we are being initialized with an IP address.
|
||||
char ch = host.charAt(0);
|
||||
if (ch == ':' || Character.digit(ch, 16) != -1) {
|
||||
if (ch == ':' || IPAddressUtil.digit(ch, 16) != -1) {
|
||||
byte ip[] = IPAddressUtil.textToNumericFormatV4(host);
|
||||
if (ip == null) {
|
||||
ip = IPAddressUtil.textToNumericFormatV6(host);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2022, 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,6 +30,7 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import jdk.internal.org.xml.sax.InputSource;
|
||||
@ -42,7 +43,11 @@ public abstract class Parser {
|
||||
|
||||
public static final String FAULT = "";
|
||||
protected static final int BUFFSIZE_READER = 512;
|
||||
// Initial buffer (mBuff) size
|
||||
protected static final int BUFFSIZE_PARSER = 128;
|
||||
// Max buffer size
|
||||
private static final int MAX_ARRAY_SIZE = 1024 << 16;
|
||||
|
||||
/**
|
||||
* The end of stream character.
|
||||
*/
|
||||
@ -525,6 +530,10 @@ public abstract class Parser {
|
||||
mPh = PH_DTD; // DTD
|
||||
for (short st = 0; st >= 0;) {
|
||||
ch = getch();
|
||||
// report error if EOS is reached while parsing the DTD
|
||||
if (ch == EOS) {
|
||||
panic(FAULT);
|
||||
}
|
||||
switch (st) {
|
||||
case 0: // read the document type name
|
||||
if (chtyp(ch) != ' ') {
|
||||
@ -1664,6 +1673,10 @@ public abstract class Parser {
|
||||
mBuffIdx = -1;
|
||||
for (short st = 0; st >= 0;) {
|
||||
ch = getch();
|
||||
// report error if EOS is reached while parsing the DTD
|
||||
if (ch == EOS) {
|
||||
panic(FAULT);
|
||||
}
|
||||
switch (st) {
|
||||
case 0: // the first '[' of the CDATA open
|
||||
if (ch == '[') {
|
||||
@ -1871,7 +1884,7 @@ public abstract class Parser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resoves an entity.
|
||||
* Resolves an entity.
|
||||
*
|
||||
* This method resolves built-in and character entity references. It is also
|
||||
* reports external entities to the application.
|
||||
@ -2529,7 +2542,7 @@ public abstract class Parser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a single or double quotted string in to the buffer.
|
||||
* Reads a single or double quoted string into the buffer.
|
||||
*
|
||||
* This method resolves entities inside a string unless the parser parses
|
||||
* DTD.
|
||||
@ -2664,7 +2677,7 @@ public abstract class Parser {
|
||||
* @param ch The character to append to the buffer.
|
||||
* @param mode The normalization mode.
|
||||
*/
|
||||
private void bappend(char ch, char mode) {
|
||||
private void bappend(char ch, char mode) throws Exception {
|
||||
// This implements attribute value normalization as
|
||||
// described in the XML specification [#3.3.3].
|
||||
switch (mode) {
|
||||
@ -2714,16 +2727,9 @@ public abstract class Parser {
|
||||
*
|
||||
* @param ch The character to append to the buffer.
|
||||
*/
|
||||
private void bappend(char ch) {
|
||||
try {
|
||||
mBuff[++mBuffIdx] = ch;
|
||||
} catch (Exception exp) {
|
||||
// Double the buffer size
|
||||
char buff[] = new char[mBuff.length << 1];
|
||||
System.arraycopy(mBuff, 0, buff, 0, mBuff.length);
|
||||
mBuff = buff;
|
||||
mBuff[mBuffIdx] = ch;
|
||||
}
|
||||
private void bappend(char ch) throws Exception {
|
||||
ensureCapacity(++mBuffIdx);
|
||||
mBuff[mBuffIdx] = ch;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2733,14 +2739,9 @@ public abstract class Parser {
|
||||
* @param cidx The character buffer (mChars) start index.
|
||||
* @param bidx The parser buffer (mBuff) start index.
|
||||
*/
|
||||
private void bcopy(int cidx, int bidx) {
|
||||
private void bcopy(int cidx, int bidx) throws Exception {
|
||||
int length = mChIdx - cidx;
|
||||
if ((bidx + length + 1) >= mBuff.length) {
|
||||
// Expand the buffer
|
||||
char buff[] = new char[mBuff.length + length];
|
||||
System.arraycopy(mBuff, 0, buff, 0, mBuff.length);
|
||||
mBuff = buff;
|
||||
}
|
||||
ensureCapacity(bidx + length + 1);
|
||||
System.arraycopy(mChars, cidx, mBuff, bidx, length);
|
||||
mBuffIdx += length;
|
||||
}
|
||||
@ -3327,7 +3328,7 @@ public abstract class Parser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrives the next character in the document.
|
||||
* Retrieves the next character in the document.
|
||||
*
|
||||
* @return The next character in the document.
|
||||
*/
|
||||
@ -3433,4 +3434,23 @@ public abstract class Parser {
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
private void ensureCapacity(int minCapacity) throws Exception {
|
||||
if (mBuff == null) {
|
||||
int newCapacity = minCapacity > BUFFSIZE_PARSER ?
|
||||
minCapacity + BUFFSIZE_PARSER : BUFFSIZE_PARSER;
|
||||
mBuff = new char[newCapacity];
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBuff.length <= minCapacity) {
|
||||
int size = mBuff.length << 1;
|
||||
int newCapacity = size > minCapacity ? size : minCapacity + BUFFSIZE_PARSER;
|
||||
if (newCapacity < 0 || newCapacity > MAX_ARRAY_SIZE) {
|
||||
panic(FAULT);
|
||||
}
|
||||
|
||||
mBuff = Arrays.copyOf(mBuff, newCapacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 2022, 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,7 +25,8 @@
|
||||
|
||||
package sun.net.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
@ -33,6 +34,7 @@ import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.URL;
|
||||
import java.nio.CharBuffer;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
@ -101,7 +103,7 @@ public class IPAddressUtil {
|
||||
tmpValue = 0;
|
||||
newOctet = true;
|
||||
} else {
|
||||
int digit = Character.digit(c, 10);
|
||||
int digit = digit(c, 10);
|
||||
if (digit < 0) {
|
||||
return null;
|
||||
}
|
||||
@ -126,6 +128,29 @@ public class IPAddressUtil {
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if input string is a valid IPv4 address literal.
|
||||
* If the "jdk.net.allowAmbiguousIPAddressLiterals" system property is set
|
||||
* to {@code false}, or is not set then validation of the address string is performed as follows:
|
||||
* If string can't be parsed by following IETF IPv4 address string literals
|
||||
* formatting style rules (default one), but can be parsed by following BSD formatting
|
||||
* style rules, the IPv4 address string content is treated as ambiguous and
|
||||
* {@code IllegalArgumentException} is thrown.
|
||||
*
|
||||
* @param src input string
|
||||
* @return bytes array if string is a valid IPv4 address string
|
||||
* @throws IllegalArgumentException if "jdk.net.allowAmbiguousIPAddressLiterals" SP is set to
|
||||
* "false" and IPv4 address string {@code "src"} is ambiguous
|
||||
*/
|
||||
public static byte[] validateNumericFormatV4(String src) {
|
||||
byte[] parsedBytes = textToNumericFormatV4(src);
|
||||
if (!ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP_VALUE
|
||||
&& parsedBytes == null && isBsdParsableV4(src)) {
|
||||
throw new IllegalArgumentException("Invalid IP address literal: " + src);
|
||||
}
|
||||
return parsedBytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert IPv6 presentation level address to network order binary form.
|
||||
* credit:
|
||||
@ -171,7 +196,7 @@ public class IPAddressUtil {
|
||||
val = 0;
|
||||
while (i < srcb_length) {
|
||||
ch = srcb[i++];
|
||||
int chval = Character.digit(ch, 16);
|
||||
int chval = digit(ch, 16);
|
||||
if (chval != -1) {
|
||||
val <<= 4;
|
||||
val |= chval;
|
||||
@ -551,4 +576,245 @@ public class IPAddressUtil {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the numeric value of the character {@code ch} in the
|
||||
* specified radix.
|
||||
*
|
||||
* @param ch the character to be converted.
|
||||
* @param radix the radix.
|
||||
* @return the numeric value represented by the character in the
|
||||
* specified radix.
|
||||
*/
|
||||
public static int digit(char ch, int radix) {
|
||||
if (ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP_VALUE) {
|
||||
return Character.digit(ch, radix);
|
||||
} else {
|
||||
return parseAsciiDigit(ch, radix);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to parse String as IPv4 address literal by following
|
||||
* BSD-style formatting rules.
|
||||
*
|
||||
* @param input input string
|
||||
* @return {@code true} if input string is parsable as IPv4 address literal,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public static boolean isBsdParsableV4(String input) {
|
||||
char firstSymbol = input.charAt(0);
|
||||
// Check if first digit is not a decimal digit
|
||||
if (parseAsciiDigit(firstSymbol, DECIMAL) == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Last character is dot OR is not a supported digit: [0-9,A-F,a-f]
|
||||
char lastSymbol = input.charAt(input.length() - 1);
|
||||
if (lastSymbol == '.' || parseAsciiHexDigit(lastSymbol) == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse IP address fields
|
||||
CharBuffer charBuffer = CharBuffer.wrap(input);
|
||||
int fieldNumber = 0;
|
||||
while (charBuffer.hasRemaining()) {
|
||||
long fieldValue = -1L;
|
||||
// Try to parse fields in all supported radixes
|
||||
for (int radix : SUPPORTED_RADIXES) {
|
||||
fieldValue = parseV4FieldBsd(radix, charBuffer, fieldNumber);
|
||||
if (fieldValue >= 0) {
|
||||
fieldNumber++;
|
||||
break;
|
||||
} else if (fieldValue == TERMINAL_PARSE_ERROR) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// If field can't be parsed as one of supported radixes stop
|
||||
// parsing
|
||||
if (fieldValue < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method tries to parse IP address field that starts from {@linkplain CharBuffer#position()
|
||||
* current position} of the provided character buffer.
|
||||
* <p>
|
||||
* This method supports three {@code "radix"} values to decode field values in
|
||||
* {@code "HEXADECIMAL (radix=16)"}, {@code "DECIMAL (radix=10)"} and
|
||||
* {@code "OCTAL (radix=8)"} radixes.
|
||||
* <p>
|
||||
* If {@code -1} value is returned the char buffer position is reset to the value
|
||||
* it was before it was called.
|
||||
* <p>
|
||||
* Method returns {@code -2} if formatting illegal for all supported {@code radix}
|
||||
* values is observed, and there is no point in checking other radix values.
|
||||
* That includes the following cases:<ul>
|
||||
* <li>Two subsequent dots are observer
|
||||
* <li>Number of dots more than 3
|
||||
* <li>Field value exceeds max allowed
|
||||
* <li>Character is not a valid digit for the requested {@code radix} value, given
|
||||
* that a field has the radix specific prefix
|
||||
* </ul>
|
||||
*
|
||||
* @param radix digits encoding radix to use for parsing. Valid values: 8, 10, 16.
|
||||
* @param buffer {@code CharBuffer} with position set to the field's fist character
|
||||
* @param fieldNumber parsed field number
|
||||
* @return {@code CANT_PARSE_IN_RADIX} if field can not be parsed in requested {@code radix}.
|
||||
* {@code TERMINAL_PARSE_ERROR} if field can't be parsed and the whole parse process should be terminated.
|
||||
* Parsed field value otherwise.
|
||||
*/
|
||||
private static long parseV4FieldBsd(int radix, CharBuffer buffer, int fieldNumber) {
|
||||
int initialPos = buffer.position();
|
||||
long val = 0;
|
||||
int digitsCount = 0;
|
||||
if (!checkPrefix(buffer, radix)) {
|
||||
val = CANT_PARSE_IN_RADIX;
|
||||
}
|
||||
boolean dotSeen = false;
|
||||
while (buffer.hasRemaining() && val != CANT_PARSE_IN_RADIX && !dotSeen) {
|
||||
char c = buffer.get();
|
||||
if (c == '.') {
|
||||
dotSeen = true;
|
||||
// Fail if 4 dots in IP address string.
|
||||
// fieldNumber counter starts from 0, therefore 3
|
||||
if (fieldNumber == 3) {
|
||||
// Terminal state, can stop parsing: too many fields
|
||||
return TERMINAL_PARSE_ERROR;
|
||||
}
|
||||
// Check for literals with two dots, like '1.2..3', '1.2.3..'
|
||||
if (digitsCount == 0) {
|
||||
// Terminal state, can stop parsing: dot with no digits
|
||||
return TERMINAL_PARSE_ERROR;
|
||||
}
|
||||
if (val > 255) {
|
||||
// Terminal state, can stop parsing: too big value for an octet
|
||||
return TERMINAL_PARSE_ERROR;
|
||||
}
|
||||
} else {
|
||||
int dv = parseAsciiDigit(c, radix);
|
||||
if (dv >= 0) {
|
||||
digitsCount++;
|
||||
val *= radix;
|
||||
val += dv;
|
||||
} else {
|
||||
// Spotted digit can't be parsed in the requested 'radix'.
|
||||
// The order in which radixes are checked - hex, octal, decimal:
|
||||
// - if symbol is not a valid digit in hex radix - terminal
|
||||
// - if symbol is not a valid digit in octal radix, and given
|
||||
// that octal prefix was observed before - terminal
|
||||
// - if symbol is not a valid digit in decimal radix - terminal
|
||||
return TERMINAL_PARSE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (val == CANT_PARSE_IN_RADIX) {
|
||||
buffer.position(initialPos);
|
||||
} else if (!dotSeen) {
|
||||
// It is the last field - check its value
|
||||
// This check will ensure that address strings with less
|
||||
// than 4 fields, i.e. A, A.B and A.B.C address types
|
||||
// contain value less then the allowed maximum for the last field.
|
||||
long maxValue = (1L << ((4 - fieldNumber) * 8)) - 1;
|
||||
if (val > maxValue) {
|
||||
// Terminal state, can stop parsing: last field value exceeds its
|
||||
// allowed value
|
||||
return TERMINAL_PARSE_ERROR;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
// This method moves the position of the supplied CharBuffer by analysing the digit prefix
|
||||
// symbols if any.
|
||||
// The caller should reset the position when method returns false.
|
||||
private static boolean checkPrefix(CharBuffer buffer, int radix) {
|
||||
return switch (radix) {
|
||||
case OCTAL -> isOctalFieldStart(buffer);
|
||||
case DECIMAL -> isDecimalFieldStart(buffer);
|
||||
case HEXADECIMAL -> isHexFieldStart(buffer);
|
||||
default -> throw new AssertionError("Not supported radix");
|
||||
};
|
||||
}
|
||||
|
||||
// This method always moves the position of the supplied CharBuffer
|
||||
// removing the octal prefix symbols '0'.
|
||||
// The caller should reset the position when method returns false.
|
||||
private static boolean isOctalFieldStart(CharBuffer cb) {
|
||||
// .0<EOS> is not treated as octal field
|
||||
if (cb.remaining() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fetch two first characters
|
||||
int position = cb.position();
|
||||
char first = cb.get();
|
||||
char second = cb.get();
|
||||
|
||||
// Return false if the first char is not octal prefix '0' or second is a
|
||||
// field separator - parseV4FieldBsd will reset position to start of the field.
|
||||
// '.0.' fields will be successfully parsed in decimal radix.
|
||||
boolean isOctalPrefix = first == '0' && second != '.';
|
||||
|
||||
// If the prefix looks like octal - consume '0', otherwise 'false' is returned
|
||||
// and caller will reset the buffer position.
|
||||
if (isOctalPrefix) {
|
||||
cb.position(position + 1);
|
||||
}
|
||||
return isOctalPrefix;
|
||||
}
|
||||
|
||||
// This method doesn't move the position of the supplied CharBuffer
|
||||
private static boolean isDecimalFieldStart(CharBuffer cb) {
|
||||
return cb.hasRemaining();
|
||||
}
|
||||
|
||||
// This method always moves the position of the supplied CharBuffer
|
||||
// removing the hexadecimal prefix symbols '0x'.
|
||||
// The caller should reset the position when method returns false.
|
||||
private static boolean isHexFieldStart(CharBuffer cb) {
|
||||
if (cb.remaining() < 2) {
|
||||
return false;
|
||||
}
|
||||
char first = cb.get();
|
||||
char second = cb.get();
|
||||
return first == '0' && (second == 'x' || second == 'X');
|
||||
}
|
||||
|
||||
// Parse ASCII digit in given radix
|
||||
private static int parseAsciiDigit(char c, int radix) {
|
||||
assert radix == OCTAL || radix == DECIMAL || radix == HEXADECIMAL;
|
||||
if (radix == HEXADECIMAL) {
|
||||
return parseAsciiHexDigit(c);
|
||||
}
|
||||
int val = c - '0';
|
||||
return (val < 0 || val >= radix) ? -1 : val;
|
||||
}
|
||||
|
||||
// Parse ASCII digit in hexadecimal radix
|
||||
private static int parseAsciiHexDigit(char digit) {
|
||||
char c = Character.toLowerCase(digit);
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
return c - 'a' + 10;
|
||||
}
|
||||
return parseAsciiDigit(c, DECIMAL);
|
||||
}
|
||||
|
||||
// Supported radixes
|
||||
private static final int HEXADECIMAL = 16;
|
||||
private static final int DECIMAL = 10;
|
||||
private static final int OCTAL = 8;
|
||||
// Order in which field formats are exercised to parse one IP address textual field
|
||||
private static final int[] SUPPORTED_RADIXES = new int[]{HEXADECIMAL, OCTAL, DECIMAL};
|
||||
|
||||
// BSD parser's return values
|
||||
private final static long CANT_PARSE_IN_RADIX = -1L;
|
||||
private final static long TERMINAL_PARSE_ERROR = -2L;
|
||||
|
||||
private static final String ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP = "jdk.net.allowAmbiguousIPAddressLiterals";
|
||||
private static final boolean ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP_VALUE = Boolean.valueOf(
|
||||
GetPropertyAction.privilegedGetProperty(ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP, "false"));
|
||||
}
|
||||
|
||||
@ -63,22 +63,32 @@ public class BitArray {
|
||||
repn = new byte[(length + BITS_PER_UNIT - 1)/BITS_PER_UNIT];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BitArray of the specified size, initialized from the
|
||||
* specified byte array. The most significant bit of {@code a[0]} gets
|
||||
* index zero in the BitArray. The array must be large enough to specify
|
||||
* a value for every bit of the BitArray. i.e. {@code 8*a.length <= length}.
|
||||
*/
|
||||
public BitArray(int length, byte[] a) throws IllegalArgumentException {
|
||||
this(length, a, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BitArray of the specified size, initialized from the
|
||||
* specified byte array. The most significant bit of {@code a[0]} gets
|
||||
* index zero in the BitArray. The array a must be large enough
|
||||
* to specify a value for every bit in the BitArray. In other words,
|
||||
* {@code 8*a.length <= length}.
|
||||
* specified byte array starting at the specified offset. The most
|
||||
* significant bit of {@code a[ofs]} gets index zero in the BitArray.
|
||||
* The array must be large enough to specify a value for every bit of
|
||||
* the BitArray, i.e. {@code 8*(a.length - ofs) <= length}.
|
||||
*/
|
||||
public BitArray(int length, byte[] a) throws IllegalArgumentException {
|
||||
public BitArray(int length, byte[] a, int ofs)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
if (length < 0) {
|
||||
throw new IllegalArgumentException("Negative length for BitArray");
|
||||
}
|
||||
if (a.length * BITS_PER_UNIT < length) {
|
||||
throw new IllegalArgumentException("Byte array too short to represent " +
|
||||
"bit array of given length");
|
||||
if ((a.length - ofs) * BITS_PER_UNIT < length) {
|
||||
throw new IllegalArgumentException
|
||||
("Byte array too short to represent " + length + "-bit array");
|
||||
}
|
||||
|
||||
this.length = length;
|
||||
@ -93,7 +103,7 @@ public class BitArray {
|
||||
2. zero out extra bits in the last byte
|
||||
*/
|
||||
repn = new byte[repLength];
|
||||
System.arraycopy(a, 0, repn, 0, repLength);
|
||||
System.arraycopy(a, ofs, repn, 0, repLength);
|
||||
if (repLength > 0) {
|
||||
repn[repLength - 1] &= bitMask;
|
||||
}
|
||||
@ -270,7 +280,7 @@ public class BitArray {
|
||||
public BitArray truncate() {
|
||||
for (int i=length-1; i>=0; i--) {
|
||||
if (get(i)) {
|
||||
return new BitArray(i+1, Arrays.copyOf(repn, (i + BITS_PER_UNIT)/BITS_PER_UNIT));
|
||||
return new BitArray(i+1, repn, 0);
|
||||
}
|
||||
}
|
||||
return new BitArray(1);
|
||||
|
||||
@ -189,6 +189,28 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
|
||||
return result.intValue();
|
||||
}
|
||||
|
||||
// check the number of pad bits, validate the pad bits in the bytes
|
||||
// if enforcing DER (i.e. allowBER == false), and return the number of
|
||||
// bits of the resulting BitString
|
||||
private static int checkPaddedBits(int numOfPadBits, byte[] data, int start,
|
||||
int end, boolean allowBER) throws IOException {
|
||||
// number of pad bits should be from 0(min) to 7(max).
|
||||
if ((numOfPadBits < 0) || (numOfPadBits > 7)) {
|
||||
throw new IOException("Invalid number of padding bits");
|
||||
}
|
||||
int lenInBits = ((end - start) << 3) - numOfPadBits;
|
||||
if (lenInBits < 0) {
|
||||
throw new IOException("Not enough bytes in BitString");
|
||||
}
|
||||
|
||||
// padding bits should be all zeros for DER
|
||||
if (!allowBER && numOfPadBits != 0 &&
|
||||
(data[end - 1] & (0xff >>> (8 - numOfPadBits))) != 0) {
|
||||
throw new IOException("Invalid value of padding bits");
|
||||
}
|
||||
return lenInBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bit string which takes up the specified
|
||||
* number of bytes in this buffer.
|
||||
@ -201,18 +223,20 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
|
||||
throw new IOException("Invalid encoding: zero length bit string");
|
||||
}
|
||||
|
||||
int numOfPadBits = buf[pos];
|
||||
if ((numOfPadBits < 0) || (numOfPadBits > 7)) {
|
||||
throw new IOException("Invalid number of padding bits");
|
||||
}
|
||||
int start = pos;
|
||||
int end = start + len;
|
||||
skip(len); // Compatibility.
|
||||
|
||||
int numOfPadBits = buf[start++];
|
||||
checkPaddedBits(numOfPadBits, buf, start, end, allowBER);
|
||||
|
||||
// minus the first byte which indicates the number of padding bits
|
||||
byte[] retval = new byte[len - 1];
|
||||
System.arraycopy(buf, pos + 1, retval, 0, len - 1);
|
||||
if (numOfPadBits != 0) {
|
||||
// get rid of the padding bits
|
||||
retval[len - 2] &= (0xff << numOfPadBits);
|
||||
System.arraycopy(buf, start, retval, 0, len - 1);
|
||||
if (allowBER && numOfPadBits != 0) {
|
||||
// fix the potential non-zero padding bits
|
||||
retval[retval.length - 1] &= (0xff << numOfPadBits);
|
||||
}
|
||||
skip(len);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -228,26 +252,35 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
|
||||
* The bit string need not be byte-aligned.
|
||||
*/
|
||||
BitArray getUnalignedBitString() throws IOException {
|
||||
return getUnalignedBitString(available());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bit string which takes up the specified
|
||||
* number of bytes in this buffer.
|
||||
* The bit string need not be byte-aligned.
|
||||
*/
|
||||
BitArray getUnalignedBitString(int len) throws IOException {
|
||||
if (len > available())
|
||||
throw new IOException("short read of bit string");
|
||||
|
||||
if (len == 0) {
|
||||
throw new IOException("Invalid encoding: zero length bit string");
|
||||
}
|
||||
|
||||
if (pos >= count)
|
||||
return null;
|
||||
/*
|
||||
* Just copy the data into an aligned, padded octet buffer,
|
||||
* and consume the rest of the buffer.
|
||||
*/
|
||||
int len = available();
|
||||
int unusedBits = buf[pos] & 0xff;
|
||||
if (unusedBits > 7 ) {
|
||||
throw new IOException("Invalid value for unused bits: " + unusedBits);
|
||||
}
|
||||
byte[] bits = new byte[len - 1];
|
||||
// number of valid bits
|
||||
int length = (bits.length == 0) ? 0 : bits.length * 8 - unusedBits;
|
||||
|
||||
System.arraycopy(buf, pos + 1, bits, 0, len - 1);
|
||||
|
||||
BitArray bitArray = new BitArray(length, bits);
|
||||
pos = count;
|
||||
return bitArray;
|
||||
int start = pos;
|
||||
int end = start + len;
|
||||
pos = count; // Compatibility.
|
||||
int numOfPadBits = buf[start++];
|
||||
int lenInBits = checkPaddedBits(numOfPadBits, buf, start,
|
||||
end, allowBER);
|
||||
return new BitArray(lenInBits, buf, start);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -264,27 +264,7 @@ public class DerInputStream {
|
||||
return new BitArray(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* First byte = number of excess bits in the last octet of the
|
||||
* representation.
|
||||
*/
|
||||
length--;
|
||||
int excessBits = buffer.read();
|
||||
if (excessBits < 0) {
|
||||
throw new IOException("Unused bits of bit string invalid");
|
||||
}
|
||||
int validBits = length*8 - excessBits;
|
||||
if (validBits < 0) {
|
||||
throw new IOException("Valid bits of bit string invalid");
|
||||
}
|
||||
|
||||
byte[] repn = new byte[length];
|
||||
|
||||
if ((length != 0) && (buffer.read(repn) != length)) {
|
||||
throw new IOException("Short read of DER bit string");
|
||||
}
|
||||
|
||||
return new BitArray(validBits, repn);
|
||||
return buffer.getUnalignedBitString(length);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -276,11 +276,6 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
|
||||
int wrap = 1;
|
||||
static const char my_version[] = ZLIB_VERSION;
|
||||
|
||||
ushf *overlay;
|
||||
/* We overlay pending_buf and d_buf+l_buf. This works since the average
|
||||
* output size for (length,distance) codes is <= 24 bits.
|
||||
*/
|
||||
|
||||
if (version == Z_NULL || version[0] != my_version[0] ||
|
||||
stream_size != sizeof(z_stream)) {
|
||||
return Z_VERSION_ERROR;
|
||||
@ -350,9 +345,47 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
|
||||
|
||||
s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
|
||||
|
||||
overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
|
||||
s->pending_buf = (uchf *) overlay;
|
||||
s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
|
||||
/* We overlay pending_buf and sym_buf. This works since the average size
|
||||
* for length/distance pairs over any compressed block is assured to be 31
|
||||
* bits or less.
|
||||
*
|
||||
* Analysis: The longest fixed codes are a length code of 8 bits plus 5
|
||||
* extra bits, for lengths 131 to 257. The longest fixed distance codes are
|
||||
* 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest
|
||||
* possible fixed-codes length/distance pair is then 31 bits total.
|
||||
*
|
||||
* sym_buf starts one-fourth of the way into pending_buf. So there are
|
||||
* three bytes in sym_buf for every four bytes in pending_buf. Each symbol
|
||||
* in sym_buf is three bytes -- two for the distance and one for the
|
||||
* literal/length. As each symbol is consumed, the pointer to the next
|
||||
* sym_buf value to read moves forward three bytes. From that symbol, up to
|
||||
* 31 bits are written to pending_buf. The closest the written pending_buf
|
||||
* bits gets to the next sym_buf symbol to read is just before the last
|
||||
* code is written. At that time, 31*(n-2) bits have been written, just
|
||||
* after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at
|
||||
* 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1
|
||||
* symbols are written.) The closest the writing gets to what is unread is
|
||||
* then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and
|
||||
* can range from 128 to 32768.
|
||||
*
|
||||
* Therefore, at a minimum, there are 142 bits of space between what is
|
||||
* written and what is read in the overlain buffers, so the symbols cannot
|
||||
* be overwritten by the compressed data. That space is actually 139 bits,
|
||||
* due to the three-bit fixed-code block header.
|
||||
*
|
||||
* That covers the case where either Z_FIXED is specified, forcing fixed
|
||||
* codes, or when the use of fixed codes is chosen, because that choice
|
||||
* results in a smaller compressed block than dynamic codes. That latter
|
||||
* condition then assures that the above analysis also covers all dynamic
|
||||
* blocks. A dynamic-code block will only be chosen to be emitted if it has
|
||||
* fewer bits than a fixed-code block would for the same set of symbols.
|
||||
* Therefore its average symbol length is assured to be less than 31. So
|
||||
* the compressed data for a dynamic block also cannot overwrite the
|
||||
* symbols from which it is being constructed.
|
||||
*/
|
||||
|
||||
s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
|
||||
s->pending_buf_size = (ulg)s->lit_bufsize * 4;
|
||||
|
||||
if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
|
||||
s->pending_buf == Z_NULL) {
|
||||
@ -361,8 +394,12 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
|
||||
deflateEnd (strm);
|
||||
return Z_MEM_ERROR;
|
||||
}
|
||||
s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
|
||||
s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
|
||||
s->sym_buf = s->pending_buf + s->lit_bufsize;
|
||||
s->sym_end = (s->lit_bufsize - 1) * 3;
|
||||
/* We avoid equality with lit_bufsize*3 because of wraparound at 64K
|
||||
* on 16 bit machines and because stored blocks are restricted to
|
||||
* 64K-1 bytes.
|
||||
*/
|
||||
|
||||
s->level = level;
|
||||
s->strategy = strategy;
|
||||
@ -573,7 +610,8 @@ int ZEXPORT deflatePrime (strm, bits, value)
|
||||
|
||||
if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
s = strm->state;
|
||||
if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
|
||||
if (bits < 0 || bits > 16 ||
|
||||
s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
|
||||
return Z_BUF_ERROR;
|
||||
do {
|
||||
put = Buf_size - s->bi_valid;
|
||||
@ -1132,7 +1170,6 @@ int ZEXPORT deflateCopy (dest, source)
|
||||
#else
|
||||
deflate_state *ds;
|
||||
deflate_state *ss;
|
||||
ushf *overlay;
|
||||
|
||||
|
||||
if (deflateStateCheck(source) || dest == Z_NULL) {
|
||||
@ -1152,8 +1189,7 @@ int ZEXPORT deflateCopy (dest, source)
|
||||
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
|
||||
ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
|
||||
ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
|
||||
overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
|
||||
ds->pending_buf = (uchf *) overlay;
|
||||
ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
|
||||
|
||||
if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
|
||||
ds->pending_buf == Z_NULL) {
|
||||
@ -1167,8 +1203,7 @@ int ZEXPORT deflateCopy (dest, source)
|
||||
zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
|
||||
|
||||
ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
|
||||
ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
|
||||
ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
|
||||
ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
|
||||
|
||||
ds->l_desc.dyn_tree = ds->dyn_ltree;
|
||||
ds->d_desc.dyn_tree = ds->dyn_dtree;
|
||||
@ -1936,7 +1971,7 @@ local block_state deflate_fast(s, flush)
|
||||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
if (s->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
@ -2067,7 +2102,7 @@ local block_state deflate_slow(s, flush)
|
||||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
if (s->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
@ -2142,7 +2177,7 @@ local block_state deflate_rle(s, flush)
|
||||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
if (s->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
@ -2181,7 +2216,7 @@ local block_state deflate_huff(s, flush)
|
||||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
if (s->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
|
||||
@ -241,7 +241,7 @@ typedef struct internal_state {
|
||||
/* Depth of each subtree used as tie breaker for trees of equal frequency
|
||||
*/
|
||||
|
||||
uchf *l_buf; /* buffer for literals or lengths */
|
||||
uchf *sym_buf; /* buffer for distances and literals/lengths */
|
||||
|
||||
uInt lit_bufsize;
|
||||
/* Size of match buffer for literals/lengths. There are 4 reasons for
|
||||
@ -263,13 +263,8 @@ typedef struct internal_state {
|
||||
* - I can't count above 4
|
||||
*/
|
||||
|
||||
uInt last_lit; /* running index in l_buf */
|
||||
|
||||
ushf *d_buf;
|
||||
/* Buffer for distances. To simplify the code, d_buf and l_buf have
|
||||
* the same number of elements. To use different lengths, an extra flag
|
||||
* array would be necessary.
|
||||
*/
|
||||
uInt sym_next; /* running index in sym_buf */
|
||||
uInt sym_end; /* symbol table full when sym_next reaches this */
|
||||
|
||||
ulg opt_len; /* bit length of current block with optimal trees */
|
||||
ulg static_len; /* bit length of current block with static trees */
|
||||
@ -349,20 +344,22 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
|
||||
|
||||
# define _tr_tally_lit(s, c, flush) \
|
||||
{ uch cc = (c); \
|
||||
s->d_buf[s->last_lit] = 0; \
|
||||
s->l_buf[s->last_lit++] = cc; \
|
||||
s->sym_buf[s->sym_next++] = 0; \
|
||||
s->sym_buf[s->sym_next++] = 0; \
|
||||
s->sym_buf[s->sym_next++] = cc; \
|
||||
s->dyn_ltree[cc].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
flush = (s->sym_next == s->sym_end); \
|
||||
}
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
{ uch len = (uch)(length); \
|
||||
ush dist = (ush)(distance); \
|
||||
s->d_buf[s->last_lit] = dist; \
|
||||
s->l_buf[s->last_lit++] = len; \
|
||||
s->sym_buf[s->sym_next++] = (uch)dist; \
|
||||
s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \
|
||||
s->sym_buf[s->sym_next++] = len; \
|
||||
dist--; \
|
||||
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
|
||||
s->dyn_dtree[d_code(dist)].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
flush = (s->sym_next == s->sym_end); \
|
||||
}
|
||||
#else
|
||||
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
|
||||
|
||||
@ -440,7 +440,7 @@ local void init_block(s)
|
||||
|
||||
s->dyn_ltree[END_BLOCK].Freq = 1;
|
||||
s->opt_len = s->static_len = 0L;
|
||||
s->last_lit = s->matches = 0;
|
||||
s->sym_next = s->matches = 0;
|
||||
}
|
||||
|
||||
#define SMALLEST 1
|
||||
@ -971,7 +971,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
|
||||
|
||||
Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
|
||||
opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
|
||||
s->last_lit));
|
||||
s->sym_next / 3));
|
||||
|
||||
if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
|
||||
|
||||
@ -1040,8 +1040,9 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
|
||||
unsigned dist; /* distance of matched string */
|
||||
unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
|
||||
{
|
||||
s->d_buf[s->last_lit] = (ush)dist;
|
||||
s->l_buf[s->last_lit++] = (uch)lc;
|
||||
s->sym_buf[s->sym_next++] = (uch)dist;
|
||||
s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
|
||||
s->sym_buf[s->sym_next++] = (uch)lc;
|
||||
if (dist == 0) {
|
||||
/* lc is the unmatched char */
|
||||
s->dyn_ltree[lc].Freq++;
|
||||
@ -1056,30 +1057,7 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
|
||||
s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
|
||||
s->dyn_dtree[d_code(dist)].Freq++;
|
||||
}
|
||||
|
||||
#ifdef TRUNCATE_BLOCK
|
||||
/* Try to guess if it is profitable to stop the current block here */
|
||||
if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
|
||||
/* Compute an upper bound for the compressed length */
|
||||
ulg out_length = (ulg)s->last_lit*8L;
|
||||
ulg in_length = (ulg)((long)s->strstart - s->block_start);
|
||||
int dcode;
|
||||
for (dcode = 0; dcode < D_CODES; dcode++) {
|
||||
out_length += (ulg)s->dyn_dtree[dcode].Freq *
|
||||
(5L+extra_dbits[dcode]);
|
||||
}
|
||||
out_length >>= 3;
|
||||
Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
|
||||
s->last_lit, in_length, out_length,
|
||||
100L - out_length*100L/in_length));
|
||||
if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
|
||||
}
|
||||
#endif
|
||||
return (s->last_lit == s->lit_bufsize-1);
|
||||
/* We avoid equality with lit_bufsize because of wraparound at 64K
|
||||
* on 16 bit machines and because stored blocks are restricted to
|
||||
* 64K-1 bytes.
|
||||
*/
|
||||
return (s->sym_next == s->sym_end);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
@ -1092,13 +1070,14 @@ local void compress_block(s, ltree, dtree)
|
||||
{
|
||||
unsigned dist; /* distance of matched string */
|
||||
int lc; /* match length or unmatched char (if dist == 0) */
|
||||
unsigned lx = 0; /* running index in l_buf */
|
||||
unsigned sx = 0; /* running index in sym_buf */
|
||||
unsigned code; /* the code to send */
|
||||
int extra; /* number of extra bits to send */
|
||||
|
||||
if (s->last_lit != 0) do {
|
||||
dist = s->d_buf[lx];
|
||||
lc = s->l_buf[lx++];
|
||||
if (s->sym_next != 0) do {
|
||||
dist = s->sym_buf[sx++] & 0xff;
|
||||
dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
|
||||
lc = s->sym_buf[sx++];
|
||||
if (dist == 0) {
|
||||
send_code(s, lc, ltree); /* send a literal byte */
|
||||
Tracecv(isgraph(lc), (stderr," '%c' ", lc));
|
||||
@ -1123,11 +1102,10 @@ local void compress_block(s, ltree, dtree)
|
||||
}
|
||||
} /* literal or match pair ? */
|
||||
|
||||
/* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
|
||||
Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
|
||||
"pendingBuf overflow");
|
||||
/* Check that the overlay between pending_buf and sym_buf is ok: */
|
||||
Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
|
||||
|
||||
} while (lx < s->last_lit);
|
||||
} while (sx < s->sym_next);
|
||||
|
||||
send_code(s, END_BLOCK, ltree);
|
||||
}
|
||||
|
||||
@ -380,6 +380,11 @@ final class SMFParser {
|
||||
case 0xF7:
|
||||
// sys ex
|
||||
int sysexLength = (int) readVarInt();
|
||||
if (sysexLength < 0 || sysexLength > trackLength - pos) {
|
||||
throw new InvalidMidiDataException("Message length is out of bounds: "
|
||||
+ sysexLength);
|
||||
}
|
||||
|
||||
byte[] sysexData = new byte[sysexLength];
|
||||
read(sysexData);
|
||||
|
||||
@ -392,8 +397,8 @@ final class SMFParser {
|
||||
// meta
|
||||
int metaType = readUnsigned();
|
||||
int metaLength = (int) readVarInt();
|
||||
if (metaLength < 0) {
|
||||
throw new InvalidMidiDataException("length out of bounds: "
|
||||
if (metaLength < 0 || metaLength > trackLength - pos) {
|
||||
throw new InvalidMidiDataException("Message length is out of bounds: "
|
||||
+ metaLength);
|
||||
}
|
||||
final byte[] metaData;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@ -26,6 +25,7 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
|
||||
|
||||
/**
|
||||
* This class represents the constant pool, i.e., a table of constants, of
|
||||
@ -37,6 +37,7 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
* @see Constant
|
||||
* @see com.sun.org.apache.bcel.internal.generic.ConstantPoolGen
|
||||
* @LastModified: May 2022
|
||||
*/
|
||||
public class ConstantPool implements Cloneable, Node {
|
||||
|
||||
@ -222,8 +223,16 @@ public class ConstantPool implements Cloneable, Node {
|
||||
* @throws IOException
|
||||
*/
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
file.writeShort(constantPool.length);
|
||||
for (int i = 1; i < constantPool.length; i++) {
|
||||
/*
|
||||
* Constants over the size of the constant pool shall not be written out.
|
||||
* This is a redundant measure as the ConstantPoolGen should have already
|
||||
* reported an error back in the situation.
|
||||
*/
|
||||
int size = constantPool.length < ConstantPoolGen.CONSTANT_POOL_SIZE - 1 ?
|
||||
constantPool.length : ConstantPoolGen.CONSTANT_POOL_SIZE - 1;
|
||||
|
||||
file.writeShort(size);
|
||||
for (int i = 1; i < size; i++) {
|
||||
if (constantPool[i] != null) {
|
||||
constantPool[i].dump(file);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@ -50,10 +50,10 @@ import com.sun.org.apache.bcel.internal.classfile.ConstantUtf8;
|
||||
* JVM and that Double and Long constants need two slots.
|
||||
*
|
||||
* @see Constant
|
||||
* @LastModified: May 2021
|
||||
* @LastModified: May 2022
|
||||
*/
|
||||
public class ConstantPoolGen {
|
||||
|
||||
public static final int CONSTANT_POOL_SIZE = 65536;
|
||||
private static final int DEFAULT_BUFFER_SIZE = 256;
|
||||
private int size;
|
||||
private Constant[] constants;
|
||||
@ -83,7 +83,7 @@ public class ConstantPoolGen {
|
||||
public ConstantPoolGen(final Constant[] cs) {
|
||||
final StringBuilder sb = new StringBuilder(DEFAULT_BUFFER_SIZE);
|
||||
|
||||
size = Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64);
|
||||
size = Math.min(Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64), CONSTANT_POOL_SIZE);
|
||||
constants = new Constant[size];
|
||||
|
||||
System.arraycopy(cs, 0, constants, 0, cs.length);
|
||||
@ -212,9 +212,18 @@ public class ConstantPoolGen {
|
||||
/** Resize internal array of constants.
|
||||
*/
|
||||
protected void adjustSize() {
|
||||
// 3 extra spaces are needed as some entries may take 3 slots
|
||||
if (index + 3 >= CONSTANT_POOL_SIZE) {
|
||||
throw new RuntimeException("The number of constants " + (index + 3)
|
||||
+ " is over the size of the constant pool: "
|
||||
+ (CONSTANT_POOL_SIZE - 1));
|
||||
}
|
||||
|
||||
if (index + 3 >= size) {
|
||||
final Constant[] cs = constants;
|
||||
size *= 2;
|
||||
// the constant array shall not exceed the size of the constant pool
|
||||
size = Math.min(size, CONSTANT_POOL_SIZE);
|
||||
constants = new Constant[size];
|
||||
System.arraycopy(cs, 0, constants, 0, index);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2021, 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
|
||||
@ -26,52 +26,83 @@
|
||||
* @bug 4511556
|
||||
* @summary Verify BitString value containing padding bits is accepted.
|
||||
* @modules java.base/sun.security.util
|
||||
* @library /test/lib
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.Utils;
|
||||
import jdk.test.lib.hexdump.HexPrinter;
|
||||
|
||||
import sun.security.util.BitArray;
|
||||
import sun.security.util.DerInputStream;
|
||||
|
||||
public class PaddedBitString {
|
||||
|
||||
// Relaxed the BitString parsing routine to accept bit strings
|
||||
// with padding bits, ex. treat DER_BITSTRING_PAD6 as the same
|
||||
// bit string as DER_BITSTRING_NOPAD.
|
||||
// with padding bits, ex. treat DER_BITSTRING_PAD6_b as the same
|
||||
// bit string as DER_BITSTRING_PAD6_0/DER_BITSTRING_NOPAD.
|
||||
// Note:
|
||||
// 1. the number of padding bits has to be in [0...7]
|
||||
// 2. value of the padding bits is ignored
|
||||
|
||||
// bit string (01011101 11000000)
|
||||
// With 6 padding bits (01011101 11001011)
|
||||
private final static byte[] DER_BITSTRING_PAD6 = { 3, 3, 6,
|
||||
(byte)0x5d, (byte)0xcb };
|
||||
|
||||
// With no padding bits
|
||||
private final static byte[] DER_BITSTRING_NOPAD = { 3, 3, 0,
|
||||
(byte)0x5d, (byte)0xc0 };
|
||||
// With 6 zero padding bits (01011101 11000000)
|
||||
private final static byte[] DER_BITSTRING_PAD6_0 = { 3, 3, 6,
|
||||
(byte)0x5d, (byte)0xc0 };
|
||||
|
||||
// With 6 nonzero padding bits (01011101 11001011)
|
||||
private final static byte[] DER_BITSTRING_PAD6_b = { 3, 3, 6,
|
||||
(byte)0x5d, (byte)0xcb };
|
||||
|
||||
// With 8 padding bits
|
||||
private final static byte[] DER_BITSTRING_PAD8_0 = { 3, 3, 8,
|
||||
(byte)0x5d, (byte)0xc0 };
|
||||
|
||||
private final static byte[] BITS = { (byte)0x5d, (byte)0xc0 };
|
||||
|
||||
static enum Type {
|
||||
BIT_STRING,
|
||||
UNALIGNED_BIT_STRING;
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
byte[] ba0, ba1;
|
||||
try {
|
||||
DerInputStream derin = new DerInputStream(DER_BITSTRING_PAD6);
|
||||
ba1 = derin.getBitString();
|
||||
} catch( IOException e ) {
|
||||
e.printStackTrace();
|
||||
throw new Exception("Unable to parse BitString with 6 padding bits");
|
||||
}
|
||||
test(DER_BITSTRING_NOPAD, new BitArray(16, BITS));
|
||||
test(DER_BITSTRING_PAD6_0, new BitArray(10, BITS));
|
||||
test(DER_BITSTRING_PAD6_b, new BitArray(10, BITS));
|
||||
test(DER_BITSTRING_PAD8_0, null);
|
||||
System.out.println("Tests Passed");
|
||||
}
|
||||
|
||||
try {
|
||||
DerInputStream derin = new DerInputStream(DER_BITSTRING_NOPAD);
|
||||
ba0 = derin.getBitString();
|
||||
} catch( IOException e ) {
|
||||
e.printStackTrace();
|
||||
throw new Exception("Unable to parse BitString with no padding");
|
||||
}
|
||||
|
||||
if (Arrays.equals(ba1, ba0) == false ) {
|
||||
throw new Exception("BitString comparison check failed");
|
||||
private static void test(byte[] in, BitArray ans) throws IOException {
|
||||
System.out.println("Testing " +
|
||||
HexPrinter.minimal().toString(in));
|
||||
for (Type t : Type.values()) {
|
||||
DerInputStream derin = new DerInputStream(in);
|
||||
boolean shouldPass = (ans != null);
|
||||
switch (t) {
|
||||
case BIT_STRING:
|
||||
if (shouldPass) {
|
||||
Asserts.assertTrue(Arrays.equals(ans.toByteArray(),
|
||||
derin.getBitString()));
|
||||
} else {
|
||||
Utils.runAndCheckException(() -> derin.getBitString(),
|
||||
IOException.class);
|
||||
}
|
||||
break;
|
||||
case UNALIGNED_BIT_STRING:
|
||||
if (shouldPass) {
|
||||
Asserts.assertEQ(ans, derin.getUnalignedBitString());
|
||||
} else {
|
||||
Utils.runAndCheckException(() ->
|
||||
derin.getUnalignedBitString(), IOException.class);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user