Skip to content
This repository was archived by the owner on Sep 19, 2021. It is now read-only.

Commit 98e7d23

Browse files
authored
Fixing Uuid Parse Error (#66)
In Uuid, ids are 32 bit unsigned integers. As Java does not supported unsigned integers, when converting to a string, the 32 bit integer is converted to a long so that it can be written to a string as a positive integer (using all 32 bits). When converting from a string to a Uuid, the integer value is not handled correctly as values that would be acceptable as a 32 bit unsigned integer fail to be parsed as a 32 bit signed integer. If the id value of a Uuid is 0xFFFFFFFF and is converted to the string 4294967295. When 4294967295 is parsed, it will fail as it is not expressible as a 32 bit signed integer. Parsing needs to parse the unsigned integer and convert and store the bit pattern correctly in a signed integer. Closes #62
1 parent 9994383 commit 98e7d23

File tree

4 files changed

+39
-14
lines changed

4 files changed

+39
-14
lines changed

src/codeu/chat/RelayMain.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ private static void loadTeamInfo(Server relay, String file) {
137137
// this line that it is not worth trying to handle ahead of time.
138138
// So instead just try to parse it and catch any exception.
139139

140-
final Uuid id = Uuid.fromString(tokens[0].trim());
140+
final Uuid id = Uuid.parse(tokens[0].trim());
141141
final byte[] secret = Secret.parse(tokens[1].trim());
142142

143143
relay.addTeam(id, secret);

src/codeu/chat/ServerMain.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,16 @@ public static void main(String[] args) {
4646

4747
LOG.info("============================= START OF LOG =============================");
4848

49-
final Uuid id = Uuid.fromString(args[0]);
49+
final int myPort = Integer.parseInt(args[2]);
5050
final byte[] secret = Secret.parse(args[1]);
5151

52-
final int myPort = Integer.parseInt(args[2]);
52+
Uuid id = null;
53+
try {
54+
id = Uuid.parse(args[0]);
55+
} catch (IOException ex) {
56+
System.out.println("Invalid id - shutting down server");
57+
System.exit(1);
58+
}
5359

5460
// This is the directory where it is safe to store data accross runs
5561
// of the server.

src/codeu/chat/util/Uuid.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -179,23 +179,29 @@ private static void buildString(Uuid current, StringBuilder build) {
179179
}
180180
}
181181

182-
// FROM STRING
182+
// Parse
183183
//
184184
// Create a uuid from a sting.
185-
public static Uuid fromString(String string) {
186-
return fromString(null, string.split("\\."), 0);
185+
public static Uuid parse(String string) throws IOException {
186+
return parse(null, string.split("\\."), 0);
187187
}
188188

189-
private static Uuid fromString(final Uuid root, String[] tokens, int index) {
189+
private static Uuid parse(final Uuid root, String[] tokens, int index) throws IOException {
190190

191-
final int id = Integer.parseInt(tokens[index]);
191+
final long id = Long.parseLong(tokens[index]);
192192

193-
final Uuid link = new Uuid(root, id);
193+
if ((id >> 32) != 0) {
194+
throw new IOException(String.format(
195+
"ID value '%s' is too large to be an unsigned 32 bit integer",
196+
tokens[index]));
197+
}
198+
199+
final Uuid link = new Uuid(root, (int)(id & 0xFFFFFFFF));
194200

195201
final int nextIndex = index + 1;
196202

197203
return nextIndex < tokens.length ?
198-
fromString(link, tokens, nextIndex) :
204+
parse(link, tokens, nextIndex) :
199205
link;
200206
}
201207
}

test/codeu/chat/util/UuidTest.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package codeu.chat.util;
1616

17+
import java.io.IOException;
1718
import static org.junit.Assert.*;
1819
import org.junit.Test;
1920

@@ -103,21 +104,21 @@ public void testRootEqualNot() {
103104
}
104105

105106
@Test
106-
public void testValidSingleLink() {
107+
public void testValidSingleLink() throws IOException {
107108

108109
final String string = "100";
109-
final Uuid id = Uuid.fromString(string);
110+
final Uuid id = Uuid.parse(string);
110111

111112
assertNotNull(id);
112113
assertNull(id.root());
113114
assertEquals(id.id(), 100);
114115
}
115116

116117
@Test
117-
public void testValidMultiLink() {
118+
public void testValidMultiLink() throws IOException {
118119

119120
final String string = "100.200";
120-
final Uuid id = Uuid.fromString(string);
121+
final Uuid id = Uuid.parse(string);
121122

122123
assertNotNull(id);
123124
assertNotNull(id.root());
@@ -126,4 +127,16 @@ public void testValidMultiLink() {
126127
assertEquals(id.id(), 200);
127128
assertEquals(id.root().id(), 100);
128129
}
130+
131+
@Test
132+
public void testLargeId() throws IOException {
133+
134+
// Use a id value that would be too large for Integer.parseInt to handle
135+
// but would still parse if we could use unsigned integers.
136+
final String string = Long.toString(0xFFFFFFFFL);
137+
final Uuid id = Uuid.parse(string);
138+
139+
assertNotNull(id);
140+
assertEquals(id.id(), 0xFFFFFFFF);
141+
}
129142
}

0 commit comments

Comments
 (0)