Thread: Bug #558: JDBC InputStream.read() from oid returns incorrect values for negative bytes and really messes up -1

James Lynn (JamesLynn@mail.com) reports a bug with a severity of 2
The lower the number the more severe it is.

Short Description
JDBC InputStream.read() from oid returns incorrect values for negative bytes and really messes up -1

Long Description
Using: PostgresSQL 7.1, jdbc7.1-1.2.jar

After inserting a large object (oid) and trying to select it back out, the InputStream returns incorrect values when
callingread() if the input contained any negative bytes. Example: 0xFE should return 254 but incorrectly returns -2.
Theworst case is when you have 0xFF in the large object: since read() returns -1 rather than 255 and -1 is the signal
thatyou have reached the end of stream so you can never tell if you have a -1. 

There is also a problem with read(byte[],int,int), where the 0xFF just doesn't appear in the data. This may or may not
berelated. 

To set up the example you must use the following create statement:
create table x (f oid);

The example code is Bug.java.

Sample Code
import java.sql.*;
import java.io.*;
import java.util.*;

public class Bug
{
 public static void main(String[] args) throws Exception
 {
 byte[] data={0,-2,-1,0};

 // Test way
  {
  OutputStream out=new FileOutputStream("bug.test");
  out.write(data);
  out.close();

  InputStream in=new FileInputStream("bug.test");
  ByteArrayOutputStream baos=new ByteArrayOutputStream();
  int ch;
  System.out.print("Correct:   ");
  while ((ch=in.read())!=-1) { System.out.print(ch);System.out.print(','); baos.write(ch);}
  System.out.print(ch);System.out.print(';');
  System.out.println(hex(baos.toByteArray()));
  }

 Connection c=null;
 Connection c2=null;
 Class.forName("org.postgresql.Driver");
 String url="jdbc:postgresql://dev002.oakscape.com/shipvis";
 String username="shipvis";
 String password="shipvis";
 c=DriverManager.getConnection(url, username, password);
 c.setAutoCommit(false);

 c.prepareStatement("delete from x").execute();
 c.commit();
 PreparedStatement insert=c.prepareStatement("insert into x (f) values (?)");

 insert.setBinaryStream(1,new ByteArrayInputStream(data),data.length);

 insert.execute();
 c.commit();

 ResultSet rs=c.prepareStatement("select * from x").executeQuery();
 rs.next();

 // One way
  {
  InputStream in=rs.getBinaryStream("f");
  ByteArrayOutputStream baos=new ByteArrayOutputStream();
  int ch;
  System.out.print("Incorrect: ");
  while ((ch=in.read())!=-1) { System.out.print(ch);System.out.print(','); baos.write(ch);}
  System.out.print(ch);System.out.print(';');
  System.out.println(hex(baos.toByteArray()));
  }


 // Another way
  {
  InputStream in=rs.getBinaryStream("f");
  ByteArrayOutputStream baos=new ByteArrayOutputStream();
  byte[] ch=new byte[4];
  int n;
  System.out.print("Odd:       ");
  while ((n=in.read(ch,0,ch.length))!=-1) baos.write(ch,0,n);
  System.out.println(hex(baos.toByteArray()));
  }

 // One way
  {
  InputStream in=rs.getBinaryStream("f");
  ByteArrayOutputStream baos=new ByteArrayOutputStream();
  int ch;
  System.out.print("Know len:  ");
  for (int i=0;i<4;i++) { ch=in.read(); System.out.print(ch);System.out.print(','); baos.write(ch);}
  System.out.print(';');
  System.out.println(hex(baos.toByteArray()));
  }

 c.close();
 }

 static String hex(byte[] data)
 {
 StringBuffer sb=new StringBuffer();
 for (int i=0;i<data.length;i++)
  {
  sb.append(hex((byte)(data[i]>>4))).append(hex(data[i]));
  }
 return sb.toString();
 }
 static char hex(byte data)
 {
 data&=0xF;
 if (data<10) return (char)('0'+data);
 return (char)('A'+data-10);
 }
}


No file was uploaded with this report