Skip to content
Permalink
Browse files
8153490: Cannot setBytes() if incoming buffer's length is bigger than…
… number of elements we want to insert.

Reviewed-by: lancea
  • Loading branch information
kariya-mitsuru authored and Lance Andersen committed Oct 28, 2021
1 parent cb989cf commit 63b9f8c0da2ed3634002f0f67b18555826aeddc4
Showing 4 changed files with 253 additions and 94 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 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
@@ -298,22 +298,21 @@ public long position(Blob pattern, long start)
}

/**
* Writes the given array of bytes to the <code>BLOB</code> value that
* this <code>Blob</code> object represents, starting at position
* <code>pos</code>, and returns the number of bytes written.
* Writes the given array of bytes to the {@code BLOB} value that
* this {@code Blob} object represents, starting at position
* {@code pos}, and returns the number of bytes written.
*
* @param pos the position in the SQL <code>BLOB</code> value at which
* to start writing. The first position is <code>1</code>;
* must not be less than <code>1</code> nor greater than
* the length of this <code>SerialBlob</code> object.
* @param bytes the array of bytes to be written to the <code>BLOB</code>
* value that this <code>Blob</code> object represents
* @param pos the position in the SQL {@code BLOB} value at which
* to start writing. The first position is {@code 1};
* must not be less than {@code 1} nor greater than
* the length+1 of this {@code SerialBlob} object.
* @param bytes the array of bytes to be written to the {@code BLOB}
* value that this {@code Blob} object represents
* @return the number of bytes written
* @throws SerialException if there is an error accessing the
* <code>BLOB</code> value; or if an invalid position is set; if an
* invalid offset value is set;
* {@code BLOB} value; or if an invalid position is set;
* if {@code free} had previously been called on this object
* @throws SQLException if there is an error accessing the <code>BLOB</code>
* @throws SQLException if there is an error accessing the {@code BLOB}
* value from the database
* @see #getBytes
*/
@@ -323,33 +322,33 @@ public int setBytes(long pos, byte[] bytes)
}

/**
* Writes all or part of the given <code>byte</code> array to the
* <code>BLOB</code> value that this <code>Blob</code> object represents
* Writes all or part of the given {@code byte} array to the
* {@code BLOB} value that this {@code Blob} object represents
* and returns the number of bytes written.
* Writing starts at position <code>pos</code> in the <code>BLOB</code>
* value; <i>len</i> bytes from the given byte array are written.
* Writing starts at position {@code pos} in the {@code BLOB}
* value; {@code length} bytes from the given byte array are written.
*
* @param pos the position in the <code>BLOB</code> object at which
* to start writing. The first position is <code>1</code>;
* must not be less than <code>1</code> nor greater than
* the length of this <code>SerialBlob</code> object.
* @param bytes the array of bytes to be written to the <code>BLOB</code>
* @param pos the position in the {@code BLOB} object at which
* to start writing. The first position is {@code 1};
* must not be less than {@code 1} nor greater than
* the length+1 of this {@code SerialBlob} object.
* @param bytes the array of bytes to be written to the {@code BLOB}
* value
* @param offset the offset in the <code>byte</code> array at which
* to start reading the bytes. The first offset position is
* <code>0</code>; must not be less than <code>0</code> nor greater
* than the length of the <code>byte</code> array
* @param offset the offset into the array {@code byte}s at which
* to start reading the bytes to be set. The first offset position is
* {@code 0}; must not be less than {@code 0} nor greater
* than the length of the array {@code byte}s
* @param length the number of bytes to be written to the
* <code>BLOB</code> value from the array of bytes <i>bytes</i>.
* {@code BLOB} value from the array of bytes {@code byte}s
*
* @return the number of bytes written
* @throws SerialException if there is an error accessing the
* <code>BLOB</code> value; if an invalid position is set; if an
* invalid offset value is set; if number of bytes to be written
* is greater than the <code>SerialBlob</code> length; or the combined
* values of the length and offset is greater than the Blob buffer;
* {@code BLOB} value; if an invalid position is set; if an
* invalid offset value is set; or the combined values of the
* {@code length} and {@code offset} is greater than the length of
* {@code byte}s;
* if {@code free} had previously been called on this object
* @throws SQLException if there is an error accessing the <code>BLOB</code>
* @throws SQLException if there is an error accessing the {@code BLOB}
* value from the database.
* @see #getBytes
*/
@@ -361,26 +360,34 @@ public int setBytes(long pos, byte[] bytes, int offset, int length)
throw new SerialException("Invalid offset in byte array set");
}

if (pos < 1 || pos > this.length()) {
throw new SerialException("Invalid position in BLOB object set");
if (length < 0) {
throw new SerialException("Invalid arguments: length cannot be "
+ "negative");
}

if ((long)(length) > origLen) {
throw new SerialException("Buffer is not sufficient to hold the value");
if (pos < 1 || pos > len + 1) {
throw new SerialException("Invalid position in BLOB object set");
}

if ((length + offset) > bytes.length) {
if (length > bytes.length - offset) {
throw new SerialException("Invalid OffSet. Cannot have combined offset " +
"and length that is greater that the Blob buffer");
"and length that is greater than the length of bytes");
}

if (pos - 1 + length > Integer.MAX_VALUE) {
throw new SerialException("Invalid length. Cannot have combined pos " +
"and length that is greater than Integer.MAX_VALUE");
}

int i = 0;
pos--; // correct to array indexing
while ( i < length || (offset + i +1) < (bytes.length-offset) ) {
this.buf[(int)pos + i] = bytes[offset + i ];
i++;
if (pos + length > len) {
len = pos + length;
byte[] newbuf = new byte[(int)len];
System.arraycopy(buf, 0, newbuf, 0, (int)pos);
buf = newbuf;
}
return i;
System.arraycopy(bytes, offset, buf, (int)pos, length);
return length;
}

/**
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 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
@@ -361,81 +361,86 @@ public long position(Clob searchStr, long start)
}

/**
* Writes the given Java <code>String</code> to the <code>CLOB</code>
* value that this <code>SerialClob</code> object represents, at the position
* <code>pos</code>.
* Writes the given Java {@code String} to the {@code CLOB}
* value that this {@code SerialClob} object represents, at the position
* {@code pos}.
*
* @param pos the position at which to start writing to the <code>CLOB</code>
* value that this <code>SerialClob</code> object represents; the first
* position is <code>1</code>; must not be less than <code>1</code> nor
* greater than the length of this <code>SerialClob</code> object
* @param str the string to be written to the <code>CLOB</code>
* value that this <code>SerialClob</code> object represents
* @param pos the position at which to start writing to the {@code CLOB}
* value that this {@code SerialClob} object represents; the first
* position is {@code 1}; must not be less than {@code 1} nor
* greater than the length+1 of this {@code SerialClob} object
* @param str the string to be written to the {@code CLOB}
* value that this {@code SerialClob} object represents
* @return the number of characters written
* @throws SerialException if there is an error accessing the
* <code>CLOB</code> value; if an invalid position is set; if an
* invalid offset value is set; if number of bytes to be written
* is greater than the <code>SerialClob</code> length; or the combined
* values of the length and offset is greater than the Clob buffer;
* {@code CLOB} value; if an invalid position is set;
* if the {@code free} method had been previously called on this object
*/
public int setString(long pos, String str) throws SerialException {
return (setString(pos, str, 0, str.length()));
}

/**
* Writes <code>len</code> characters of <code>str</code>, starting
* at character <code>offset</code>, to the <code>CLOB</code> value
* that this <code>Clob</code> represents.
* Writes {@code len} characters of {@code str}, starting
* at character {@code offset}, to the {@code CLOB} value
* that this {@code Clob} represents.
*
* @param pos the position at which to start writing to the <code>CLOB</code>
* value that this <code>SerialClob</code> object represents; the first
* position is <code>1</code>; must not be less than <code>1</code> nor
* greater than the length of this <code>SerialClob</code> object
* @param str the string to be written to the <code>CLOB</code>
* value that this <code>Clob</code> object represents
* @param offset the offset into <code>str</code> to start reading
* @param pos the position at which to start writing to the {@code CLOB}
* value that this {@code SerialClob} object represents; the first
* position is {@code 1}; must not be less than {@code 1} nor
* greater than the length+1 of this {@code SerialClob} object
* @param str the string to be written to the {@code CLOB}
* value that this {@code Clob} object represents
* @param offset the offset into {@code str} to start reading
* the characters to be written
* @param length the number of characters to be written
* @return the number of characters written
* @throws SerialException if there is an error accessing the
* <code>CLOB</code> value; if an invalid position is set; if an
* invalid offset value is set; if number of bytes to be written
* is greater than the <code>SerialClob</code> length; or the combined
* values of the length and offset is greater than the Clob buffer;
* {@code CLOB} value; if an invalid position is set; if an
* invalid offset value is set; or the combined values of the
* {@code length} and {@code offset} is greater than the length of
* {@code str};
* if the {@code free} method had been previously called on this object
*/
public int setString(long pos, String str, int offset, int length)
throws SerialException {
isValid();
String temp = str.substring(offset);
char cPattern[] = temp.toCharArray();

if (offset < 0 || offset > str.length()) {
throw new SerialException("Invalid offset in byte array set");
throw new SerialException("Invalid offset in String object set");
}

if (pos < 1 || pos > this.length()) {
throw new SerialException("Invalid position in Clob object set");
if (length < 0) {
throw new SerialException("Invalid arguments: length cannot be "
+ "negative");
}

if ((long)(length) > origLen) {
throw new SerialException("Buffer is not sufficient to hold the value");
if (pos < 1 || pos > len + 1) {
throw new SerialException("Invalid position in Clob object set");
}

if ((length + offset) > str.length()) {
// need check to ensure length + offset !> bytes.length
if (length > str.length() - offset) {
// need check to ensure length + offset !> str.length
throw new SerialException("Invalid OffSet. Cannot have combined offset " +
" and length that is greater that the Blob buffer");
" and length that is greater than the length of str");
}

if (pos - 1 + length > Integer.MAX_VALUE) {
throw new SerialException("Invalid length. Cannot have combined pos " +
"and length that is greater than Integer.MAX_VALUE");
}

int i = 0;
pos--; //values in the array are at position one less
while ( i < length || (offset + i +1) < (str.length() - offset ) ) {
this.buf[(int)pos + i ] = cPattern[offset + i ];
i++;
if (pos + length > len) {
len = pos + length;
char[] newbuf = new char[(int)len];
System.arraycopy(buf, 0, newbuf, 0, (int)pos);
buf = newbuf;
}
return i;

String temp = str.substring(offset, offset + length);
char cPattern[] = temp.toCharArray();
System.arraycopy(cPattern, 0, buf, (int)pos, length);
return length;
}

/**
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 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
@@ -396,4 +396,78 @@ public void test30() throws Exception {
long pos = sb.position(pattern, 2);
assertEquals(pos, expectedPos);
}

/*
* Validate that setBytes will properly write a set of bytes to the
* specified location in the SerialBlob and the correct count is returned
* for bytes written (writePos - 1 + diff.length > sb.length() &&
* writePos - 1 + bytesToWrite <= sb.length())
*/
@Test
public void test31() throws Exception {
int writePos = 5;
int bytesToWrite = 1;
byte[] diff = new byte[]{7, 8, 9};
byte[] expected = new byte[]{1, 2, 3, 4, 7};
SerialBlob sb = new SerialBlob(bytes);
int written = sb.setBytes(writePos, diff, 0, bytesToWrite);
assertEquals(written, bytesToWrite);
assertEquals(sb.getBytes(1, (int) sb.length()), expected);
}

/*
* Validate that setBytes will properly write a set of bytes to the
* specified location in the SerialBlob and the correct count is returned
* for bytes written (writePos - 1 + bytesToWrite > sb.length())
*/
@Test
public void test32() throws Exception {
int writePos = 5;
int bytesToWrite = 2;
byte[] diff = new byte[]{7, 8, 9, 0};
byte[] expected = new byte[]{1, 2, 3, 4, 8, 9};
SerialBlob sb = new SerialBlob(bytes);
int written = sb.setBytes(writePos, diff, 1, bytesToWrite);
assertEquals(written, bytesToWrite);
assertEquals(sb.getBytes(1, (int) sb.length()), expected);
}

/*
* Validate that setBytes will properly write a set of bytes to the
* specified location in the SerialBlob and the correct count is returned
* for bytes written (writePos == sb.length() + 1)
*/
@Test
public void test33() throws Exception {
int writePos = 6;
int bytesToWrite = 3;
byte[] diff = new byte[]{7, 8, 9, 0};
byte[] expected = new byte[]{1, 2, 3, 4, 5, 8, 9, 0};
SerialBlob sb = new SerialBlob(bytes);
int written = sb.setBytes(writePos, diff, 1, bytesToWrite);
assertEquals(written, bytesToWrite);
assertEquals(sb.getBytes(1, (int) sb.length()), expected);
}

/*
* Validate a SerialException is thrown if length < 0 for setBytes
*/
@Test(expectedExceptions = SerialException.class)
public void test34() throws Exception {
int length = -1;
SerialBlob sb = new SerialBlob(bytes);
int written = sb.setBytes(1, new byte[]{1}, 1, length);
}

/*
* Validate a SerialException is thrown if length + offset >
* Integer.MAX_VALUE for setBytes
*/
@Test(expectedExceptions = SerialException.class)
public void test35() throws Exception {
int offset = 1;
int length = Integer.MAX_VALUE;
SerialBlob sb = new SerialBlob(bytes);
int written = sb.setBytes(1, new byte[]{1, 2, 3}, offset, length);
}
}

1 comment on commit 63b9f8c

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on 63b9f8c Oct 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.