1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-11-05 20:15:59 +01:00

More cleanup and better error reporting

This commit is contained in:
Paul Schaub 2022-10-27 12:42:30 +02:00
parent 3c94f3677f
commit a0c8de57e9
5 changed files with 48 additions and 15 deletions

View file

@ -6,6 +6,9 @@ package org.pgpainless.decryption_verification.syntax_check;
import org.pgpainless.exception.MalformedOpenPgpMessageException; import org.pgpainless.exception.MalformedOpenPgpMessageException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* This class describes the syntax for OpenPGP messages as specified by rfc4880. * This class describes the syntax for OpenPGP messages as specified by rfc4880.
* *
@ -19,7 +22,7 @@ import org.pgpainless.exception.MalformedOpenPgpMessageException;
public class OpenPgpMessageSyntax implements Syntax { public class OpenPgpMessageSyntax implements Syntax {
@Override @Override
public Transition transition(State from, InputSymbol input, StackSymbol stackItem) public @Nonnull Transition transition(@Nonnull State from, @Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
throws MalformedOpenPgpMessageException { throws MalformedOpenPgpMessageException {
switch (from) { switch (from) {
case OpenPgpMessage: case OpenPgpMessage:
@ -37,7 +40,7 @@ public class OpenPgpMessageSyntax implements Syntax {
throw new MalformedOpenPgpMessageException(from, input, stackItem); throw new MalformedOpenPgpMessageException(from, input, stackItem);
} }
Transition fromOpenPgpMessage(InputSymbol input, StackSymbol stackItem) Transition fromOpenPgpMessage(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
throws MalformedOpenPgpMessageException { throws MalformedOpenPgpMessageException {
if (stackItem != StackSymbol.msg) { if (stackItem != StackSymbol.msg) {
throw new MalformedOpenPgpMessageException(State.OpenPgpMessage, input, stackItem); throw new MalformedOpenPgpMessageException(State.OpenPgpMessage, input, stackItem);
@ -65,7 +68,7 @@ public class OpenPgpMessageSyntax implements Syntax {
} }
} }
Transition fromLiteralMessage(InputSymbol input, StackSymbol stackItem) Transition fromLiteralMessage(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
throws MalformedOpenPgpMessageException { throws MalformedOpenPgpMessageException {
switch (input) { switch (input) {
case Signature: case Signature:
@ -84,7 +87,7 @@ public class OpenPgpMessageSyntax implements Syntax {
throw new MalformedOpenPgpMessageException(State.LiteralMessage, input, stackItem); throw new MalformedOpenPgpMessageException(State.LiteralMessage, input, stackItem);
} }
Transition fromCompressedMessage(InputSymbol input, StackSymbol stackItem) Transition fromCompressedMessage(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
throws MalformedOpenPgpMessageException { throws MalformedOpenPgpMessageException {
switch (input) { switch (input) {
case Signature: case Signature:
@ -103,7 +106,7 @@ public class OpenPgpMessageSyntax implements Syntax {
throw new MalformedOpenPgpMessageException(State.CompressedMessage, input, stackItem); throw new MalformedOpenPgpMessageException(State.CompressedMessage, input, stackItem);
} }
Transition fromEncryptedMessage(InputSymbol input, StackSymbol stackItem) Transition fromEncryptedMessage(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
throws MalformedOpenPgpMessageException { throws MalformedOpenPgpMessageException {
switch (input) { switch (input) {
case Signature: case Signature:
@ -122,7 +125,7 @@ public class OpenPgpMessageSyntax implements Syntax {
throw new MalformedOpenPgpMessageException(State.EncryptedMessage, input, stackItem); throw new MalformedOpenPgpMessageException(State.EncryptedMessage, input, stackItem);
} }
Transition fromValid(InputSymbol input, StackSymbol stackItem) Transition fromValid(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
throws MalformedOpenPgpMessageException { throws MalformedOpenPgpMessageException {
// There is no applicable transition rule out of Valid // There is no applicable transition rule out of Valid
throw new MalformedOpenPgpMessageException(State.Valid, input, stackItem); throw new MalformedOpenPgpMessageException(State.Valid, input, stackItem);

View file

@ -20,10 +20,13 @@ public class PDA {
private static final Logger LOGGER = LoggerFactory.getLogger(PDA.class); private static final Logger LOGGER = LoggerFactory.getLogger(PDA.class);
// right now we implement what rfc4880 specifies.
// TODO: Consider implementing what we proposed here:
// https://mailarchive.ietf.org/arch/msg/openpgp/uepOF6XpSegMO4c59tt9e5H1i4g/
private final Syntax syntax = new OpenPgpMessageSyntax();
private final Stack<StackSymbol> stack = new Stack<>(); private final Stack<StackSymbol> stack = new Stack<>();
private final List<InputSymbol> inputs = new ArrayList<>(); // keep track of inputs for debugging / error reporting private final List<InputSymbol> inputs = new ArrayList<>(); // Track inputs for debugging / error reporting
private State state; private State state;
private Syntax syntax = new OpenPgpMessageSyntax();
public PDA() { public PDA() {
state = State.OpenPgpMessage; state = State.OpenPgpMessage;
@ -32,16 +35,20 @@ public class PDA {
} }
public void next(InputSymbol input) throws MalformedOpenPgpMessageException { public void next(InputSymbol input) throws MalformedOpenPgpMessageException {
StackSymbol stackSymbol = popStack();
try { try {
Transition transition = syntax.transition(state, input, popStack()); Transition transition = syntax.transition(state, input, stackSymbol);
inputs.add(input);
state = transition.getNewState(); state = transition.getNewState();
for (StackSymbol item : transition.getPushedItems()) { for (StackSymbol item : transition.getPushedItems()) {
pushStack(item); pushStack(item);
} }
inputs.add(input);
} catch (MalformedOpenPgpMessageException e) { } catch (MalformedOpenPgpMessageException e) {
MalformedOpenPgpMessageException wrapped = new MalformedOpenPgpMessageException("Malformed message: After reading stream " + Arrays.toString(inputs.toArray()) + MalformedOpenPgpMessageException wrapped = new MalformedOpenPgpMessageException(
", token '" + input + "' is unexpected and illegal.", e); "Malformed message: After reading stream " + Arrays.toString(inputs.toArray()) +
", token '" + input + "' is not allowed." +
"\nNo transition from state '" + state + "' with stack " + Arrays.toString(stack.toArray()) +
(stackSymbol != null ? "||'" + stackSymbol + "'." : "."), e);
LOGGER.debug("Invalid input '" + input + "'", wrapped); LOGGER.debug("Invalid input '" + input + "'", wrapped);
throw wrapped; throw wrapped;
} }

View file

@ -6,6 +6,9 @@ package org.pgpainless.decryption_verification.syntax_check;
import org.pgpainless.exception.MalformedOpenPgpMessageException; import org.pgpainless.exception.MalformedOpenPgpMessageException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* This interface can be used to define a custom syntax for the {@link PDA}. * This interface can be used to define a custom syntax for the {@link PDA}.
*/ */
@ -25,6 +28,6 @@ public interface Syntax {
* @return applicable transition rule containing the new state and pushed stack symbols * @return applicable transition rule containing the new state and pushed stack symbols
* @throws MalformedOpenPgpMessageException if there is no applicable transition rule (the input symbol is illegal) * @throws MalformedOpenPgpMessageException if there is no applicable transition rule (the input symbol is illegal)
*/ */
Transition transition(State from, InputSymbol input, StackSymbol stackItem) @Nonnull Transition transition(@Nonnull State from, @Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
throws MalformedOpenPgpMessageException; throws MalformedOpenPgpMessageException;
} }

View file

@ -4,24 +4,44 @@
package org.pgpainless.decryption_verification.syntax_check; package org.pgpainless.decryption_verification.syntax_check;
import javax.annotation.Nonnull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
/**
* Result of applying a transition rule.
* Transition rules can be described by implementing the {@link Syntax} interface.
*/
public class Transition { public class Transition {
private final List<StackSymbol> pushedItems = new ArrayList<>(); private final List<StackSymbol> pushedItems = new ArrayList<>();
private final State newState; private final State newState;
public Transition(State newState, StackSymbol... pushedItems) { public Transition(@Nonnull State newState, @Nonnull StackSymbol... pushedItems) {
this.newState = newState; this.newState = newState;
this.pushedItems.addAll(Arrays.asList(pushedItems)); this.pushedItems.addAll(Arrays.asList(pushedItems));
} }
/**
* Return the new {@link State} that is reached by applying the transition.
*
* @return new state
*/
@Nonnull
public State getNewState() { public State getNewState() {
return newState; return newState;
} }
/**
* Return a list of {@link StackSymbol StackSymbols} that are pushed onto the stack
* by applying the transition.
* The list contains items in the order in which they are pushed onto the stack.
* The list may be empty.
*
* @return list of items to be pushed onto the stack
*/
@Nonnull
public List<StackSymbol> getPushedItems() { public List<StackSymbol> getPushedItems() {
return new ArrayList<>(pushedItems); return new ArrayList<>(pushedItems);
} }

View file

@ -97,7 +97,7 @@ public class PDATest {
} }
@Test @Test
public void testEncryptedMessageWithAppendedStandalongSigIsNotValid() { public void testEncryptedMessageWithAppendedStandaloneSigIsNotValid() {
PDA check = new PDA(); PDA check = new PDA();
check.next(InputSymbol.EncryptedData); check.next(InputSymbol.EncryptedData);
assertThrows(MalformedOpenPgpMessageException.class, assertThrows(MalformedOpenPgpMessageException.class,