Skip to content

Commit

Permalink
Allows the text reader to fail cleanly when the user attempts to reco…
Browse files Browse the repository at this point in the history
…ver after catching IonException, but recovery is not possible.
  • Loading branch information
tgregg committed Feb 2, 2024
1 parent b338ae0 commit 8dbd001
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 56 deletions.
118 changes: 62 additions & 56 deletions src/main/java/com/amazon/ion/impl/IonReaderTextRawX.java
Original file line number Diff line number Diff line change
Expand Up @@ -1113,64 +1113,70 @@ else if (_current_value_save_point_loaded) {
}
else {
_scanner.save_point_start(_current_value_save_point);
switch (token_type) {
case IonTokenConstsX.TOKEN_UNKNOWN_NUMERIC:
case IonTokenConstsX.TOKEN_INT:
case IonTokenConstsX.TOKEN_BINARY:
case IonTokenConstsX.TOKEN_HEX:
case IonTokenConstsX.TOKEN_FLOAT:
case IonTokenConstsX.TOKEN_DECIMAL:
case IonTokenConstsX.TOKEN_TIMESTAMP:
_value_type = _scanner.load_number(sb);
break;
case IonTokenConstsX.TOKEN_SYMBOL_IDENTIFIER:
_scanner.load_symbol_identifier(sb);
_value_type = IonType.SYMBOL;
break;
case IonTokenConstsX.TOKEN_SYMBOL_OPERATOR:
_scanner.load_symbol_operator(sb);
_value_type = IonType.SYMBOL;
break;
case IonTokenConstsX.TOKEN_SYMBOL_QUOTED:
clob_chars_only = (IonType.CLOB == _value_type);
c = _scanner.load_single_quoted_string(sb, clob_chars_only);
if (c == UnifiedInputStreamX.EOF) {
//String message = "EOF encountered before closing single quote";
//parse_error(message);
_scanner.unexpected_eof();
}
_value_type = IonType.SYMBOL;
break;
case IonTokenConstsX.TOKEN_STRING_DOUBLE_QUOTE:
clob_chars_only = (IonType.CLOB == _value_type);
c = _scanner.load_double_quoted_string(sb, clob_chars_only);
if (c == UnifiedInputStreamX.EOF) {
// String message = "EOF encountered before closing single quote";
// parse_error(message);
_scanner.unexpected_eof();
}
_value_type = IonType.STRING;
break;
case IonTokenConstsX.TOKEN_STRING_TRIPLE_QUOTE:
clob_chars_only = (IonType.CLOB == _value_type);
c = _scanner.load_triple_quoted_string(sb, clob_chars_only);
if (c == UnifiedInputStreamX.EOF) {
//String message = "EOF encountered before closing single quote";
//parse_error(message);
_scanner.unexpected_eof();
try {
switch (token_type) {
case IonTokenConstsX.TOKEN_UNKNOWN_NUMERIC:
case IonTokenConstsX.TOKEN_INT:
case IonTokenConstsX.TOKEN_BINARY:
case IonTokenConstsX.TOKEN_HEX:
case IonTokenConstsX.TOKEN_FLOAT:
case IonTokenConstsX.TOKEN_DECIMAL:
case IonTokenConstsX.TOKEN_TIMESTAMP:
_value_type = _scanner.load_number(sb);
break;
case IonTokenConstsX.TOKEN_SYMBOL_IDENTIFIER:
_scanner.load_symbol_identifier(sb);
_value_type = IonType.SYMBOL;
break;
case IonTokenConstsX.TOKEN_SYMBOL_OPERATOR:
_scanner.load_symbol_operator(sb);
_value_type = IonType.SYMBOL;
break;
case IonTokenConstsX.TOKEN_SYMBOL_QUOTED:
clob_chars_only = (IonType.CLOB == _value_type);
c = _scanner.load_single_quoted_string(sb, clob_chars_only);
if (c == UnifiedInputStreamX.EOF) {
//String message = "EOF encountered before closing single quote";
//parse_error(message);
_scanner.unexpected_eof();
}
_value_type = IonType.SYMBOL;
break;
case IonTokenConstsX.TOKEN_STRING_DOUBLE_QUOTE:
clob_chars_only = (IonType.CLOB == _value_type);
c = _scanner.load_double_quoted_string(sb, clob_chars_only);
if (c == UnifiedInputStreamX.EOF) {
// String message = "EOF encountered before closing single quote";
// parse_error(message);
_scanner.unexpected_eof();
}
_value_type = IonType.STRING;
break;
case IonTokenConstsX.TOKEN_STRING_TRIPLE_QUOTE:
clob_chars_only = (IonType.CLOB == _value_type);
c = _scanner.load_triple_quoted_string(sb, clob_chars_only);
if (c == UnifiedInputStreamX.EOF) {
//String message = "EOF encountered before closing single quote";
//parse_error(message);
_scanner.unexpected_eof();
}
_value_type = IonType.STRING;
break;
default:
String message = "unexpected token "
+ IonTokenConstsX.getTokenName(token_type)
+ " encountered";
throw new IonException(message);
}
_value_type = IonType.STRING;
break;
default:
String message = "unexpected token "
+ IonTokenConstsX.getTokenName(token_type)
+ " encountered";
throw new IonException(message);
_current_value_save_point.markEnd();
_current_value_save_point_loaded = true;
_current_value_buffer_loaded = true;
tokenValueIsFinished();
} catch (IonException e) {
_current_value_save_point.clear();
_current_value_save_point_loaded = false;
throw e;
}
_current_value_save_point.markEnd();
_current_value_save_point_loaded = true;
_current_value_buffer_loaded = true;
tokenValueIsFinished();
}
return sb;
}
Expand Down
21 changes: 21 additions & 0 deletions src/test/java/com/amazon/ion/util/TextTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
import com.amazon.ion.BlobTest;
import com.amazon.ion.BlobTest.TestData;
import com.amazon.ion.Decimal;
import com.amazon.ion.IonException;
import com.amazon.ion.IonReader;
import com.amazon.ion.IonTestCase;
import com.amazon.ion.IonType;
import com.amazon.ion.impl._Private_IonTextAppender;
import java.math.BigDecimal;
import org.junit.Test;
Expand Down Expand Up @@ -248,4 +251,22 @@ public void testPrintClob()
checkClob("{{\"\"}}", new byte[0]);
checkClob("{{\"\\0a\\xff\"}}", new byte[]{ 0, 'a', (byte) 0xff });
}

@Test
public void testAttemptedRecoveryOnMalformedDataFailsCleanly()
throws Exception
{
// `\0` is not a valid character in unquoted Ion text.
try (IonReader reader = system().newReader("0x2\0")) {
// Note: the reader does not fail on next() because it only needs to read `0x` to determine that the value that
// follows must be an int.
assertEquals(IonType.INT, reader.next());
// Now, the reader attempts to read to the end of the int in order to determine its size. This will raise an
// error due to the invalid character. Ignore this error and attempt to recover.
assertThrows(IonException.class, reader::getIntegerSize);
// Recovery will not be possible, but the following should throw IonException and not a different unchecked
// exception.
assertThrows(IonException.class, reader::intValue);
}
}
}

0 comments on commit 8dbd001

Please sign in to comment.