From 5f92d0d2de6aec6ad6ebe79d0dbb90740bfcd374 Mon Sep 17 00:00:00 2001 From: Hannes Braun Date: Sat, 22 Jul 2023 16:20:27 +0200 Subject: [PATCH] Require strings sent via RoboViz Draw to be UTF-8 encoded --- examples/java/RVDraw.java | 65 ++++++++++++------- .../rv/comm/drawing/commands/Command.java | 14 ++-- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/examples/java/RVDraw.java b/examples/java/RVDraw.java index 64be3711..0b1b0253 100644 --- a/examples/java/RVDraw.java +++ b/examples/java/RVDraw.java @@ -16,6 +16,7 @@ import java.awt.Color; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.Locale; /** @@ -28,7 +29,7 @@ public class RVDraw /** Writes a float formatted in 6 ASCII characters to a buffer */ public static void writeFloatToBuffer(ByteBuffer buf, float value) { - buf.put(String.format(Locale.US, "%6f", value).substring(0, 6).getBytes()); + buf.put(String.format(Locale.US, "%6f", value).substring(0, 6).getBytes(StandardCharsets.UTF_8)); } /** Writes RGB values of a Color object to a buffer */ @@ -42,9 +43,9 @@ public static void writeColorToBuffer(ByteBuffer buf, Color color, boolean alpha } /** Writes a string to a buffer */ - public static void writeStringToBuffer(ByteBuffer buf, String s) + public static void writeStringToBuffer(ByteBuffer buf, byte[] s) { - buf.put(s.getBytes()); + buf.put(s); buf.put((byte) 0); } @@ -64,13 +65,18 @@ public static float readFloatFromBuffer(ByteBuffer buf) */ public static byte[] newBufferSwap(String group) { - int numBytes = 3 + ((group != null) ? group.length() : 0); + int numBytes = 3; + byte[] groupEncoded = null; + if (group != null) { + groupEncoded = group.getBytes(StandardCharsets.UTF_8); + numBytes += groupEncoded.length; + } ByteBuffer buf = ByteBuffer.allocate(numBytes); buf.put((byte) 0); buf.put((byte) 0); if (group != null) - buf.put(group.getBytes()); + buf.put(groupEncoded); buf.put((byte) 0); return buf.array(); @@ -92,7 +98,8 @@ public static byte[] newBufferSwap(String group) */ public static byte[] newCircle(float[] center, float radius, float thickness, Color color, String group) { - int numBytes = 30 + group.length(); + byte[] groupEncoded = group.getBytes(StandardCharsets.UTF_8); + int numBytes = 30 + groupEncoded.length; ByteBuffer buf = ByteBuffer.allocate(numBytes); buf.put((byte) 1); @@ -102,7 +109,7 @@ public static byte[] newCircle(float[] center, float radius, float thickness, Co writeFloatToBuffer(buf, radius); writeFloatToBuffer(buf, thickness); writeColorToBuffer(buf, color, false); - writeStringToBuffer(buf, group); + writeStringToBuffer(buf, groupEncoded); return buf.array(); } @@ -123,7 +130,8 @@ public static byte[] newCircle(float[] center, float radius, float thickness, Co */ public static byte[] newLine(float[] a, float[] b, float thickness, Color color, String group) { - int numBytes = 48 + group.length(); + byte[] groupEncoded = group.getBytes(StandardCharsets.UTF_8); + int numBytes = 48 + groupEncoded.length; ByteBuffer buf = ByteBuffer.allocate(numBytes); buf.put((byte) 1); @@ -136,7 +144,7 @@ public static byte[] newLine(float[] a, float[] b, float thickness, Color color, writeFloatToBuffer(buf, b[2]); writeFloatToBuffer(buf, thickness); writeColorToBuffer(buf, color, false); - writeStringToBuffer(buf, group); + writeStringToBuffer(buf, groupEncoded); return buf.array(); } @@ -155,7 +163,8 @@ public static byte[] newLine(float[] a, float[] b, float thickness, Color color, */ public static byte[] newPoint(float[] p, float size, Color color, String group) { - int numBytes = 30 + group.length(); + byte[] groupEncoded = group.getBytes(StandardCharsets.UTF_8); + int numBytes = 30 + groupEncoded.length; ByteBuffer buf = ByteBuffer.allocate(numBytes); buf.put((byte) 1); @@ -165,7 +174,7 @@ public static byte[] newPoint(float[] p, float size, Color color, String group) writeFloatToBuffer(buf, p[2]); writeFloatToBuffer(buf, size); writeColorToBuffer(buf, color, false); - writeStringToBuffer(buf, group); + writeStringToBuffer(buf, groupEncoded); return buf.array(); } @@ -184,7 +193,8 @@ public static byte[] newPoint(float[] p, float size, Color color, String group) */ public static byte[] newSphere(float[] p, float radius, Color color, String group) { - int numBytes = 30 + group.length(); + byte[] groupEncoded = group.getBytes(StandardCharsets.UTF_8); + int numBytes = 30 + groupEncoded.length; ByteBuffer buf = ByteBuffer.allocate(numBytes); buf.put((byte) 1); @@ -194,14 +204,15 @@ public static byte[] newSphere(float[] p, float radius, Color color, String grou writeFloatToBuffer(buf, p[2]); writeFloatToBuffer(buf, radius); writeColorToBuffer(buf, color, false); - writeStringToBuffer(buf, group); + writeStringToBuffer(buf, groupEncoded); return buf.array(); } public static byte[] newPolygon(float[][] v, Color color, String set) { - int numBytes = 18 * v.length + 8 + set.length(); + byte[] setEncoded = set.getBytes(StandardCharsets.UTF_8); + int numBytes = 18 * v.length + 8 + setEncoded.length; ByteBuffer buf = ByteBuffer.allocate(numBytes); @@ -218,20 +229,23 @@ public static byte[] newPolygon(float[][] v, Color color, String set) writeFloatToBuffer(buf, v[i][2]); } - // set.length + 1 bytes - writeStringToBuffer(buf, set); + // setEncoded.length + 1 bytes + writeStringToBuffer(buf, setEncoded); return buf.array(); } public static byte[] newAnnotation(String text, float[] pos, Color color, String set) { + byte[] textEncoded = text.getBytes(StandardCharsets.UTF_8); + byte[] setEncoded = set.getBytes(StandardCharsets.UTF_8); + // header bytes = 2 // pos = 3 floats * 6 bytes per float = 18 // color = 3 - // text = text.length + 1 - // set = set.length + 1 - int numBytes = 25 + text.length() + set.length(); + // text = textEncoded.length + 1 + // set = setEncoded.length + 1 + int numBytes = 25 + textEncoded.length + setEncoded.length; ByteBuffer buf = ByteBuffer.allocate(numBytes); buf.put((byte) 2); @@ -240,8 +254,8 @@ public static byte[] newAnnotation(String text, float[] pos, Color color, String writeFloatToBuffer(buf, pos[1]); writeFloatToBuffer(buf, pos[2]); writeColorToBuffer(buf, color, false); - writeStringToBuffer(buf, text); - writeStringToBuffer(buf, set); + writeStringToBuffer(buf, textEncoded); + writeStringToBuffer(buf, setEncoded); return buf.array(); } @@ -252,7 +266,12 @@ public static byte[] newAnnotation(String text, float[] pos, Color color, String */ public static byte[] newAgentAnnotation(String text, boolean leftTeam, int agentNum, Color color) { - int numBytes = (text == null) ? 3 : 7 + text.length(); + int numBytes = 3; + byte[] textEncoded = null; + if (text != null) { + textEncoded = text.getBytes(StandardCharsets.UTF_8); + numBytes += 4 + textEncoded.length; + } ByteBuffer buf = ByteBuffer.allocate(numBytes); buf.put((byte) 2); @@ -263,7 +282,7 @@ public static byte[] newAgentAnnotation(String text, boolean leftTeam, int agent buf.put((byte) 1); buf.put((byte) (leftTeam ? agentNum - 1 : agentNum + 127)); writeColorToBuffer(buf, color, false); - writeStringToBuffer(buf, text); + writeStringToBuffer(buf, text.getBytes(StandardCharsets.UTF_8)); } return buf.array(); diff --git a/src/main/java/rv/comm/drawing/commands/Command.java b/src/main/java/rv/comm/drawing/commands/Command.java index d2807343..448b4771 100644 --- a/src/main/java/rv/comm/drawing/commands/Command.java +++ b/src/main/java/rv/comm/drawing/commands/Command.java @@ -17,6 +17,7 @@ package rv.comm.drawing.commands; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.Locale; import jsgl.io.ByteUtil; import jsgl.math.vector.Vec3f; @@ -49,11 +50,14 @@ public abstract class Command */ public static String getString(ByteBuffer buf) { - StringBuilder sb = new StringBuilder(); - char c; - while ((c = (char) ByteUtil.uValue(buf.get())) != 0) - sb.append(c); - return sb.toString(); + ByteBuffer str = buf.slice(); + int i = 0; + while (buf.hasRemaining() && buf.get() != 0x00) { + // Count bytes until null + i++; + } + str.limit(i); + return StandardCharsets.UTF_8.decode(str).toString(); } /**