From 6b7839d9d70958b85da5c9340a53d1f21bd12c31 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Wed, 21 Sep 2011 16:06:11 +0000
Subject: [PATCH] Fix OPENDJ-291: Do not use String representation of byte[] when constructing attribute values and byte strings.
---
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java | 138 ++++++++++++++++++++++++++++++++++++---------
1 files changed, 109 insertions(+), 29 deletions(-)
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java
index 6b693c1..9260a46 100755
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2009 Sun Microsystems, Inc.
+ * Portions copyright 2011 ForgeRock AS
*/
package org.forgerock.opendj.ldap;
@@ -32,6 +33,8 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
import java.util.logging.Level;
import com.forgerock.opendj.util.StaticUtils;
@@ -364,22 +367,22 @@
* An invocation of the form:
*
* <pre>
- * src.append(b)
+ * src.append(bytes)
* </pre>
*
* Behaves in exactly the same way as the invocation:
*
* <pre>
- * src.append(b, 0, b.length);
+ * src.append(bytes, 0, bytes.length);
* </pre>
*
- * @param b
+ * @param bytes
* The byte array to be appended to this byte string builder.
* @return This byte string builder.
*/
- public ByteStringBuilder append(final byte[] b)
+ public ByteStringBuilder append(final byte[] bytes)
{
- return append(b, 0, b.length);
+ return append(bytes, 0, bytes.length);
}
@@ -387,28 +390,28 @@
/**
* Appends the provided byte array to this byte string builder.
*
- * @param b
+ * @param bytes
* The byte array to be appended to this byte string builder.
* @param offset
* The offset of the byte array to be used; must be non-negative and
- * no larger than {@code b.length} .
+ * no larger than {@code bytes.length} .
* @param length
* The length of the byte array to be used; must be non-negative and
- * no larger than {@code b.length - offset}.
+ * no larger than {@code bytes.length - offset}.
* @return This byte string builder.
* @throws IndexOutOfBoundsException
* If {@code offset} is negative or if {@code length} is negative or
- * if {@code offset + length} is greater than {@code b.length}.
+ * if {@code offset + length} is greater than {@code bytes.length}.
*/
- public ByteStringBuilder append(final byte[] b, final int offset,
+ public ByteStringBuilder append(final byte[] bytes, final int offset,
final int length) throws IndexOutOfBoundsException
{
- ByteString.checkArrayBounds(b, offset, length);
+ ByteString.checkArrayBounds(bytes, offset, length);
if (length != 0)
{
ensureAdditionalCapacity(length);
- System.arraycopy(b, offset, buffer, this.length, length);
+ System.arraycopy(bytes, offset, buffer, this.length, length);
this.length += length;
}
@@ -498,6 +501,57 @@
/**
+ * Appends the UTF-8 encoded bytes of the provided
+ * char array to this byte string
+ * builder.
+ *
+ * @param chars
+ * The char array whose UTF-8 encoding is to be appended to this byte
+ * string builder.
+ * @return This byte string builder.
+ */
+ public ByteStringBuilder append(final char[] chars)
+ {
+ if (chars == null)
+ {
+ return this;
+ }
+
+ // Assume that each char is 1 byte
+ final int len = chars.length;
+ ensureAdditionalCapacity(len);
+
+ for (int i = 0; i < len; i++)
+ {
+ final char c = chars[i];
+ final byte b = (byte) (c & 0x0000007F);
+
+ if (c == b)
+ {
+ buffer[this.length + i] = b;
+ }
+ else
+ {
+ // There is a multi-byte char. Defer to JDK.
+ final Charset utf8 = Charset.forName("UTF-8");
+ final ByteBuffer byteBuffer = utf8.encode(CharBuffer.wrap(chars));
+ final int remaining = byteBuffer.remaining();
+ ensureAdditionalCapacity(remaining - len);
+ byteBuffer.get(buffer, this.length, remaining);
+ this.length += remaining;
+ return this;
+ }
+ }
+
+ // The 1 byte char assumption was correct
+ this.length += len;
+ return this;
+
+ }
+
+
+
+ /**
* Appends the provided {@code InputStream} to this byte string builder.
*
* @param stream
@@ -578,11 +632,26 @@
/**
- * Appends the provided object to this byte string builder. If the object is
- * an instance of {@code ByteSequence} then its contents will be appended
- * directly to this byte string builder using the {@code append(ByteSequence)}
- * method. Otherwise the string representation of the object will be appended
- * using the {@code append(String)} method.
+ * Appends the byte string representation of the provided object to this byte
+ * string builder. The object is converted to a byte string as follows:
+ * <ul>
+ * <li>if the object is an instance of {@code ByteSequence} then this method
+ * is equivalent to calling {@link #append(ByteSequence)}
+ * <li>if the object is a {@code byte[]} then this method is equivalent to
+ * calling {@link #append(byte[])}
+ * <li>if the object is a {@code char[]} then this method is equivalent to
+ * calling {@link #append(char[])}
+ * <li>for all other types of object this method is equivalent to calling
+ * {@link #append(String)} with the {@code toString()} representation of the
+ * provided object.
+ * </ul>
+ * <b>Note:</b> this method treats {@code Long} and {@code Integer} objects
+ * like any other type of {@code Object}. More specifically, the following
+ * invocations are not equivalent:
+ * <ul>
+ * <li>{@code append(0)} is not equivalent to {@code append((Object) 0)}
+ * <li>{@code append(0L)} is not equivalent to {@code append((Object) 0L)}
+ * </ul>
*
* @param o
* The object to be appended to this byte string builder.
@@ -598,6 +667,14 @@
{
return append((ByteSequence) o);
}
+ else if (o instanceof byte[])
+ {
+ return append((byte[]) o);
+ }
+ else if (o instanceof char[])
+ {
+ return append((char[]) o);
+ }
else
{
return append(o.toString());
@@ -795,11 +872,12 @@
/**
* {@inheritDoc}
*/
- public int compareTo(final byte[] b, final int offset, final int length)
+ public int compareTo(final byte[] bytes, final int offset, final int length)
throws IndexOutOfBoundsException
{
- ByteString.checkArrayBounds(b, offset, length);
- return ByteString.compareTo(this.buffer, 0, this.length, b, offset, length);
+ ByteString.checkArrayBounds(bytes, offset, length);
+ return ByteString.compareTo(this.buffer, 0, this.length, bytes, offset,
+ length);
}
@@ -821,10 +899,10 @@
/**
* {@inheritDoc}
*/
- public byte[] copyTo(final byte[] b)
+ public byte[] copyTo(final byte[] bytes)
{
- copyTo(b, 0);
- return b;
+ copyTo(bytes, 0);
+ return bytes;
}
@@ -832,15 +910,16 @@
/**
* {@inheritDoc}
*/
- public byte[] copyTo(final byte[] b, final int offset)
+ public byte[] copyTo(final byte[] bytes, final int offset)
throws IndexOutOfBoundsException
{
if (offset < 0)
{
throw new IndexOutOfBoundsException();
}
- System.arraycopy(buffer, 0, b, offset, Math.min(length, b.length - offset));
- return b;
+ System.arraycopy(buffer, 0, bytes, offset,
+ Math.min(length, bytes.length - offset));
+ return bytes;
}
@@ -892,11 +971,12 @@
/**
* {@inheritDoc}
*/
- public boolean equals(final byte[] b, final int offset, final int length)
+ public boolean equals(final byte[] bytes, final int offset, final int length)
throws IndexOutOfBoundsException
{
- ByteString.checkArrayBounds(b, offset, length);
- return ByteString.equals(this.buffer, 0, this.length, b, offset, length);
+ ByteString.checkArrayBounds(bytes, offset, length);
+ return ByteString
+ .equals(this.buffer, 0, this.length, bytes, offset, length);
}
--
Gitblit v1.10.0