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 &lt;= 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 &lt;= 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;
     }
 
     /**

Reply via email to