8153490: Cannot setBytes() if incoming buffer's length is bigger than number of elements we want to insert.
Reviewed-by: lancea
This commit is contained in:
parent
cb989cf3a1
commit
63b9f8c0da
src/java.sql.rowset/share/classes/javax/sql/rowset/serial
test/jdk/javax/sql/testng/test/rowset/serial
@ -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 class SerialBlob implements Blob, Serializable, Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class SerialBlob implements Blob, Serializable, Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class SerialBlob implements Blob, Serializable, Cloneable {
|
||||
throw new SerialException("Invalid offset in byte array set");
|
||||
}
|
||||
|
||||
if (pos < 1 || pos > this.length()) {
|
||||
if (length < 0) {
|
||||
throw new SerialException("Invalid arguments: length cannot be "
|
||||
+ "negative");
|
||||
}
|
||||
|
||||
if (pos < 1 || pos > len + 1) {
|
||||
throw new SerialException("Invalid position in BLOB object set");
|
||||
}
|
||||
|
||||
if ((long)(length) > origLen) {
|
||||
throw new SerialException("Buffer is not sufficient to hold the value");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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 - 1 + length > Integer.MAX_VALUE) {
|
||||
throw new SerialException("Invalid length. Cannot have combined pos " +
|
||||
"and length that is greater than Integer.MAX_VALUE");
|
||||
}
|
||||
return i;
|
||||
|
||||
pos--; // correct to array indexing
|
||||
if (pos + length > len) {
|
||||
len = pos + length;
|
||||
byte[] newbuf = new byte[(int)len];
|
||||
System.arraycopy(buf, 0, newbuf, 0, (int)pos);
|
||||
buf = newbuf;
|
||||
}
|
||||
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,22 +361,19 @@ public class SerialClob implements Clob, Serializable, Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
@ -384,58 +381,66 @@ public class SerialClob implements Clob, Serializable, Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()) {
|
||||
if (length < 0) {
|
||||
throw new SerialException("Invalid arguments: length cannot be "
|
||||
+ "negative");
|
||||
}
|
||||
|
||||
if (pos < 1 || pos > len + 1) {
|
||||
throw new SerialException("Invalid position in Clob object set");
|
||||
}
|
||||
|
||||
if ((long)(length) > origLen) {
|
||||
throw new SerialException("Buffer is not sufficient to hold the value");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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 - 1 + length > Integer.MAX_VALUE) {
|
||||
throw new SerialException("Invalid length. Cannot have combined pos " +
|
||||
"and length that is greater than Integer.MAX_VALUE");
|
||||
}
|
||||
return i;
|
||||
|
||||
pos--; //values in the array are at position one less
|
||||
if (pos + length > len) {
|
||||
len = pos + length;
|
||||
char[] newbuf = new char[(int)len];
|
||||
System.arraycopy(buf, 0, newbuf, 0, (int)pos);
|
||||
buf = newbuf;
|
||||
}
|
||||
|
||||
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 class SerialBlobTests extends BaseTest {
|
||||
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,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
|
||||
@ -407,18 +407,21 @@ public class SerialClobTests extends BaseTest {
|
||||
|
||||
/*
|
||||
* Check that setString() updates the appropriate characters in the
|
||||
* SerialClob
|
||||
* SerialClob (writePos - 1 + val1.length() - offset > sc.length() &&
|
||||
* writePos - 1 + expectedWritten <= sc.length())
|
||||
*/
|
||||
@Test(enabled = false)
|
||||
@Test
|
||||
public void test32() throws Exception {
|
||||
int writePos = 10;
|
||||
int offset = 7;
|
||||
int expectedWritten = 9;
|
||||
String val = "Hi, I am Catwoman!!!!!!";
|
||||
String val1 = "Hahaha the Joker, who are you?!";
|
||||
String expected = "Hi, I am the Joker!";
|
||||
String expected = "Hi, I am the Joker!!!!!";
|
||||
SerialClob sc = new SerialClob(val.toCharArray());
|
||||
int written = sc.setString(10, val1, 8, expectedWritten+1);
|
||||
int written = sc.setString(writePos, val1, offset, expectedWritten);
|
||||
assertEquals(written, expectedWritten);
|
||||
|
||||
assertEquals(sc.getSubString(1, (int) sc.length()), expected);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -496,4 +499,74 @@ public class SerialClobTests extends BaseTest {
|
||||
SerialClob sc2 = serializeDeserializeObject(sc);
|
||||
assertTrue(sc.equals(sc2), "SerialClobs not equal");
|
||||
}
|
||||
|
||||
/*
|
||||
* Check calling setString() with offset > val1.length() throws a
|
||||
* SerialException
|
||||
*/
|
||||
@Test(expectedExceptions = SerialException.class)
|
||||
public void test39() throws Exception {
|
||||
String val1 = "hello";
|
||||
int offset = val1.length() + 1;
|
||||
SerialClob sc = new SerialClob(chars);
|
||||
sc.setString(1, val1, offset, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that setString() updates the appropriate characters in the
|
||||
* SerialClob (writePos - 1 + expectedWritten > sc.length())
|
||||
*/
|
||||
@Test
|
||||
public void test40() throws Exception {
|
||||
int writePos = 13;
|
||||
int offset = 7;
|
||||
int expectedWritten = 24;
|
||||
String val = "Hello, I am Bruce Wayne";
|
||||
String val1 = "Hahaha the Joker, who are you?!";
|
||||
String expected = "Hello, I am the Joker, who are you?!";
|
||||
SerialClob sc = new SerialClob(val.toCharArray());
|
||||
int written = sc.setString(writePos, val1, offset, expectedWritten);
|
||||
assertEquals(written, expectedWritten);
|
||||
assertEquals(sc.getSubString(1, (int) sc.length()), expected);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that setString() updates the appropriate characters in the
|
||||
* SerialClob (writePos == sc.length() + 1)
|
||||
*/
|
||||
@Test
|
||||
public void test41() throws Exception {
|
||||
int writePos = 10;
|
||||
int offset = 7;
|
||||
int expectedWritten = 10;
|
||||
String val = "Hi, I am ";
|
||||
String val1 = "Hahaha the Joker!";
|
||||
String expected = "Hi, I am the Joker!";
|
||||
SerialClob sc = new SerialClob(val.toCharArray());
|
||||
int written = sc.setString(writePos, val1, offset, expectedWritten);
|
||||
assertEquals(written, expectedWritten);
|
||||
assertEquals(sc.getSubString(1, (int) sc.length()), expected);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate a SerialException is thrown if length < 0 for setString
|
||||
*/
|
||||
@Test(expectedExceptions = SerialException.class)
|
||||
public void test42() throws Exception {
|
||||
int length = -1;
|
||||
SerialClob sc = new SerialClob(chars);
|
||||
int written = sc.setString(1, "hello", 1, length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate a SerialException is thrown if length + offset >
|
||||
* Integer.MAX_VALUE for setString
|
||||
*/
|
||||
@Test(expectedExceptions = SerialException.class)
|
||||
public void test43() throws Exception {
|
||||
int offset = 1;
|
||||
int length = Integer.MAX_VALUE;
|
||||
SerialClob sc = new SerialClob(chars);
|
||||
int written = sc.setString(1, "hello", offset, length);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user