From 0bb8b6cd190e5ba22de761fb779859a0f3335f91 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 30 Sep 2019 15:55:58 +0200 Subject: [PATCH] Fix exception when a message line is longer than 64k --- .../org/jboss/fuse/mvnd/daemon/Message.java | 119 ++++++++++++++++-- 1 file changed, 107 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/jboss/fuse/mvnd/daemon/Message.java b/src/main/java/org/jboss/fuse/mvnd/daemon/Message.java index 30341038..eb20c13b 100644 --- a/src/main/java/org/jboss/fuse/mvnd/daemon/Message.java +++ b/src/main/java/org/jboss/fuse/mvnd/daemon/Message.java @@ -19,6 +19,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.IOException; +import java.io.UTFDataFormatException; import java.util.ArrayList; import java.util.List; @@ -149,44 +150,44 @@ public abstract class Message { private BuildRequest readBuildRequest(DataInputStream input) throws IOException { List args = readStringList(input); - String workingDir = input.readUTF(); - String projectDir = input.readUTF(); + String workingDir = readUTF(input); + String projectDir = readUTF(input); return new BuildRequest(args, workingDir, projectDir); } private void writeBuildRequest(DataOutputStream output, BuildRequest value) throws IOException { writeStringList(output, value.args); - output.writeUTF(value.workingDir); - output.writeUTF(value.projectDir); + writeUTF(output, value.workingDir); + writeUTF(output, value.projectDir); } private BuildEvent readBuildEvent(DataInputStream input) throws IOException { BuildEvent.Type type = BuildEvent.Type.values()[input.read()]; - String projectId = input.readUTF(); - String display = input.readUTF(); + String projectId = readUTF(input); + String display = readUTF(input); return new BuildEvent(type, projectId, display); } private void writeBuildEvent(DataOutputStream output, BuildEvent value) throws IOException { output.write(value.type.ordinal()); - output.writeUTF(value.projectId); - output.writeUTF(value.display); + writeUTF(output, value.projectId); + writeUTF(output, value.display); } private BuildMessage readBuildMessage(DataInputStream input) throws IOException { - String message = input.readUTF(); + String message = readUTF(input); return new BuildMessage(message); } private void writeBuildMessage(DataOutputStream output, BuildMessage value) throws IOException { - output.writeUTF(value.message); + writeUTF(output, value.message); } private List readStringList(DataInputStream input) throws IOException { ArrayList l = new ArrayList<>(); int nb = input.readInt(); for (int i = 0; i < nb; i++) { - l.add(input.readUTF()); + l.add(readUTF(input)); } return l; } @@ -194,7 +195,101 @@ public abstract class Message { private void writeStringList(DataOutputStream output, List value) throws IOException { output.writeInt(value.size()); for (String v : value) { - output.writeUTF(v); + writeUTF(output, v); + } + } + + private static final String INVALID_BYTE = "Invalid byte"; + private static final int UTF_BUFS_CHAR_CNT = 256; + private static final int UTF_BUFS_BYTE_CNT = UTF_BUFS_CHAR_CNT * 3; + final byte[] byteBuf = new byte[UTF_BUFS_BYTE_CNT]; + + String readUTF(DataInputStream input) throws IOException { + int len = input.readInt(); + final char[] chars = new char[len]; + int i = 0, cnt = 0, charIdx = 0; + while (charIdx < len) { + if (i == cnt) { + cnt = input.read(byteBuf, 0, Math.min(UTF_BUFS_BYTE_CNT, len - charIdx)); + if (cnt < 0) { + throw new EOFException(); + } + i = 0; + } + final int a = byteBuf[i++] & 0xff; + if (a < 0x80) { + // low bit clear + chars[charIdx ++] = (char) a; + } else if (a < 0xc0) { + throw new UTFDataFormatException(INVALID_BYTE); + } else if (a < 0xe0) { + if (i == cnt) { + cnt = input.read(byteBuf, 0, Math.min(UTF_BUFS_BYTE_CNT, len - charIdx)); + if (cnt < 0) { + throw new EOFException(); + } + i = 0; + } + final int b = byteBuf[i ++] & 0xff; + if ((b & 0xc0) != 0x80) { + throw new UTFDataFormatException(INVALID_BYTE); + } + chars[charIdx ++] = (char) ((a & 0x1f) << 6 | b & 0x3f); + } else if (a < 0xf0) { + if (i == cnt) { + cnt = input.read(byteBuf, 0, Math.min(UTF_BUFS_BYTE_CNT, len - charIdx)); + if (cnt < 0) { + throw new EOFException(); + } + i = 0; + } + final int b = byteBuf[i ++] & 0xff; + if ((b & 0xc0) != 0x80) { + throw new UTFDataFormatException(INVALID_BYTE); + } + if (i == cnt) { + cnt = input.read(byteBuf, 0, Math.min(UTF_BUFS_BYTE_CNT, len - charIdx)); + if (cnt < 0) { + throw new EOFException(); + } + i = 0; + } + final int c = byteBuf[i ++] & 0xff; + if ((c & 0xc0) != 0x80) { + throw new UTFDataFormatException(INVALID_BYTE); + } + chars[charIdx ++] = (char) ((a & 0x0f) << 12 | (b & 0x3f) << 6 | c & 0x3f); + } else { + throw new UTFDataFormatException(INVALID_BYTE); + } + } + return String.valueOf(chars); + } + + void writeUTF(DataOutputStream output, String s) throws IOException { + final int length = s.length(); + output.writeInt(length); + int strIdx = 0; + int byteIdx = 0; + while (strIdx < length) { + final char c = s.charAt(strIdx ++); + if (c > 0 && c <= 0x7f) { + byteBuf[byteIdx ++] = (byte) c; + } else if (c <= 0x07ff) { + byteBuf[byteIdx ++] = (byte)(0xc0 | 0x1f & c >> 6); + byteBuf[byteIdx ++] = (byte)(0x80 | 0x3f & c); + } else { + byteBuf[byteIdx ++] = (byte)(0xe0 | 0x0f & c >> 12); + byteBuf[byteIdx ++] = (byte)(0x80 | 0x3f & c >> 6); + byteBuf[byteIdx ++] = (byte)(0x80 | 0x3f & c); + } + if (byteIdx > UTF_BUFS_BYTE_CNT - 4) { + output.write(byteBuf, 0, byteIdx); + byteIdx = 0; + } + } + if (byteIdx > 0) { + output.write(byteBuf, 0, byteIdx); } }