Skip to content

Commit

Permalink
fix: fixes problems with missing or multiple delimiters
Browse files Browse the repository at this point in the history
A missing delimiter would cause the parser to hang in a loop and cause
a OOM error, while multiple delimiters would cause the parser to
incorrectly parse the line,

Fixes #20
  • Loading branch information
quintesse committed Feb 21, 2024
1 parent 5e5162f commit 1c63d72
Showing 1 changed file with 25 additions and 15 deletions.
40 changes: 25 additions & 15 deletions src/main/java/org/codejive/properties/PropertiesParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import java.io.Reader;
import java.util.Objects;
import java.util.Spliterators;
import java.util.function.BiFunction;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

Expand Down Expand Up @@ -211,31 +213,36 @@ public Token nextToken() throws IOException {
if (isEof(ch)) {
return null;
}
int oldch = -1;
BiFunction<Integer, Integer, Boolean> isValid = (c, oldc) -> false;
Function<Integer, Boolean> isValid = (c) -> false;
Type nextState = null;
if (state == null) {
if (isCommentChar(ch)) {
state = Type.COMMENT;
isValid = (c, oldc) -> !isEol(c) && !isEof(c);
} else if (isWhitespaceChar(ch)) {
isValid = (c) -> !isEol(c) && !isEof(c);
} else if (isWhitespaceEolChar(ch)) {
state = Type.WHITESPACE;
isValid = (c, oldc) -> isWhitespaceChar(c) && !isEol(oldc);
final AtomicInteger oldc = new AtomicInteger(-1);
isValid = (c) -> isWhitespaceEolChar(c) && !isEol(oldc.getAndSet(c));
} else {
state = Type.KEY;
isValid = (c, oldc) -> !isSeparatorChar(c);
isValid =
(c) ->
!isSeparatorChar(c)
&& !isWhitespaceChar(c)
&& !isEol(c)
&& !isEof(c);
nextState = Type.SEPARATOR;
}
} else if (state == Type.SEPARATOR) {
isValid = (c, oldc) -> isSeparatorChar(c);
final AtomicBoolean once = new AtomicBoolean(true);
isValid = (c) -> isWhitespaceChar(c) || (isSeparatorChar(c) && once.getAndSet(false));
nextState = Type.VALUE;
} else if (state == Type.VALUE) {
isValid = (c, oldc) -> !isEol(c) && !isEof(c);
isValid = (c) -> !isEol(c) && !isEof(c);
}
while (true) {
if (isValid.apply(ch, oldch)) {
if (isValid.apply(ch)) {
addChar(readChar());
oldch = ch;
ch = peekChar();
} else {
String text = string();
Expand Down Expand Up @@ -336,8 +343,7 @@ static String unescape(String escape) {
case '\n':
// Skip any leading whitespace
while (i < (escape.length() - 1)
&& isWhitespaceChar(ch = escape.charAt(i + 1))
&& !isEol(ch)) {
&& isWhitespaceChar(ch = escape.charAt(i + 1))) {
i++;
}
break;
Expand All @@ -353,11 +359,15 @@ && isWhitespaceChar(ch = escape.charAt(i + 1))
}

private static boolean isSeparatorChar(int ch) {
return ch == ' ' || ch == '\t' || ch == '=' || ch == ':';
return ch == '=' || ch == ':';
}

private static boolean isWhitespaceChar(int ch) {
return ch == ' ' || ch == '\t' || ch == '\f' || isEol(ch);
return ch == ' ' || ch == '\t' || ch == '\f';
}

private static boolean isWhitespaceEolChar(int ch) {
return isWhitespaceChar(ch) || isEol(ch);
}

private static boolean isCommentChar(int ch) {
Expand Down

0 comments on commit 1c63d72

Please sign in to comment.