This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit ebe805a2730ad38886f9f04bd4d242e0a8c9caaa Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Sat Apr 20 13:40:04 2024 -0400 Base64 constructor makes a defensive copy of a custom alphabet array --- src/changes/changes.xml | 3 +- .../org/apache/commons/codec/binary/Base64.java | 44 +++++++++++----------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 018e6f41..c88d2d7c 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -49,7 +49,8 @@ The <action> type attribute can be add,update,fix,remove. <action type="fix" dev="ggregory" due-to="Gary Gregory">Optimize memory allocation in PhoneticEngine.</action> <action type="fix" dev="ggregory" due-to="Gary Gregory">BCodec and QCodec encode() methods throw UnsupportedCharsetException instead of EncoderException.</action> <action type="fix" dev="ggregory" due-to="Gary Gregory">Set Javadoc link to latest Java API LTS version.</action> - <action type="fix" dev="ggregory" due-to="Gary Gregory">Base64 constructor makes a better defensive copy of the line separator array.</action> + <action type="fix" dev="ggregory" due-to="Gary Gregory">Base64 constructor makes a defensive copy of the line separator array.</action> + <action type="fix" dev="ggregory" due-to="Gary Gregory">Base64 constructor makes a defensive copy of a custom alphabet array.</action> <!-- ADD --> <action type="add" dev="ggregory" due-to="Gary Gregory">Add override org.apache.commons.codec.language.bm.Rule.PhonemeExpr.size().</action> <action type="add" dev="ggregory" due-to="Chris Kocel, Gary Gregory">Add support for Base64 custom alphabets #266.</action> diff --git a/src/main/java/org/apache/commons/codec/binary/Base64.java b/src/main/java/org/apache/commons/codec/binary/Base64.java index df72909f..f482db9d 100644 --- a/src/main/java/org/apache/commons/codec/binary/Base64.java +++ b/src/main/java/org/apache/commons/codec/binary/Base64.java @@ -498,6 +498,8 @@ public class Base64 extends BaseNCodec { */ private final int encodeSize; + private final boolean isUrlSafe; + /** * Constructs a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. * <p> @@ -646,8 +648,7 @@ public class Base64 extends BaseNCodec { /** * Constructs a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. * <p> - * When encoding the line length and line separator are given in the constructor, and the encoding table is - * STANDARD_ENCODE_TABLE. + * When encoding the line length and line separator are given in the constructor, and the encoding table is STANDARD_ENCODE_TABLE. * </p> * <p> * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data. @@ -656,29 +657,28 @@ public class Base64 extends BaseNCodec { * When decoding all variants are supported. * </p> * - * @param lineLength - * Each line of encoded data will be at most of the given length (rounded down to the nearest multiple of - * 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when - * decoding. - * @param lineSeparator - * Each line of encoded data will end with this sequence of bytes; the constructor makes a defensive copy. - * @param padding padding byte. - * @param encodeTable - * The manual encodeTable - a byte array of 64 chars. + * @param lineLength Each line of encoded data will be at most of the given length (rounded down to the nearest multiple of 4). If lineLength <= 0, + * then the output will not be divided into lines (chunks). Ignored when decoding. + * @param lineSeparator Each line of encoded data will end with this sequence of bytes; the constructor makes a defensive copy. May be null. + * @param padding padding byte. + * @param encodeTable The manual encodeTable - a byte array of 64 chars. * @param decodingPolicy The decoding policy. - * @throws IllegalArgumentException - * Thrown when the {@code lineSeparator} contains Base64 characters. + * @throws IllegalArgumentException Thrown when the {@code lineSeparator} contains Base64 characters. */ private Base64(final int lineLength, final byte[] lineSeparator, final byte padding, final byte[] encodeTable, final CodecPolicy decodingPolicy) { super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, lineLength, toLength(lineSeparator), padding, decodingPolicy); - this.encodeTable = Objects.requireNonNull(encodeTable, "encodeTable"); - if (encodeTable == STANDARD_ENCODE_TABLE || encodeTable == URL_SAFE_ENCODE_TABLE) { + Objects.requireNonNull(encodeTable, "encodeTable"); + if (encodeTable.length != ALPHABET_LENGTH) { + throw new IllegalArgumentException("encodeTable must have exactly 64 entries."); + } + this.isUrlSafe = encodeTable == URL_SAFE_ENCODE_TABLE; + if (encodeTable == STANDARD_ENCODE_TABLE || this.isUrlSafe) { decodeTable = DECODE_TABLE; + // No need of a defensive copy of an internal table. + this.encodeTable = encodeTable; } else { - if (encodeTable.length != ALPHABET_LENGTH) { - throw new IllegalArgumentException("encodeTable must have exactly 64 entries."); - } - decodeTable = calculateDecodeTable(encodeTable); + this.encodeTable = encodeTable.clone(); + this.decodeTable = calculateDecodeTable(this.encodeTable); } // TODO could be simplified if there is no requirement to reject invalid line sep when length <=0 // @see test case Base64Test.testConstructors() @@ -919,13 +919,13 @@ public class Base64 extends BaseNCodec { } /** - * Returns our current encode mode. True if we're URL-SAFE, false otherwise. + * Returns our current encode mode. True if we're URL-safe, false otherwise. * - * @return true if we're in URL-SAFE mode, false otherwise. + * @return true if we're in URL-safe mode, false otherwise. * @since 1.4 */ public boolean isUrlSafe() { - return this.encodeTable == URL_SAFE_ENCODE_TABLE; + return isUrlSafe; } /**