Error while unserializing ImageCaptcha object in Java 1.6

Description

When the ImageCaptcha is unserializing it generates the exception:
java.io.StreamCorruptedException: unexpected end of block data
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1945)
at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:480)
at com.octo.captcha.image.ImageCaptcha.readObject(ImageCaptcha.java:100)

The bug could be repeted using below code:
{{{
// assumption: captcha is an ImageCaptcha instance
ByteArrayOutputStream arrayOutput = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(arrayOutput);
out.writeObject(captcha);
out.flush();
arrayOutput.close();

ObjectInputStream in = new ObjectInputStream(new
ByteArrayInputStream(arrayOutput.toByteArray()));
Captcha captchaUnserialized = (Captcha) in.readObject();
}}}

Environment

Java1.6 and Tomcat6

Activity

Show:
Radek
September 11, 2007, 11:26 AM

I set the priority to critical as it doesn't allow me to distribute the application on tomcat cluster using ehcache.

Radek
October 25, 2007, 4:53 PM

It seems that above issue appears only if challenge was disposed before the serialization of captcha happaned. We found out that replication with synchronous ehcache works but anynchronous doesn't. The reason is because in AbstractCaptchaService.getChallengeForID() method calls dsiposeChallenge() on captcha object. It seems that ImageCaptcha.writeObject() serialize entire object only if challenge != null.
{{{
// from ImageCaptcha class:
//use jpeg encoding
private void writeObject(java.io.ObjectOutputStream out)
throws IOException {

if (this.challenge != null) {
out.defaultWriteObject();
// a jpeg encoder
JPEGImageEncoder jpegEncoder =
JPEGCodec.createJPEGEncoder(out);
jpegEncoder.encode(this.challenge);
}
}
}}}

As a workaroung to this problem we changed disposeChallenge method to set a small BuffereImage() object which shouldn't cause any drop in performance but at least correctly replicates. Replicating entire challenge images on cluster doesn't seem like a good idea.

This bug should be fixed in such a way that ImageCaptcha is replicated even if challenge is equal null.

Improved testing case:
{{{
// assumption: captcha is an ImageCaptcha instance
captcha.disposeChallenge(); // dispose challenge image first
ByteArrayOutputStream arrayOutput = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(arrayOutput);
out.writeObject(captcha);
out.flush();
arrayOutput.close();

ObjectInputStream in = new ObjectInputStream(new
ByteArrayInputStream(arrayOutput.toByteArray()));
Captcha captchaUnserialized = (Captcha) in.readObject();
}}}

AntoineV
November 7, 2007, 11:07 AM

Fixed, thanks for this meaningful bug report

Fixed

Assignee

AntoineV

Reporter

Radek

Labels

None

Fix versions

Affects versions

Priority

Critical
Configure