diff --git a/src/main/java/de/rub/nds/modifiablevariable/FileConfigurationException.java b/src/main/java/de/rub/nds/modifiablevariable/FileConfigurationException.java deleted file mode 100644 index fbc01d75..00000000 --- a/src/main/java/de/rub/nds/modifiablevariable/FileConfigurationException.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * ModifiableVariable - A Variable Concept for Runtime Modifications - * - * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH - * - * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 - */ -package de.rub.nds.modifiablevariable; - -public class FileConfigurationException extends RuntimeException { - - public FileConfigurationException() { - super(); - } - - public FileConfigurationException(Exception ex) { - super(ex); - } - - public FileConfigurationException(String message, Exception ex) { - super(message, ex); - } -} diff --git a/src/main/java/de/rub/nds/modifiablevariable/HoldsModifiableVariable.java b/src/main/java/de/rub/nds/modifiablevariable/HoldsModifiableVariable.java index c7b067cb..2d33ee91 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/HoldsModifiableVariable.java +++ b/src/main/java/de/rub/nds/modifiablevariable/HoldsModifiableVariable.java @@ -13,8 +13,24 @@ import java.lang.annotation.Target; /** - * Annotation interface for modifiable variables holders. A modifiable variable holder is for - * example a TLS protocol message. + * Annotation for fields that contain ModifiableVariable instances or ModifiableVariableHolder + * objects. + * + *

This annotation marks fields within a class that reference modifiable variables or objects + * that contain modifiable variables. It is used for reflection-based discovery and manipulation of + * modifiable variables throughout a complex object hierarchy. + * + *

By marking fields with this annotation, the framework can identify which fields should be + * included in operations like: + * + *

+ * + *

This annotation is retained at runtime and can only be applied to fields. */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) diff --git a/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariable.java b/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariable.java index 7aca6a30..8942187e 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariable.java +++ b/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariable.java @@ -14,26 +14,46 @@ import java.util.stream.Collectors; /** - * The base abstract class for modifiable variables, including the getValue function. The class - * needs to be defined transient to allow propOrder definition in subclasses, see: docs + * The base abstract class for modifiable variables that provides runtime value modification + * capabilities. ModifiableVariable serves as the foundation for all modifiable types in the + * library. * - * @param + *

This class implements the concept of runtime value modifications, where variables can be + * modified through a chain of {@link VariableModification} operations before being accessed. Each + * subclass represents a specific data type that can be modified at runtime. + * + *

The class is defined as transient to allow proper XML serialization with propOrder definition + * in subclasses. See: Ignoring + * Inheritance with XmlTransient for details. + * + * @param The type of value this modifiable variable holds (e.g., Integer, String, byte[]) */ @XmlTransient @XmlAccessorType(XmlAccessType.FIELD) public abstract class ModifiableVariable implements Serializable { + /** The list of modifications that will be applied to the original value when accessed */ @XmlElementWrapper @XmlAnyElement(lax = true) private LinkedList> modifications; + /** The expected value for assertion validation */ protected E assertEquals; + /** Default constructor that creates an empty modifiable variable. */ protected ModifiableVariable() { super(); } + /** + * Copy constructor that creates a new modifiable variable with the same modifications and + * assertions. + * + *

Note: Subclasses must ensure proper copying of the respecitve assertEquals field. + * + * @param other The modifiable variable to copy + */ protected ModifiableVariable(ModifiableVariable other) { super(); if (other.modifications != null) { @@ -46,23 +66,39 @@ protected ModifiableVariable(ModifiableVariable other) { assertEquals = other.assertEquals; } - /** Sets multiple modifications, all previously set modifications are removed */ + /** + * Sets multiple modifications, replacing any previously set modifications. + * + * @param modifications The list of modifications to apply in sequence + */ public void setModifications(List> modifications) { this.modifications = new LinkedList<>(modifications); } - /** Sets multiple modifications, all previously set modifications are removed */ + /** + * Sets multiple modifications, replacing any previously set modifications. + * + * @param modifications The variable arguments list of modifications to apply in sequence + */ @SafeVarargs public final void setModifications(VariableModification... modifications) { this.modifications = new LinkedList<>(List.of(modifications)); } - /** Removes all modifications */ + /** + * Removes all modifications from this variable. After calling this method, getValue() will + * return the original value. + */ public void clearModifications() { modifications = null; } - /** Adds a modification to this modifiable variable */ + /** + * Adds a modification to the end of this variable's modification chain. The modification will + * be applied after all previously added modifications. + * + * @param modification The modification to add + */ public void addModification(VariableModification modification) { if (modification != null) { if (modifications == null) { @@ -72,15 +108,31 @@ public void addModification(VariableModification modification) { } } - /** Returns all modifications that are set for this modifiable variable */ + /** + * Returns all modifications that are set for this modifiable variable. + * + * @return The list of modifications or null if no modifications are set + */ public LinkedList> getModifications() { return modifications; } + /** + * Returns the modified value of this variable. The original value will be modified by applying + * all registered modifications in sequence. + * + * @return The modified value after applying all modifications + */ public E getValue() { return getModifiedValue(); } + /** + * Internal implementation method to compute the modified value. Applies all registered + * modifications to the original value in sequence. + * + * @return The value after applying all modifications + */ private E getModifiedValue() { E resultValue = getOriginalValue(); if (modifications != null) { @@ -91,20 +143,57 @@ private E getModifiedValue() { return resultValue; } + /** + * Returns the original, unmodified value of this variable. + * + * @return The original value + */ public abstract E getOriginalValue(); + /** + * Sets the original value of this variable. + * + * @param originalValue The new original value + */ public abstract void setOriginalValue(E originalValue); + /** + * Creates a deep copy of this modifiable variable. + * + * @return A new instance with the same original value, modifications, and assertion values + */ public abstract ModifiableVariable createCopy(); + /** + * Checks if the modified value differs from the original value. + * + * @return true if the modified value is different from the original, false otherwise + * @throws IllegalStateException If the original value is not set + */ public abstract boolean isOriginalValueModified(); + /** + * Validates whether the modified value matches the expected value (if set). + * + * @return true if no assertions are set or if all assertions pass, false otherwise + */ public abstract boolean validateAssertions(); + /** + * Checks if this variable has an assertion value set. + * + * @return true if an assertEquals value is set, false otherwise + */ public boolean containsAssertion() { return assertEquals != null; } + /** + * Helper method for toString() implementations in subclasses. Provides a string representation + * of modifications and assertions. + * + * @return A string containing the modifications and assertions + */ protected String innerToString() { StringBuilder result = new StringBuilder(); if (modifications != null) { diff --git a/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableFactory.java b/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableFactory.java index 7f163b09..1f63a608 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableFactory.java +++ b/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableFactory.java @@ -16,36 +16,21 @@ import de.rub.nds.modifiablevariable.string.ModifiableString; import java.math.BigInteger; +/** + * Factory class for creating modifiable variables of different types. + * + *

This factory provides methods to safely set values on existing or new modifiable variables. + * The factory ensures that null modifiable variables are properly initialized when setting values. + */ public final class ModifiableVariableFactory { - public static ModifiableBigInteger createBigIntegerModifiableVariable() { - return new ModifiableBigInteger(); - } - - public static ModifiableInteger createIntegerModifiableVariable() { - return new ModifiableInteger(); - } - - public static ModifiableByte createByteModifiableVariable() { - return new ModifiableByte(); - } - - public static ModifiableByteArray createByteArrayModifiableVariable() { - return new ModifiableByteArray(); - } - - public static ModifiableLong createLongModifiableVariable() { - return new ModifiableLong(); - } - - public static ModifiableBoolean createBooleanModifiableVariable() { - return new ModifiableBoolean(); - } - - public static ModifiableString createStringModifiableVariable() { - return new ModifiableString(); - } - + /** + * Safely sets a value on a ModifiableBigInteger, creating a new instance if necessary. + * + * @param mv The ModifiableBigInteger to set the value on, or null to create a new one + * @param value The BigInteger value to set + * @return The ModifiableBigInteger with the value set + */ public static ModifiableBigInteger safelySetValue(ModifiableBigInteger mv, BigInteger value) { if (mv == null) { return new ModifiableBigInteger(value); @@ -54,6 +39,13 @@ public static ModifiableBigInteger safelySetValue(ModifiableBigInteger mv, BigIn return mv; } + /** + * Safely sets a value on a ModifiableString, creating a new instance if necessary. + * + * @param mv The ModifiableString to set the value on, or null to create a new one + * @param value The String value to set + * @return The ModifiableString with the value set + */ public static ModifiableString safelySetValue(ModifiableString mv, String value) { if (mv == null) { return new ModifiableString(value); @@ -62,6 +54,13 @@ public static ModifiableString safelySetValue(ModifiableString mv, String value) return mv; } + /** + * Safely sets a value on a ModifiableInteger, creating a new instance if necessary. + * + * @param mv The ModifiableInteger to set the value on, or null to create a new one + * @param value The Integer value to set + * @return The ModifiableInteger with the value set + */ public static ModifiableInteger safelySetValue(ModifiableInteger mv, Integer value) { if (mv == null) { return new ModifiableInteger(value); @@ -70,6 +69,13 @@ public static ModifiableInteger safelySetValue(ModifiableInteger mv, Integer val return mv; } + /** + * Safely sets a value on a ModifiableByte, creating a new instance if necessary. + * + * @param mv The ModifiableByte to set the value on, or null to create a new one + * @param value The Byte value to set + * @return The ModifiableByte with the value set + */ public static ModifiableByte safelySetValue(ModifiableByte mv, Byte value) { if (mv == null) { return new ModifiableByte(value); @@ -78,6 +84,13 @@ public static ModifiableByte safelySetValue(ModifiableByte mv, Byte value) { return mv; } + /** + * Safely sets a value on a ModifiableByteArray, creating a new instance if necessary. + * + * @param mv The ModifiableByteArray to set the value on, or null to create a new one + * @param value The byte array value to set + * @return The ModifiableByteArray with the value set + */ public static ModifiableByteArray safelySetValue(ModifiableByteArray mv, byte[] value) { if (mv == null) { return new ModifiableByteArray(value); @@ -86,6 +99,13 @@ public static ModifiableByteArray safelySetValue(ModifiableByteArray mv, byte[] return mv; } + /** + * Safely sets a value on a ModifiableLong, creating a new instance if necessary. + * + * @param mv The ModifiableLong to set the value on, or null to create a new one + * @param value The Long value to set + * @return The ModifiableLong with the value set + */ public static ModifiableLong safelySetValue(ModifiableLong mv, Long value) { if (mv == null) { return new ModifiableLong(value); @@ -94,6 +114,13 @@ public static ModifiableLong safelySetValue(ModifiableLong mv, Long value) { return mv; } + /** + * Safely sets a value on a ModifiableBoolean, creating a new instance if necessary. + * + * @param mv The ModifiableBoolean to set the value on, or null to create a new one + * @param value The Boolean value to set + * @return The ModifiableBoolean with the value set + */ public static ModifiableBoolean safelySetValue(ModifiableBoolean mv, Boolean value) { if (mv == null) { return new ModifiableBoolean(value); @@ -102,6 +129,7 @@ public static ModifiableBoolean safelySetValue(ModifiableBoolean mv, Boolean val return mv; } + /** Private constructor to prevent instantiation of utility class. */ private ModifiableVariableFactory() { super(); } diff --git a/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableHolder.java b/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableHolder.java index 73f6a3c3..850a53c0 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableHolder.java +++ b/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableHolder.java @@ -19,36 +19,71 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +/** + * Base class for objects that contain modifiable variables. + * + *

This abstract class provides functionality for managing and accessing modifiable variables + * within a containing class. It allows for runtime reflection-based access to fields of type {@link + * ModifiableVariable} and provides methods for: + * + *

+ * + *

This class is the backbone of the modifiable variable framework, as it allows for systematic + * manipulation and inspection of protocol data structures that contain modifiable variables. + * + *

Classes that extend this base class can be serialized to XML using JAXB. + */ @XmlType(name = "ModVarHolder") public abstract class ModifiableVariableHolder implements Serializable { + /** Logger for this class */ private static final Logger LOGGER = LogManager.getLogger(); + /** Creates a new ModifiableVariableHolder.+ */ + protected ModifiableVariableHolder() { + // Default constructor deliberately left empty + } + /** - * Lists all the modifiable variables declared in the class + * Lists all fields that are of type ModifiableVariable declared in this class and its + * superclasses. * - * @return List of all modifiableVariables declared in this class + *

This method uses reflection to identify all fields that extend ModifiableVariable. + * + * @return A list of Field objects representing all ModifiableVariable fields in the class */ - public List getAllModifiableVariableFields() { + public final List getAllModifiableVariableFields() { return ReflectionHelper.getFieldsUpTo(getClass(), null, ModifiableVariable.class); } /** - * Returns a random field representing a modifiable variable from this class + * Returns a randomly selected ModifiableVariable field from this class. + * + *

This method is particularly useful for testing and fuzzing, where random manipulation of + * fields is needed. * - * @param random The RandomNumber generator that should be used - * @return A random ModifiableVariableField + * @param random The random number generator to use for the selection + * @return A randomly selected Field object representing a ModifiableVariable */ - public Field getRandomModifiableVariableField(Random random) { + public final Field getRandomModifiableVariableField(Random random) { List fields = getAllModifiableVariableFields(); int randomField = random.nextInt(fields.size()); return fields.get(randomField); } /** - * Returns a list of all the modifiable variable holders in the object, including this instance + * Returns a list of all ModifiableVariableHolder instances in this object. + * + *

The default implementation only includes this instance, but subclasses can override this + * method to include nested ModifiableVariableHolder objects. * - * @return All ModifiableVariableHolders + * @return A list containing this instance and, potentially, nested ModifiableVariableHolder + * objects */ public List getAllModifiableVariableHolders() { List holders = new LinkedList<>(); @@ -57,17 +92,33 @@ public List getAllModifiableVariableHolders() { } /** - * Returns a random modifiable variable holder + * Returns a randomly selected ModifiableVariableHolder from this object. * - * @param random The RandomNumberGenerator that should be used - * @return A Random ModifiableVariableHolder + *

If this class contains nested ModifiableVariableHolder objects and overrides + * getAllModifiableVariableHolders(), this method could return one of those nested holders. + * + * @param random The random number generator to use for the selection + * @return A randomly selected ModifiableVariableHolder */ - public ModifiableVariableHolder getRandomModifiableVariableHolder(Random random) { + public final ModifiableVariableHolder getRandomModifiableVariableHolder(Random random) { List holders = getAllModifiableVariableHolders(); int randomHolder = random.nextInt(holders.size()); return holders.get(randomHolder); } + /** + * Resets all ModifiableVariable fields in this object to their default state. + * + *

For each ModifiableVariable field: + * + *

+ * + *

This method is useful for returning an object to a clean state before applying new + * modifications. + */ public void reset() { List fields = getAllModifiableVariableFields(); for (Field field : fields) { @@ -94,10 +145,34 @@ public void reset() { } } + /** + * Creates a detailed string representation of this object and all its fields. + * + *

This method returns a hierarchical, formatted string that includes the values of all + * fields, including nested ModifiableVariableHolder objects. The format is particularly useful + * for debugging and detailed logging. + * + * @return A formatted string representation of this object + */ public String getExtendedString() { return getClass().getSimpleName() + "{\n" + getExtendedString(1) + "}\n"; } + /** + * Helper method that creates a detailed string representation of this object with indentation. + * + *

This method handles the recursion and formatting for the getExtendedString() method, with + * special handling for different field types: + * + *

+ * + * @param depth The current indentation depth + * @return A formatted string representing this object's fields + */ protected String getExtendedString(int depth) { StringBuilder stringBuilder = new StringBuilder(); List fields = ReflectionHelper.getFieldsUpTo(getClass(), null, null); diff --git a/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableProperty.java b/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableProperty.java index affcc4db..0cdcad4c 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableProperty.java +++ b/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableProperty.java @@ -12,39 +12,85 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** Annotation interface for modifiable variables. */ +/** + * Annotation interface for marking and categorizing modifiable variables within a class. + * + *

This annotation provides metadata about a modifiable variable field, including its semantic + * type (what kind of data it represents) and format (how the data is encoded). This information can + * be used for reflection-based analysis, serialization, or other operations that need to understand + * the purpose of different variables. + * + *

//TODO This class has not been touched or used much for a while and needs refactoring. + * + *

The annotation is retained at runtime and can only be applied to fields. + */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface ModifiableVariableProperty { + /** + * Semantic types that can be assigned to modifiable variables. These values describe the + * purpose or role of the variable. + */ enum Type { + /** Variable representing a length field */ LENGTH, + /** Variable representing a count field */ COUNT, + /** Variable representing padding */ PADDING, - /** variable presenting one or more (array of) TLS constants */ + /** Variable representing one or more (array of) TLS constants */ TLS_CONSTANT, + /** Variable representing a cryptographic signature */ SIGNATURE, + /** Variable representing encrypted data */ CIPHERTEXT, + /** Variable representing a message authentication code */ HMAC, + /** Variable representing a public key */ PUBLIC_KEY, + /** Variable representing a private key */ PRIVATE_KEY, + /** Variable representing key material */ KEY_MATERIAL, + /** Variable representing a certificate */ CERTIFICATE, - /** plain protocol message, always in a decrypted state */ + /** Variable representing a plain protocol message, always in a decrypted state */ PLAIN_PROTOCOL_MESSAGE, + /** Variable representing a plain record */ PLAIN_RECORD, + /** Variable representing a cookie */ COOKIE, + /** Default type when no specific type is applicable */ NONE, + /** Variable that switches behavior */ BEHAVIOR_SWITCH } + /** + * Encoding formats that can be used for modifiable variables. These values describe how the + * data is encoded. + */ enum Format { + /** ASN.1 encoding format */ ASN1, + /** PKCS#1 encoding format */ PKCS1, + /** Default format when no specific format is applicable */ NONE } + /** + * Specifies the semantic type of the annotated variable. + * + * @return The type of the variable + */ Type type() default Type.NONE; + /** + * Specifies the encoding format of the annotated variable. + * + * @return The format of the variable + */ Format format() default Format.NONE; } diff --git a/src/main/java/de/rub/nds/modifiablevariable/VariableModification.java b/src/main/java/de/rub/nds/modifiablevariable/VariableModification.java index a7582bc2..d7d665e4 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/VariableModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/VariableModification.java @@ -17,35 +17,115 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +/** + * Abstract base class for all variable modifications. + * + *

A VariableModification represents a transformation that can be applied to a value of type E at + * runtime. Each concrete implementation defines a specific way to modify values, such as addition, + * XOR operations, explicit value replacements, or other transformations. + * + *

The modification framework is designed for security testing and protocol analysis, allowing + * runtime manipulation of protocol fields to: + * + *

+ * + *

This class follows the Template Method pattern, with the main {@link #modify} method providing + * common functionality (such as debugging) while delegating the actual modification implementation + * to subclasses through the {@link #modifyImplementationHook} method. + * + *

All modifications are designed to be immutable and preserve the original input values, + * creating new objects with the modified data rather than modifying the inputs in-place. + * + * @param The type of value this modification operates on + */ @XmlTransient @XmlAccessorType(XmlAccessType.FIELD) public abstract class VariableModification implements Serializable { + /** Logger for debugging modification applications */ protected static final Logger LOGGER = LogManager.getLogger(VariableModification.class); + /** Default constructor. */ protected VariableModification() { super(); } + /** + * Copy constructor. + * + * @param other The modification to copy + */ protected VariableModification(VariableModification other) { super(); } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same modification parameters + */ public abstract VariableModification createCopy(); + /** + * Applies this modification to the provided input value. + * + *

This method is the main entry point for applying modifications to values. It follows the + * Template Method pattern by: + * + *

    + *
  1. Delegating the actual modification to the implementation-specific {@link + * #modifyImplementationHook} method + *
  2. Handling debug logging of the modification operation through the {@link #debug} method + *
  3. Returning the modified value to the caller + *
+ * + *

This design centralizes common functionality while allowing subclasses to focus solely on + * implementing their specific modification logic. + * + * @param input The value to modify + * @return The modified value, or null if the input was null (null-safety is maintained) + */ public E modify(E input) { E modifiedValue = modifyImplementationHook(input); debug(modifiedValue); return modifiedValue; } + /** + * Abstract hook method that each concrete modification must implement to define how the input + * value is transformed. + * + *

This hook method is part of the Template Method pattern and is called by {@link #modify} + * to perform the actual modification logic. Subclasses must implement this method to: + * + *

+ * + *

Each implementation is expected to maintain null-safety by returning null if the input is + * null, rather than throwing exceptions. This ensures consistent behavior across all + * modification types. + * + * @param input The value to modify + * @return The modified value, or null if the input was null + */ protected abstract E modifyImplementationHook(E input); /** - * Debugging modified variables. Getting stack trace can be time-consuming, thus we use - * isDebugEnabled() function + * Logs debug information about the modification being applied. + * + *

This method logs the modification class name, calling function, and the new value after + * modification. * - * @param value variable modification that is going to be debugged + * @param value The modified value to be logged */ protected void debug(E value) { if (LOGGER.isDebugEnabled()) { diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerAddModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerAddModification.java index f2d7e4c9..65c33865 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerAddModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerAddModification.java @@ -12,30 +12,62 @@ import java.math.BigInteger; import java.util.Objects; +/** + * A modification that adds a constant value to a BigInteger. + * + *

This modification adds a specified BigInteger value (summand) to the input value when applied. + * It can be used to increment or decrement BigInteger values at runtime, which is particularly + * useful for manipulating large integer values like those used in cryptographic operations. + */ @XmlRootElement public class BigIntegerAddModification extends VariableModification { + /** The value to add to the original BigInteger */ private BigInteger summand; - public BigIntegerAddModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private BigIntegerAddModification() { super(); } + /** + * Creates a new addition modification with the specified summand. + * + * @param summand The value to add to the original BigInteger + * @throws NullPointerException if summand is null + */ public BigIntegerAddModification(BigInteger summand) { super(); - this.summand = summand; + this.summand = Objects.requireNonNull(summand, "Summand must not be null"); } + /** + * Copy constructor. + * + * @param other The modification to copy + */ public BigIntegerAddModification(BigIntegerAddModification other) { super(other); summand = other.summand; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same summand + */ @Override public BigIntegerAddModification createCopy() { return new BigIntegerAddModification(this); } + /** + * Modifies the input by adding the summand. + * + * @param input The BigInteger value to modify + * @return The result of adding the summand to the input, or null if the input is null + */ @Override protected BigInteger modifyImplementationHook(BigInteger input) { if (input == null) { @@ -44,14 +76,30 @@ protected BigInteger modifyImplementationHook(BigInteger input) { return input.add(summand); } + /** + * Gets the summand used for the addition. + * + * @return The value that will be added to the original BigInteger + */ public BigInteger getSummand() { return summand; } + /** + * Sets the summand for the addition. + * + * @param summand The value that will be added to the original BigInteger + */ public void setSummand(BigInteger summand) { + Objects.requireNonNull(summand, "Summand must not be null"); this.summand = summand; } + /** + * Computes a hash code for this modification. The hash code is based on the summand value. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -59,6 +107,13 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two BigIntegerAddModification + * instances are considered equal if they have the same summand. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -74,6 +129,11 @@ public boolean equals(Object obj) { return Objects.equals(summand, other.summand); } + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type and summand + */ @Override public String toString() { return "BigIntegerAddModification{" + "summand=" + summand + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerExplicitValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerExplicitValueModification.java index df12ae11..fb2137c5 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerExplicitValueModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerExplicitValueModification.java @@ -12,30 +12,68 @@ import java.math.BigInteger; import java.util.Objects; +/** + * A modification that replaces the original BigInteger value with an explicitly defined value. + * + *

This modification ignores the original value and always returns a predefined value specified + * at initialization or via setter. It's useful for testing scenarios where a specific BigInteger + * value needs to be injected regardless of the original value. + * + * @see ModifiableBigInteger + */ @XmlRootElement public class BigIntegerExplicitValueModification extends VariableModification { - protected BigInteger explicitValue; + /** The explicit value that will replace the original value */ + private BigInteger explicitValue; - public BigIntegerExplicitValueModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private BigIntegerExplicitValueModification() { super(); } + /** + * Creates a new explicit value modification with the specified value. + * + * @param explicitValue The value that will replace the original value + * @throws NullPointerException if explicitValue is null + */ public BigIntegerExplicitValueModification(BigInteger explicitValue) { super(); - this.explicitValue = explicitValue; + this.explicitValue = + Objects.requireNonNull(explicitValue, "ExplicitValue must not be null"); } + /** + * Copy constructor. + * + * @param other The modification to copy + */ public BigIntegerExplicitValueModification(BigIntegerExplicitValueModification other) { super(other); explicitValue = other.explicitValue; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same explicit value + */ @Override public BigIntegerExplicitValueModification createCopy() { return new BigIntegerExplicitValueModification(this); } + /** + * Modifies the input by replacing it with the explicit value. + * + *

This method ignores the input value and always returns the explicit value set during + * initialization or via setter. The original value is completely discarded. + * + * @param input The original value (ignored except for null check) + * @return The explicit value, or null if input was null + */ @Override protected BigInteger modifyImplementationHook(BigInteger input) { if (input == null) { @@ -44,14 +82,30 @@ protected BigInteger modifyImplementationHook(BigInteger input) { return explicitValue; } + /** + * Gets the explicit value that will replace the original value. + * + * @return The explicit value + */ public BigInteger getExplicitValue() { return explicitValue; } + /** + * Sets the explicit value that will replace the original value. + * + * @param explicitValue The new explicit value to use + */ public void setExplicitValue(BigInteger explicitValue) { + Objects.requireNonNull(explicitValue, "ExplicitValue must not be null"); this.explicitValue = explicitValue; } + /** + * Computes a hash code for this modification. The hash code is based on the explicit value. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -59,6 +113,14 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two + * BigIntegerExplicitValueModification instances are considered equal if they have the same + * explicit value. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -74,6 +136,11 @@ public boolean equals(Object obj) { return Objects.equals(explicitValue, other.explicitValue); } + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type and explicit value + */ @Override public String toString() { return "BigIntegerExplicitValueModification{" + "explicitValue=" + explicitValue + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerMultiplyModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerMultiplyModification.java index d51e29e7..76c7019a 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerMultiplyModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerMultiplyModification.java @@ -12,30 +12,63 @@ import java.math.BigInteger; import java.util.Objects; +/** + * A modification that multiplies a ModifiableBigInteger by a constant factor. + * + *

This modification multiplies the input value by a specified BigInteger factor when applied. It + * can be used to scale BigInteger values at runtime. + * + * @see ModifiableBigInteger + */ @XmlRootElement public class BigIntegerMultiplyModification extends VariableModification { + /** The factor to multiply by */ private BigInteger factor; - public BigIntegerMultiplyModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private BigIntegerMultiplyModification() { super(); } + /** + * Creates a new multiplication modification with the specified factor. + * + * @param factor The value to multiply the original BigInteger by + * @throws NullPointerException if factor is null + */ public BigIntegerMultiplyModification(BigInteger factor) { super(); - this.factor = factor; + this.factor = Objects.requireNonNull(factor, "Factor must not be null"); } + /** + * Copy constructor. + * + * @param other The modification to copy + */ public BigIntegerMultiplyModification(BigIntegerMultiplyModification other) { super(other); factor = other.factor; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same factor + */ @Override public BigIntegerMultiplyModification createCopy() { return new BigIntegerMultiplyModification(this); } + /** + * Modifies the input by multiplying it by the factor. + * + * @param input The BigInteger value to modify + * @return The result of multiplying the input by the factor, or null if input is null + */ @Override protected BigInteger modifyImplementationHook(BigInteger input) { if (input == null) { @@ -44,14 +77,29 @@ protected BigInteger modifyImplementationHook(BigInteger input) { return input.multiply(factor); } + /** + * Gets the factor used for multiplication. + * + * @return The value that will multiply the original BigInteger + */ public BigInteger getFactor() { return factor; } + /** + * Sets the factor for multiplication. + * + * @param factor The value that will multiply the original BigInteger + */ public void setFactor(BigInteger factor) { - this.factor = factor; + this.factor = Objects.requireNonNull(factor, "Factor must not be null"); } + /** + * Computes a hash code for this modification. The hash code is based on the factor value. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -59,6 +107,13 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two BigIntegerMultiplyModification + * instances are considered equal if they have the same factor. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -74,6 +129,11 @@ public boolean equals(Object obj) { return Objects.equals(factor, other.factor); } + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type and factor + */ @Override public String toString() { return "BigIntegerMultiplyModification{" + "factor=" + factor + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModification.java index c8b447d2..d71bb8e3 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModification.java @@ -11,30 +11,74 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.math.BigInteger; +/** + * A modification that performs a left bit shift on a ModifiableBigInteger. + * + *

This modification shifts the bits of the input BigInteger to the left by a specified number of + * positions when applied. It effectively multiplies the value by 2 raised to the power of the shift + * amount, which can be used to rapidly scale BigInteger values at runtime. + * + * @see ModifiableBigInteger + * @see BigIntegerShiftRightModification + */ @XmlRootElement public class BigIntegerShiftLeftModification extends VariableModification { + /** The number of bits to shift left */ private int shift; - public BigIntegerShiftLeftModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private BigIntegerShiftLeftModification() { super(); } + /** + * Creates a new modification with the specified shift amount. + * + *

This constructor sets the number of bits by which the original BigInteger will be shifted + * left when the modification is applied. + * + * @param shift The number of bits to shift left + */ public BigIntegerShiftLeftModification(int shift) { super(); this.shift = shift; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public BigIntegerShiftLeftModification(BigIntegerShiftLeftModification other) { super(other); shift = other.shift; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same shift amount + */ @Override public BigIntegerShiftLeftModification createCopy() { return new BigIntegerShiftLeftModification(this); } + /** + * Implements the modification by shifting the input BigInteger left. + * + *

This method shifts the input BigInteger left by the number of bits specified during + * initialization or via {@link #setShift(int)}. If the input is null, it returns null to + * preserve null-safety. + * + *

The implementation uses {@link BigInteger#shiftLeft(int)}, which effectively multiplies + * the value by 2 raised to the power of the shift amount. + * + * @param input The original BigInteger value + * @return The shifted BigInteger value, or null if input was null + */ @Override protected BigInteger modifyImplementationHook(BigInteger input) { if (input == null) { @@ -43,14 +87,31 @@ protected BigInteger modifyImplementationHook(BigInteger input) { return input.shiftLeft(shift); } + /** + * Gets the number of bits to shift left. + * + * @return The shift amount + */ public int getShift() { return shift; } + /** + * Sets the number of bits to shift left. + * + * @param shift The new shift amount + */ public void setShift(int shift) { this.shift = shift; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the shift amount. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -58,6 +119,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two BigIntegerShiftLeftModification objects are considered equal if they have the same + * shift amount. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +143,13 @@ public boolean equals(Object obj) { return shift == other.shift; } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and the shift amount. + * + * @return A string representation of this object + */ @Override public String toString() { return "BigIntegerShiftLeftModification{" + "shift=" + shift + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftRightModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftRightModification.java index 41f9b6d4..0eadcb0d 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftRightModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftRightModification.java @@ -11,30 +11,68 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.math.BigInteger; +/** + * A modification that performs a right bit shift on a ModifiableBigInteger. + * + *

This modification applies a logical right shift operation to the input value, effectively + * dividing the value by 2 raised to the power of the shift amount. It can be used to manipulate + * binary data at runtime. + * + * @see BigIntegerShiftLeftModification + * @see ModifiableBigInteger + */ @XmlRootElement public class BigIntegerShiftRightModification extends VariableModification { + /** The number of bit positions to shift right */ private int shift; - public BigIntegerShiftRightModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private BigIntegerShiftRightModification() { super(); } + /** + * Creates a new right shift modification with the specified shift amount. + * + * @param shift The number of bit positions to shift the value right + */ public BigIntegerShiftRightModification(int shift) { super(); this.shift = shift; } + /** + * Copy constructor. + * + * @param other The modification to copy + */ public BigIntegerShiftRightModification(BigIntegerShiftRightModification other) { super(other); shift = other.shift; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same shift amount + */ @Override public BigIntegerShiftRightModification createCopy() { return new BigIntegerShiftRightModification(this); } + /** + * Modifies the input by shifting it right by the specified number of bits. + * + *

A right shift by n bits is equivalent to dividing by 2^n (integer division with truncation + * toward zero). This operation preserves the sign of the original value. + * + * @param input The BigInteger value to modify + * @return The result of shifting the input right by the specified amount, or null if input is + * null + */ @Override protected BigInteger modifyImplementationHook(BigInteger input) { if (input == null) { @@ -43,14 +81,29 @@ protected BigInteger modifyImplementationHook(BigInteger input) { return input.shiftRight(shift); } + /** + * Gets the number of bits to shift right. + * + * @return The shift amount used for this modification + */ public int getShift() { return shift; } + /** + * Sets the number of bits to shift right. + * + * @param shift The new shift amount to use + */ public void setShift(int shift) { this.shift = shift; } + /** + * Computes a hash code for this modification. The hash code is based on the shift amount. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -58,6 +111,13 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two BigIntegerShiftRightModification + * instances are considered equal if they have the same shift amount. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +133,11 @@ public boolean equals(Object obj) { return shift == other.shift; } + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type and shift amount + */ @Override public String toString() { return "BigIntegerShiftRightModification{" + "shift=" + shift + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerSubtractModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerSubtractModification.java index 99c09761..b14771d0 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerSubtractModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerSubtractModification.java @@ -12,30 +12,65 @@ import java.math.BigInteger; import java.util.Objects; +/** + * A modification that subtracts a constant value from a ModifiableBigInteger. + * + *

This modification subtracts a specified BigInteger value (subtrahend) from the input value + * when applied. It can be used to decrement BigInteger values at runtime. + * + * @see ModifiableBigInteger + */ @XmlRootElement public class BigIntegerSubtractModification extends VariableModification { + /** The value to subtract from the original BigInteger */ private BigInteger subtrahend; - public BigIntegerSubtractModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private BigIntegerSubtractModification() { super(); } + /** + * Creates a new subtraction modification with the specified subtrahend. + * + * @param subtrahend The value to subtract from the original BigInteger + * @throws NullPointerException if subtrahend is null + */ public BigIntegerSubtractModification(BigInteger subtrahend) { super(); - this.subtrahend = subtrahend; + this.subtrahend = Objects.requireNonNull(subtrahend, "Subtrahend must not be null"); } + /** + * Copy constructor. + * + * @param other The modification to copy + */ public BigIntegerSubtractModification(BigIntegerSubtractModification other) { super(other); subtrahend = other.subtrahend; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same subtrahend + */ @Override public BigIntegerSubtractModification createCopy() { return new BigIntegerSubtractModification(this); } + /** + * Modifies the input by subtracting the subtrahend. + * + *

Note that the result can be negative if the subtrahend is larger than the input value. + * + * @param input The BigInteger value to modify + * @return The result of subtracting the subtrahend from the input, or null if input is null + */ @Override protected BigInteger modifyImplementationHook(BigInteger input) { if (input == null) { @@ -44,14 +79,29 @@ protected BigInteger modifyImplementationHook(BigInteger input) { return input.subtract(subtrahend); } + /** + * Gets the subtrahend used for the subtraction. + * + * @return The value that will be subtracted from the original BigInteger + */ public BigInteger getSubtrahend() { return subtrahend; } + /** + * Sets the subtrahend for the subtraction. + * + * @param subtrahend The value that will be subtracted from the original BigInteger + */ public void setSubtrahend(BigInteger subtrahend) { - this.subtrahend = subtrahend; + this.subtrahend = Objects.requireNonNull(subtrahend, "Subtrahend must not be null"); } + /** + * Computes a hash code for this modification. The hash code is based on the subtrahend value. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -59,6 +109,13 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two BigIntegerSubtractModification + * instances are considered equal if they have the same subtrahend. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -74,6 +131,11 @@ public boolean equals(Object obj) { return Objects.equals(subtrahend, other.subtrahend); } + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type and subtrahend + */ @Override public String toString() { return "BigIntegerSubtractModification{" + "subtrahend=" + subtrahend + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerXorModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerXorModification.java index 74c455a2..87d5cf80 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerXorModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerXorModification.java @@ -12,30 +12,76 @@ import java.math.BigInteger; import java.util.Objects; +/** + * A modification that applies a bitwise XOR operation to a ModifiableBigInteger. + * + *

This modification performs a bitwise XOR (exclusive OR) operation between the original + * BigInteger value and a specified XOR mask when applied. It can be used to selectively flip + * specific bits in BigInteger values at runtime. + * + * @see ModifiableBigInteger + * @see de.rub.nds.modifiablevariable.integer.IntegerXorModification + * @see de.rub.nds.modifiablevariable.longint.LongXorModification + */ @XmlRootElement public class BigIntegerXorModification extends VariableModification { + /** The BigInteger value to XOR with the original value */ private BigInteger xor; - public BigIntegerXorModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private BigIntegerXorModification() { super(); } + /** + * Creates a new modification with the specified XOR value. + * + *

This constructor sets the BigInteger value that will be XORed with the original value when + * the modification is applied. + * + * @param xor The BigInteger to XOR with the original value + * @throws NullPointerException if xor is null + */ public BigIntegerXorModification(BigInteger xor) { super(); - this.xor = xor; + this.xor = Objects.requireNonNull(xor, "Xor must not be null"); } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + *

This constructor creates a new instance with the same XOR value as the provided + * modification. + * + * @param other The modification to copy + */ public BigIntegerXorModification(BigIntegerXorModification other) { super(other); xor = other.xor; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same XOR mask + */ @Override public BigIntegerXorModification createCopy() { return new BigIntegerXorModification(this); } + /** + * Modifies the input by applying a bitwise XOR operation with the configured XOR mask. + * + *

This method uses BigInteger's native xor method which performs the operation on all bits + * regardless of the size of the values. The operation is performed bit by bit according to the + * standard XOR truth table (1⊕0=1, 0⊕1=1, 0⊕0=0, 1⊕1=0). + * + * @param input The BigInteger value to modify + * @return The result of XORing the input with the configured mask, or null if the input is null + */ @Override protected BigInteger modifyImplementationHook(BigInteger input) { if (input == null) { @@ -44,14 +90,30 @@ protected BigInteger modifyImplementationHook(BigInteger input) { return input.xor(xor); } + /** + * Gets the BigInteger value that will be XORed with the original value. + * + * @return The BigInteger XOR value + */ public BigInteger getXor() { return xor; } + /** + * Sets the BigInteger value that will be XORed with the original value. + * + * @param xor The new BigInteger value to use for XOR operations + * @throws NullPointerException if xor is null + */ public void setXor(BigInteger xor) { - this.xor = xor; + this.xor = Objects.requireNonNull(xor, "Xor must not be null"); } + /** + * Computes a hash code for this modification. The hash code is based on the XOR mask. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -59,6 +121,13 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two BigIntegerXorModification + * instances are considered equal if they have the same XOR mask. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -74,6 +143,11 @@ public boolean equals(Object obj) { return Objects.equals(xor, other.xor); } + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type and XOR mask + */ @Override public String toString() { return "BigIntegerXorModification{" + "xor=" + xor + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/ModifiableBigInteger.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/ModifiableBigInteger.java index 1414963b..2148fc72 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/ModifiableBigInteger.java +++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/ModifiableBigInteger.java @@ -12,51 +12,120 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.math.BigInteger; +/** + * A modifiable variable implementation for BigInteger values. + * + *

This class extends {@link ModifiableVariable} to provide runtime modification capabilities for + * BigInteger values. It supports various BigInteger-specific modifications like addition, + * multiplication, bit-shifts, XOR operations, and more. + * + * @see ModifiableVariable + * @see BigIntegerAddModification + * @see BigIntegerSubtractModification + * @see BigIntegerMultiplyModification + * @see BigIntegerShiftLeftModification + * @see BigIntegerShiftRightModification + * @see BigIntegerXorModification + */ @XmlRootElement public class ModifiableBigInteger extends ModifiableVariable { + /** The original BigInteger value before any modifications */ private BigInteger originalValue; + /** Default constructor that creates an empty ModifiableBigInteger with no original value. */ public ModifiableBigInteger() { super(); } + /** + * Constructor that creates a ModifiableBigInteger with the specified original value. + * + * @param originalValue The original BigInteger value + */ public ModifiableBigInteger(BigInteger originalValue) { super(); this.originalValue = originalValue; } + /** + * Copy constructor that creates a new ModifiableBigInteger with the same original value and + * modifications as the provided instance. + * + * @param other The ModifiableBigInteger to copy + */ public ModifiableBigInteger(ModifiableBigInteger other) { super(other); originalValue = other.originalValue; } + /** + * Creates a deep copy of this ModifiableBigInteger. + * + * @return A new ModifiableBigInteger instance with the same properties + */ @Override public ModifiableBigInteger createCopy() { return new ModifiableBigInteger(this); } + /** + * Gets the expected value for assertion validation. + * + * @return The assertion value + */ public BigInteger getAssertEquals() { return assertEquals; } + /** + * Sets the expected value for assertion validation. + * + * @param assertEquals The expected BigInteger value + */ public void setAssertEquals(BigInteger assertEquals) { this.assertEquals = assertEquals; } + /** + * Checks if the modified value differs from the original value. + * + * @return true if the value has been modified, false otherwise + * @throws IllegalStateException if the original value is null + */ @Override public boolean isOriginalValueModified() { - return originalValue != null && originalValue.compareTo(getValue()) != 0; + if (getOriginalValue() == null) { + throw new IllegalStateException("Original value must not be null"); + } else { + return originalValue.compareTo(getValue()) != 0; + } } + /** + * Converts the BigInteger value to an unsigned byte array with minimum required size. + * + * @return The byte array representation of the BigInteger + */ public byte[] getByteArray() { return ArrayConverter.bigIntegerToByteArray(getValue()); } + /** + * Converts the BigInteger value to an unsigned byte array of the specified size. + * + * @param size The size of the resulting byte array + * @return The byte array representation of the BigInteger + */ public byte[] getByteArray(int size) { return ArrayConverter.bigIntegerToByteArray(getValue(), size, true); } + /** + * Validates whether the modified value matches the expected value (if set). + * + * @return true if no assertion is set or if the current value equals the expected value + */ @Override public boolean validateAssertions() { if (assertEquals != null) { @@ -65,21 +134,43 @@ public boolean validateAssertions() { return true; } + /** + * Gets the original, unmodified BigInteger value. + * + * @return The original value + */ @Override public BigInteger getOriginalValue() { return originalValue; } + /** + * Sets the original BigInteger value. + * + * @param originalValue The new original value + */ @Override public void setOriginalValue(BigInteger originalValue) { this.originalValue = originalValue; } + /** + * Returns a string representation of this ModifiableBigInteger. + * + * @return A string containing the original value and modifications + */ @Override public String toString() { return "ModifiableBigInteger{" + "originalValue=" + originalValue + innerToString() + '}'; } + /** + * Checks if this ModifiableBigInteger is equal to another object. Two ModifiableBigInteger + * instances are considered equal if they have the same modified value. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -92,6 +183,12 @@ public boolean equals(Object obj) { return getValue() != null ? getValue().equals(that.getValue()) : that.getValue() == null; } + /** + * Computes a hash code for this ModifiableBigInteger. The hash code is based on the modified + * value rather than the original value. + * + * @return The hash code value + */ @Override public int hashCode() { int result = 17; diff --git a/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanExplicitValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanExplicitValueModification.java index 01f1625a..60c7c3a5 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanExplicitValueModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanExplicitValueModification.java @@ -10,30 +10,71 @@ import de.rub.nds.modifiablevariable.VariableModification; import jakarta.xml.bind.annotation.XmlRootElement; +/** + * A modification that replaces the original value with an explicitly defined boolean value. + * + *

This modification ignores the original value of a {@link ModifiableBoolean} and always returns + * a predefined boolean value specified at initialization or via setter. It can be used to force + * specific boolean states at runtime. + * + * @see ModifiableBoolean + * @see BooleanToggleModification + */ @XmlRootElement public class BooleanExplicitValueModification extends VariableModification { + /** The explicit boolean value that will replace the original value */ private boolean explicitValue; - public BooleanExplicitValueModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private BooleanExplicitValueModification() { super(); } + /** + * Creates a new modification with the specified explicit value. + * + *

This constructor sets the boolean value that will replace the original value when the + * modification is applied. + * + * @param explicitValue The boolean value that will replace the original value + */ public BooleanExplicitValueModification(boolean explicitValue) { super(); this.explicitValue = explicitValue; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public BooleanExplicitValueModification(BooleanExplicitValueModification other) { super(other); explicitValue = other.explicitValue; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same explicit value + */ @Override public BooleanExplicitValueModification createCopy() { return new BooleanExplicitValueModification(this); } + /** + * Implements the modification by returning the explicit value. + * + *

This method ignores the input value and always returns the explicit value set during + * initialization or via {@link #setExplicitValue(boolean)}. If the input is null, it returns + * null to preserve null-safety. + * + * @param input The original value (ignored except for null check) + * @return The explicit value, or null if input was null + */ @Override protected Boolean modifyImplementationHook(Boolean input) { if (input == null) { @@ -42,14 +83,31 @@ protected Boolean modifyImplementationHook(Boolean input) { return explicitValue; } + /** + * Gets the explicit value that will replace the original value. + * + * @return The explicit boolean value + */ public boolean getExplicitValue() { return explicitValue; } + /** + * Sets the explicit value that will replace the original value. + * + * @param explicitValue The new explicit boolean value to use + */ public void setExplicitValue(boolean explicitValue) { this.explicitValue = explicitValue; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the explicit value. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -57,6 +115,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two BooleanExplicitValueModification objects are considered equal if they have the same + * explicit value. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -72,6 +139,13 @@ public boolean equals(Object obj) { return explicitValue == other.explicitValue; } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and the explicit value. + * + * @return A string representation of this object + */ @Override public String toString() { return "BooleanExplicitValueModification{" + "explicitValue=" + explicitValue + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanToggleModification.java b/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanToggleModification.java index 4f832979..4ad94560 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanToggleModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanToggleModification.java @@ -10,22 +10,54 @@ import de.rub.nds.modifiablevariable.VariableModification; import jakarta.xml.bind.annotation.XmlRootElement; +/** + * A modification that inverts (toggles) a ModifiableBoolean value. + * + *

This modification inverts the input Boolean value when applied, turning true to false and + * false to true. It can be used to flip boolean flags at runtime + * + * @see ModifiableBoolean + * @see BooleanExplicitValueModification + */ @XmlRootElement public class BooleanToggleModification extends VariableModification { + /** Default constructor */ public BooleanToggleModification() { super(); } + /** + * Copy constructor. + * + * @param other The modification to copy + */ public BooleanToggleModification(BooleanToggleModification other) { super(other); } + /** + * Creates a deep copy of this modification. + * + * @return A new instance of BooleanToggleModification + */ @Override public BooleanToggleModification createCopy() { return new BooleanToggleModification(this); } + /** + * Modifies the input by inverting its boolean value. + * + *

If the input is true, returns false. + * + *

If the input is false, returns true. + * + *

If the input is null, returns null. + * + * @param input The Boolean value to invert + * @return The inverted Boolean value, or null if the input is null + */ @Override protected Boolean modifyImplementationHook(Boolean input) { if (input == null) { @@ -34,11 +66,28 @@ protected Boolean modifyImplementationHook(Boolean input) { return !input; } + /** + * Computes a hash code for this modification. + * + *

Since this modification has no configurable parameters, all instances are functionally + * identical and return the same hash code. + * + * @return A constant hash code + */ @Override public int hashCode() { return 7; } + /** + * Checks if this modification is equal to another object. + * + *

Since this modification has no configurable parameters, it equals any other instance of + * the same class. + * + * @param obj The object to compare with + * @return true if the object is a BooleanToggleModification, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -50,6 +99,11 @@ public boolean equals(Object obj) { return getClass() == obj.getClass(); } + /** + * Returns a string representation of this modification. + * + * @return A string identifying this modification type + */ @Override public String toString() { return "BooleanToggleModification{" + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/bool/ModifiableBoolean.java b/src/main/java/de/rub/nds/modifiablevariable/bool/ModifiableBoolean.java index b695ca89..e11f3a03 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/bool/ModifiableBoolean.java +++ b/src/main/java/de/rub/nds/modifiablevariable/bool/ModifiableBoolean.java @@ -10,45 +10,98 @@ import de.rub.nds.modifiablevariable.ModifiableVariable; import jakarta.xml.bind.annotation.XmlRootElement; +/** + * A modifiable variable implementation for Boolean values. + * + *

This class extends {@link ModifiableVariable} to provide runtime modification capabilities for + * Boolean values. + * + * @see ModifiableVariable + * @see BooleanExplicitValueModification + * @see BooleanToggleModification + */ @XmlRootElement public class ModifiableBoolean extends ModifiableVariable { + /** The original Boolean value before any modifications */ private Boolean originalValue; + /** Default constructor that creates an empty ModifiableBoolean with no original value. */ public ModifiableBoolean() { super(); } + /** + * Constructor that creates a ModifiableBoolean with the specified original value. + * + * @param originalValue The original Boolean value + */ public ModifiableBoolean(Boolean originalValue) { super(); this.originalValue = originalValue; } + /** + * Copy constructor that creates a new ModifiableBoolean with the same original value and + * modifications as the provided instance. + * + * @param other The ModifiableBoolean to copy + */ public ModifiableBoolean(ModifiableBoolean other) { super(other); originalValue = other.originalValue; } + /** + * Creates a deep copy of this ModifiableBoolean. + * + * @return A new ModifiableBoolean instance with the same properties + */ @Override public ModifiableBoolean createCopy() { return new ModifiableBoolean(this); } + /** + * Gets the original, unmodified Boolean value. + * + * @return The original value + */ @Override public Boolean getOriginalValue() { return originalValue; } + /** + * Sets the original Boolean value. + * + * @param originalValue The new original value + */ @Override public void setOriginalValue(Boolean originalValue) { this.originalValue = originalValue; } + /** + * Checks if the modified value differs from the original value. + * + * @return true if the value has been modified, false otherwise + * @throws IllegalStateException if the original value is null + */ @Override public boolean isOriginalValueModified() { - return originalValue != null && originalValue.compareTo(getValue()) != 0; + if (getOriginalValue() == null) { + throw new IllegalStateException("Original value must not be null"); + } else { + return originalValue.compareTo(getValue()) != 0; + } } + /** + * Validates whether the modified value matches the expected value (if set). + * + * @return true if no assertion is set or if the current value equals the expected value + */ @Override public boolean validateAssertions() { if (assertEquals != null) { @@ -57,11 +110,23 @@ public boolean validateAssertions() { return true; } + /** + * Returns a string representation of this ModifiableBoolean. + * + * @return A string containing the original value and modifications + */ @Override public String toString() { return "ModifiableBoolean{" + "originalValue=" + originalValue + innerToString() + '}'; } + /** + * Checks if this ModifiableBoolean is equal to another object. Two ModifiableBoolean instances + * are considered equal if they have the same modified value. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -74,6 +139,12 @@ public boolean equals(Object obj) { return getValue() != null ? getValue().equals(that.getValue()) : that.getValue() == null; } + /** + * Computes a hash code for this ModifiableBoolean. The hash code is based on the modified value + * rather than the original value. + * + * @return The hash code value + */ @Override public int hashCode() { int result = 17; diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayAppendValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayAppendValueModification.java index 25a7c8df..c5be4a38 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayAppendValueModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayAppendValueModification.java @@ -13,32 +13,84 @@ import jakarta.xml.bind.annotation.XmlRootElement; import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.util.Arrays; +import java.util.Objects; +/** + * A modification that appends additional bytes to the end of a ModifiableByteArray. + * + *

This modification takes the original byte array and concatenates a specified array of bytes to + * its end. + * + *

When applied, this modification creates a new byte array that is the concatenation of the + * original byte array followed by the bytes to append. The original byte array remains unchanged. + * + * @see ModifiableByteArray + * @see ByteArrayPrependValueModification + */ @XmlRootElement public class ByteArrayAppendValueModification extends VariableModification { + /** The bytes to append to the end of the original byte array */ @XmlJavaTypeAdapter(UnformattedByteArrayAdapter.class) private byte[] bytesToAppend; - public ByteArrayAppendValueModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private ByteArrayAppendValueModification() { super(); } + /** + * Creates a new modification with the specified bytes to append. + * + *

This constructor sets the bytes that will be appended to the original byte array when the + * modification is applied. + * + * @param bytesToAppend The bytes to append to the original byte array + * @throws NullPointerException if bytesToAppend is null + */ public ByteArrayAppendValueModification(byte[] bytesToAppend) { super(); - this.bytesToAppend = bytesToAppend; + this.bytesToAppend = + Objects.requireNonNull(bytesToAppend, "bytesToAppend must not be null"); } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + *

This constructor creates a new instance with a clone of the bytes to append from the + * provided modification. + * + * @param other The modification to copy + */ public ByteArrayAppendValueModification(ByteArrayAppendValueModification other) { super(other); bytesToAppend = other.bytesToAppend != null ? other.bytesToAppend.clone() : null; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with a clone of the bytes to append + */ @Override public ByteArrayAppendValueModification createCopy() { return new ByteArrayAppendValueModification(this); } + /** + * Modifies the input by appending bytes to the end of the array. + * + *

This method concatenates the bytes to append to the end of the input byte array using the + * ArrayConverter's concatenate method. A new byte array is created with the original input + * bytes followed by the bytes to append. + * + *

Note that this operation creates a new array that is longer than the original input by the + * length of the bytes to append. The original input remains unchanged. + * + * @param input The original byte array + * @return A new byte array with the bytes appended, or null if input was null + */ @Override protected byte[] modifyImplementationHook(byte[] input) { if (input == null) { @@ -47,14 +99,33 @@ protected byte[] modifyImplementationHook(byte[] input) { return ArrayConverter.concatenate(input, bytesToAppend); } + /** + * Gets the bytes that will be appended to the original byte array. + * + * @return The bytes to append + */ public byte[] getBytesToAppend() { return bytesToAppend; } + /** + * Sets the bytes that will be appended to the original byte array. + * + * @param bytesToAppend The new bytes to append to the original byte array + * @throws NullPointerException if bytesToAppend is null + */ public void setBytesToAppend(byte[] bytesToAppend) { - this.bytesToAppend = bytesToAppend; + this.bytesToAppend = + Objects.requireNonNull(bytesToAppend, "BytesToAppend must not be null"); } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the bytes to append. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -62,6 +133,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two ByteArrayAppendValueModification objects are considered equal if they have the same + * bytes to append. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -77,9 +157,16 @@ public boolean equals(Object obj) { return Arrays.equals(bytesToAppend, other.bytesToAppend); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and the bytes to append as a hexadecimal string. + * + * @return A string representation of this object + */ @Override public String toString() { - return "ByteArrayInsertModification{bytesToAppend=" + return "ByteArrayAppendValueModification{bytesToAppend=" + ArrayConverter.bytesToHexString(bytesToAppend) + "}"; } diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayDeleteModification.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayDeleteModification.java index 8e41844b..2031ae9b 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayDeleteModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayDeleteModification.java @@ -12,34 +12,84 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Arrays; +/** + * A modification that deletes a portion of a ModifiableByteArray. + * + *

This modification removes a specified number of bytes from the original byte array starting at + * a specified position when applied. It can be used to create truncated or partial data at runtime. + * + *

The result is always a new byte array with the specified portion removed, preserving the + * immutability of the original data. + * + * @see ModifiableByteArray + */ @XmlRootElement public class ByteArrayDeleteModification extends VariableModification { + /** The number of bytes to delete */ private int count; + /** The position from which to start deletion (0-based index) */ private int startPosition; - public ByteArrayDeleteModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private ByteArrayDeleteModification() { super(); } + /** + * Creates a new delete modification with the specified parameters. + * + * @param startPosition The position from which to start deleting (0-based index) + * @param count The number of bytes to delete + */ public ByteArrayDeleteModification(int startPosition, int count) { super(); this.startPosition = startPosition; this.count = count; } + /** + * Copy constructor creating a deep copy of the provided modification. + * + * @param other The modification to copy + */ public ByteArrayDeleteModification(ByteArrayDeleteModification other) { super(other); count = other.count; startPosition = other.startPosition; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same deletion parameters + */ @Override public ByteArrayDeleteModification createCopy() { return new ByteArrayDeleteModification(this); } + /** + * Modifies the input by removing bytes from the specified position. + * + *

This method creates a new byte array with the specified section removed. It effectively + * takes the bytes before the deletion point, then concatenates them with the bytes after the + * deletion point, creating a shorter array. + * + *

The implementation handles several edge cases to ensure robustness: + * + *

+ * + * @param input The byte array to modify + * @return A new byte array with the specified portion removed, or null if input was null + */ @Override protected byte[] modifyImplementationHook(byte[] input) { if (input == null) { @@ -69,22 +119,49 @@ protected byte[] modifyImplementationHook(byte[] input) { return ret1; } + /** + * Gets the starting position for deletion. + * + * @return The position from which to start deleting (0-based index) + */ public int getStartPosition() { return startPosition; } + /** + * Sets the starting position for deletion. + * + * @param startPosition The position from which to start deleting (0-based index) + */ public void setStartPosition(int startPosition) { this.startPosition = startPosition; } + /** + * Gets the number of bytes to delete. + * + * @return The number of bytes to delete + */ public int getCount() { return count; } + /** + * Sets the number of bytes to delete. + * + * @param count The number of bytes to delete + */ public void setCount(int count) { this.count = count; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based on the count and startPosition fields. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -93,6 +170,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two ByteArrayDeleteModification objects are considered equal if they have the same count + * and startPosition values. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -111,6 +197,13 @@ public boolean equals(Object obj) { return startPosition == other.startPosition; } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and the values of the count and startPosition fields. + * + * @return A string representation of this object + */ @Override public String toString() { return "ByteArrayDeleteModification{" diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayDuplicateModification.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayDuplicateModification.java index a11c806d..ac6acb7e 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayDuplicateModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayDuplicateModification.java @@ -11,22 +11,62 @@ import de.rub.nds.modifiablevariable.util.ArrayConverter; import jakarta.xml.bind.annotation.XmlRootElement; +/** + * A modification that duplicates a ModifiableByteArray by concatenating it with itself. + * + *

This modification takes the original byte array and appends a copy of itself, effectively + * doubling its length. It can be used to create repeated data sequences at runtime. + * + *

For example, given the byte array {@code {0x01, 0x02, 0x03}}, this modification would produce + * {@code {0x01, 0x02, 0x03, 0x01, 0x02, 0x03}}. + * + * @see ModifiableByteArray + * @see ByteArrayAppendValueModification + */ @XmlRootElement public class ByteArrayDuplicateModification extends VariableModification { + /** Default constructor */ public ByteArrayDuplicateModification() { super(); } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public ByteArrayDuplicateModification(ByteArrayDuplicateModification other) { super(other); } + /** + * Creates a deep copy of this modification. + * + *

Since this modification is stateless, all instances are equivalent. + * + * @return A new instance of this modification + */ @Override public ByteArrayDuplicateModification createCopy() { return new ByteArrayDuplicateModification(this); } + /** + * Modifies the input by duplicating the byte array. + * + *

This method creates a new byte array that consists of the input array concatenated with a + * copy of itself, effectively doubling the length of the array. The operation preserves the + * original array's contents and ordering, simply repeating it. + * + *

The implementation uses the ArrayConverter's concatenate method for efficient array + * manipulation and guarantees that the original array is not modified, maintaining + * immutability. + * + * @param input The original byte array + * @return A new byte array consisting of the input array concatenated with itself, or null if + * input was null + */ @Override protected byte[] modifyImplementationHook(byte[] input) { if (input == null) { @@ -35,11 +75,28 @@ protected byte[] modifyImplementationHook(byte[] input) { return ArrayConverter.concatenate(input, input); } + /** + * Computes a hash code for this modification. + * + *

Since this modification is stateless, a constant hash code is returned. + * + * @return A constant hash code value for all instances of this class + */ @Override public int hashCode() { return 7; } + /** + * Compares this modification with another object for equality. + * + *

Since this modification is stateless, all instances of this class are considered equal to + * each other. + * + * @param obj The object to compare with + * @return {@code true} if the object is also a ByteArrayDuplicateModification, {@code false} + * otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -51,8 +108,15 @@ public boolean equals(Object obj) { return getClass() == obj.getClass(); } + /** + * Returns a string representation of this modification. + * + *

Since this modification is stateless, the string only includes the class name. + * + * @return A string representation of this object + */ @Override public String toString() { - return "ByteArrayDuplicateModification{" + '}'; + return "ByteArrayDuplicateModification{}"; } } diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayExplicitValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayExplicitValueModification.java index 3ec57152..a2c86c5a 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayExplicitValueModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayExplicitValueModification.java @@ -13,32 +13,70 @@ import jakarta.xml.bind.annotation.XmlRootElement; import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.util.Arrays; +import java.util.Objects; +/** + * A modification that replaces the original byte array with an explicitly defined value. + * + *

This modification ignores the original value and always returns a predefined byte array + * specified at initialization or via setter. It can be used to inject specific byte sequences + * regardless of the original content. + * + * @see ModifiableByteArray + */ @XmlRootElement public class ByteArrayExplicitValueModification extends VariableModification { + /** The explicit byte array that will replace the original value */ @XmlJavaTypeAdapter(UnformattedByteArrayAdapter.class) - protected byte[] explicitValue; + private byte[] explicitValue; - public ByteArrayExplicitValueModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private ByteArrayExplicitValueModification() { super(); } + /** + * Creates a new explicit value modification with the specified value. + * + * @param explicitValue The byte array that will replace the original value + */ public ByteArrayExplicitValueModification(byte[] explicitValue) { super(); - this.explicitValue = explicitValue; + this.explicitValue = + Objects.requireNonNull(explicitValue, "ExplicitValue must not be null"); } + /** + * Copy constructor. + * + * @param other The modification to copy + */ public ByteArrayExplicitValueModification(ByteArrayExplicitValueModification other) { super(other); explicitValue = other.explicitValue != null ? other.explicitValue.clone() : null; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with a clone of the explicit value + */ @Override public ByteArrayExplicitValueModification createCopy() { return new ByteArrayExplicitValueModification(this); } + /** + * Modifies the input by replacing it with the explicit value. + * + *

This method ignores the input value and always returns a clone of the explicit value. A + * defensive copy is returned to prevent modification of the internal value. + * + * @param input The original byte array (ignored except for null check) + * @return A clone of the explicit value, or null if input was null + */ @Override protected byte[] modifyImplementationHook(byte[] input) { if (input == null) { @@ -47,22 +85,30 @@ protected byte[] modifyImplementationHook(byte[] input) { return explicitValue.clone(); } + /** + * Gets the explicit value that will replace the original value. + * + * @return The explicit byte array + */ public byte[] getExplicitValue() { return explicitValue; } + /** + * Sets the explicit value that will replace the original value. + * + * @param explicitValue The new explicit byte array to use + */ public void setExplicitValue(byte[] explicitValue) { - this.explicitValue = explicitValue; - } - - @Override - public String toString() { - return "ByteArrayExplicitValueModification{" - + "explicitValue=" - + ArrayConverter.bytesToHexString(explicitValue) - + '}'; + this.explicitValue = + Objects.requireNonNull(explicitValue, "ExplicitValue must not be null"); } + /** + * Computes a hash code for this modification. The hash code is based on the explicit value. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -70,6 +116,14 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two + * ByteArrayExplicitValueModification instances are considered equal if they have the same + * explicit value (compared by content). + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -84,4 +138,17 @@ public boolean equals(Object obj) { ByteArrayExplicitValueModification other = (ByteArrayExplicitValueModification) obj; return Arrays.equals(explicitValue, other.explicitValue); } + + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type and explicit value as hex + */ + @Override + public String toString() { + return "ByteArrayExplicitValueModification{" + + "explicitValue=" + + ArrayConverter.bytesToHexString(explicitValue) + + '}'; + } } diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayInsertValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayInsertValueModification.java index 88ea912f..41476a3d 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayInsertValueModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayInsertValueModification.java @@ -13,36 +13,97 @@ import jakarta.xml.bind.annotation.XmlRootElement; import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.util.Arrays; +import java.util.Objects; +/** + * A modification that inserts bytes at a specified position within a ModifiableByteArray. + * + *

This modification takes the original byte array and inserts additional bytes at a specified + * position when applied. It can be used to inject data into specific locations at runtime. + * + *

When applied, this modification creates a new byte array with the specified bytes inserted at + * the designated position, preserving all original data before and after the insertion point. + * + * @see ModifiableByteArray + * @see ByteArrayAppendValueModification + * @see ByteArrayPrependValueModification + */ @XmlRootElement public class ByteArrayInsertValueModification extends VariableModification { + /** The bytes to insert into the original byte array */ @XmlJavaTypeAdapter(UnformattedByteArrayAdapter.class) private byte[] bytesToInsert; + /** The position at which to insert the bytes (0-based index) */ private int startPosition; - public ByteArrayInsertValueModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private ByteArrayInsertValueModification() { super(); } + /** + * Creates a new modification with the specified bytes and position. + * + *

This constructor sets the bytes to insert and the position at which to insert them when + * the modification is applied. + * + * @param bytesToInsert The bytes to insert into the original array + * @param startPosition The position at which to insert the bytes (0-based index) + * @throws NullPointerException if bytesToInsert is null + */ public ByteArrayInsertValueModification(byte[] bytesToInsert, int startPosition) { super(); - this.bytesToInsert = bytesToInsert; + this.bytesToInsert = + Objects.requireNonNull(bytesToInsert, "BytesToInsert must not be null"); this.startPosition = startPosition; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public ByteArrayInsertValueModification(ByteArrayInsertValueModification other) { super(other); bytesToInsert = other.bytesToInsert != null ? other.bytesToInsert.clone() : null; startPosition = other.startPosition; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same insertion parameters + */ @Override public ByteArrayInsertValueModification createCopy() { return new ByteArrayInsertValueModification(this); } + /** + * Modifies the input by inserting bytes at the specified position. + * + *

This method creates a new byte array with the specified bytes inserted at the designated + * position. It works by: 1. Copying the portion of the input array before the insertion point + * 2. Adding the bytes to insert 3. Appending the remainder of the input array after the + * insertion point + * + *

The position calculation handles various edge cases gracefully: + * + *

+ * + *

The implementation uses ArrayConverter for efficient concatenation operations, ensuring + * optimal performance even with large arrays. + * + * @param input The original byte array + * @return A new byte array with the bytes inserted at the specified position, or null if input + * was null + */ @Override protected byte[] modifyImplementationHook(byte[] input) { if (input == null) { @@ -62,22 +123,51 @@ protected byte[] modifyImplementationHook(byte[] input) { return ArrayConverter.concatenate(ret1, bytesToInsert); } + /** + * Gets the bytes that will be inserted into the original array. + * + * @return The bytes to insert + */ public byte[] getBytesToInsert() { return bytesToInsert; } + /** + * Sets the bytes that will be inserted into the original array. + * + * @param bytesToInsert The new bytes to insert + * @throws NullPointerException if bytesToInsert is null + */ public void setBytesToInsert(byte[] bytesToInsert) { - this.bytesToInsert = bytesToInsert; + this.bytesToInsert = + Objects.requireNonNull(bytesToInsert, "bytesToInsert must not be null"); } + /** + * Gets the position at which the bytes will be inserted. + * + * @return The insertion position (0-based index) + */ public int getStartPosition() { return startPosition; } + /** + * Sets the position at which the bytes will be inserted. + * + * @param startPosition The new insertion position (0-based index) + */ public void setStartPosition(int startPosition) { this.startPosition = startPosition; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based on the bytes to insert and start position. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -86,6 +176,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two ByteArrayInsertValueModification objects are considered equal if they have the same + * bytes to insert and start position. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -104,6 +203,14 @@ public boolean equals(Object obj) { return Arrays.equals(bytesToInsert, other.bytesToInsert); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name, bytes to insert (in hexadecimal format), and start + * position. + * + * @return A string representation of this object + */ @Override public String toString() { return "ByteArrayInsertModification{" diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayPrependValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayPrependValueModification.java index 9bffe16f..68f692b6 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayPrependValueModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayPrependValueModification.java @@ -13,32 +13,86 @@ import jakarta.xml.bind.annotation.XmlRootElement; import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.util.Arrays; +import java.util.Objects; +/** + * A modification that prepends additional bytes to the beginning of a ModifiableByteArray. + * + *

This modification takes the original byte array and adds a specified array of bytes to its + * beginning. + * + *

When applied, this modification creates a new byte array that is the concatenation of the + * bytes to prepend followed by the original byte array. The original byte array remains unchanged. + * + * @see ModifiableByteArray + * @see ByteArrayAppendValueModification + * @see ByteArrayInsertValueModification + */ @XmlRootElement public class ByteArrayPrependValueModification extends VariableModification { + /** The bytes to prepend to the beginning of the original byte array */ @XmlJavaTypeAdapter(UnformattedByteArrayAdapter.class) private byte[] bytesToPrepend; - public ByteArrayPrependValueModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private ByteArrayPrependValueModification() { super(); } + /** + * Creates a new modification with the specified bytes to prepend. + * + *

This constructor sets the bytes that will be prepended to the original byte array when the + * modification is applied. + * + * @param bytesToPrepend The bytes to prepend to the original byte array + * @throws NullPointerException if bytesToPrepend is null + */ public ByteArrayPrependValueModification(byte[] bytesToPrepend) { super(); - this.bytesToPrepend = bytesToPrepend; + this.bytesToPrepend = + Objects.requireNonNull(bytesToPrepend, "bytesToPrepend must not be null"); } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + *

This constructor creates a new instance with a clone of the bytes to prepend from the + * provided modification. + * + * @param other The modification to copy + */ public ByteArrayPrependValueModification(ByteArrayPrependValueModification other) { super(other); bytesToPrepend = other.bytesToPrepend != null ? other.bytesToPrepend.clone() : null; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with a clone of the bytes to prepend + */ @Override public ByteArrayPrependValueModification createCopy() { return new ByteArrayPrependValueModification(this); } + /** + * Modifies the input by prepending bytes to the beginning of the array. + * + *

This method concatenates the bytes to prepend with the input byte array using the + * ArrayConverter's concatenate method. A new byte array is created with the bytes to prepend at + * the beginning followed by the original input bytes. + * + *

Note that this operation creates a new array that is longer than the original input by the + * length of the bytes to prepend. This can be useful for testing how protocol implementations + * handle unexpected additional data. + * + * @param input The original byte array + * @return A new byte array with the bytes prepended, or null if input was null + */ @Override protected byte[] modifyImplementationHook(byte[] input) { if (input == null) { @@ -47,14 +101,33 @@ protected byte[] modifyImplementationHook(byte[] input) { return ArrayConverter.concatenate(bytesToPrepend, input); } + /** + * Gets the bytes that will be prepended to the original byte array. + * + * @return The bytes to prepend + */ public byte[] getBytesToPrepend() { return bytesToPrepend; } + /** + * Sets the bytes that will be prepended to the original byte array. + * + * @param bytesToPrepend The new bytes to prepend to the original byte array + * @throws NullPointerException if bytesToPrepend is null + */ public void setBytesToPrepend(byte[] bytesToPrepend) { - this.bytesToPrepend = bytesToPrepend; + this.bytesToPrepend = + Objects.requireNonNull(bytesToPrepend, "bytesToPrepend must not be null"); } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the bytes to prepend. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -62,6 +135,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two ByteArrayPrependValueModification objects are considered equal if they have the same + * bytes to prepend (compared by content, not reference). + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -77,6 +159,13 @@ public boolean equals(Object obj) { return Arrays.equals(bytesToPrepend, other.bytesToPrepend); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and the bytes to prepend as a hexadecimal string. + * + * @return A string representation of this object + */ @Override public String toString() { return "ByteArrayPrependValueModification{bytesToPrepend=" diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayShuffleModification.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayShuffleModification.java index 150e6311..03d08b97 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayShuffleModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayShuffleModification.java @@ -8,77 +8,150 @@ package de.rub.nds.modifiablevariable.bytearray; import de.rub.nds.modifiablevariable.VariableModification; -import de.rub.nds.modifiablevariable.util.ArrayConverter; -import de.rub.nds.modifiablevariable.util.UnformattedByteArrayAdapter; import jakarta.xml.bind.annotation.XmlRootElement; -import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.util.Arrays; +import java.util.Objects; /** - * Shuffles the byte array, using a pre-defined array of array pointers (#shuffle). Array pointers - * are currently defined as bytes, since we are modifying rather smaller arrays. + * A modification that shuffles elements within a ModifiableByteArray. + * + *

+ * This modification reorders elements within the byte array by performing a + * series of swap + * operations based on a predefined shuffle pattern. It can be used to create + * data with the same + * content but in a different order at runtime. + * + *

+ * The transformation always produces a byte array with the same length and the + * same elements as + * the input, just in a different order, making it valuable for testing protocol + * sensitivity to + * element ordering without changing the actual content. + * + * @see ModifiableByteArray */ @XmlRootElement public class ByteArrayShuffleModification extends VariableModification { - @XmlJavaTypeAdapter(UnformattedByteArrayAdapter.class) - private byte[] shuffle; + /** The shuffle pattern defining which indices to swap */ + private int[] shuffle; - public ByteArrayShuffleModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private ByteArrayShuffleModification() { super(); } - public ByteArrayShuffleModification(byte[] shuffle) { + /** + * Creates a new shuffle modification with the specified shuffle pattern. + * + * @param shuffle The int array containing the shuffle pattern defining which + * indices to swap + * @throws NullPointerException if shuffle is null + */ + public ByteArrayShuffleModification(int[] shuffle) { super(); - this.shuffle = shuffle; + this.shuffle = Objects.requireNonNull(shuffle, "Shuffle pattern must not be null"); } + /** + * Copy constructor creating a deep copy of the provided modification. + * + *

+ * This creates a new instance with a copy of the shuffle pattern array. + * + * @param other The modification to copy + */ public ByteArrayShuffleModification(ByteArrayShuffleModification other) { super(other); shuffle = other.shuffle != null ? other.shuffle.clone() : null; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with a copy of the shuffle pattern + */ @Override public ByteArrayShuffleModification createCopy() { return new ByteArrayShuffleModification(this); } + /** + * Modifies the input by shuffling bytes according to the specified pattern. + * + *

+ * This method creates a copy of the input array and performs a series of swap + * operations as + * defined by the shuffle pattern. The original array is not modified, + * preserving immutability. + * + *

+ * Each index in the shuffle pattern is taken modulo the length of the input + * array to ensure + * that all swaps are performed within bounds, even if the shuffle pattern was + * designed for + * arrays of a different size. + * + *

+ * The shuffle pattern is interpreted as pairs of indices to swap. For example, + * the pattern + * [0, 1, 2, 3] would swap [0] with [1] and [2] with [3]. + * + * @param input The byte array to shuffle + * @return A new byte array containing the same elements as the input but in + * shuffled order, or + * null if the input is null + */ @Override protected byte[] modifyImplementationHook(byte[] input) { if (input == null) { return null; } + if (input.length == 0) { + return input; + } byte[] result = input.clone(); int size = input.length; - if (size > 255) { - for (int i = 0; i < shuffle.length - 3; i += 4) { - // Combine two consecutive bytes to form 16-bit values - int p1 = ((shuffle[i] & 0xff) << 8 | shuffle[i + 1] & 0xff) % size; - int p2 = ((shuffle[i + 2] & 0xff) << 8 | shuffle[i + 3] & 0xff) % size; - byte tmp = result[p1]; - result[p1] = result[p2]; - result[p2] = tmp; - } - } else if (size > 0) { - for (int i = 0; i < shuffle.length - 1; i += 2) { - int p1 = (shuffle[i] & 0xff) % size; - int p2 = (shuffle[i + 1] & 0xff) % size; - byte tmp = result[p1]; - result[p1] = result[p2]; - result[p2] = tmp; - } + for (int i = 0; i < shuffle.length - 1; i += 2) { + int p1 = (shuffle[i] & 0xff) % size; + int p2 = (shuffle[i + 1] & 0xff) % size; + byte tmp = result[p1]; + result[p1] = result[p2]; + result[p2] = tmp; } return result; } - public byte[] getShuffle() { + /** + * Gets the shuffle pattern array. + * + * @return The int array containing the shuffle pattern + */ + public int[] getShuffle() { return shuffle; } - public void setShuffle(byte[] shuffle) { - this.shuffle = shuffle; + /** + * Sets the shuffle pattern array. + * + * @param shuffle The int array containing the shuffle pattern defining which + * indices to swap + * @throws NullPointerException if shuffle is null + */ + public void setShuffle(int[] shuffle) { + this.shuffle = Objects.requireNonNull(shuffle, "Shuffle pattern must not be null"); } + /** + * Computes a hash code for this shuffle modification. + * + *

+ * The hash code is based solely on the shuffle pattern array. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -86,6 +159,17 @@ public int hashCode() { return hash; } + /** + * Compares this shuffle modification with another object for equality. + * + *

+ * Two ByteArrayShuffleModification objects are considered equal if they have + * identical + * shuffle pattern arrays. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -101,11 +185,16 @@ public boolean equals(Object obj) { return Arrays.equals(shuffle, other.shuffle); } + /** + * Returns a string representation of this shuffle modification. + * + *

+ * The string includes the shuffle pattern as a list of ints. + * + * @return A string representation of this object + */ @Override public String toString() { - return "ByteArrayShuffleModification{" - + "shuffle=" - + ArrayConverter.bytesToHexString(shuffle) - + '}'; + return "ByteArrayShuffleModification{" + "shuffle=" + Arrays.toString(shuffle) + '}'; } } diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayXorModification.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayXorModification.java index 89e96ca9..ff92ad07 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayXorModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayXorModification.java @@ -13,36 +13,87 @@ import jakarta.xml.bind.annotation.XmlRootElement; import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.util.Arrays; +import java.util.Objects; +/** + * A modification that applies an XOR operation to a portion of a ModifiableByteArray. + * + *

This modification performs a bitwise XOR operation between a specified byte array and the + * input byte array, starting at a specified position when applied. It can be used to selectively + * alter specific bytes or bits at runtime. + * + * @see ModifiableByteArray + */ @XmlRootElement public class ByteArrayXorModification extends VariableModification { + /** The byte array to XOR with the original byte array */ @XmlJavaTypeAdapter(UnformattedByteArrayAdapter.class) private byte[] xor; + /** The position in the original byte array where the XOR operation starts */ private int startPosition; - public ByteArrayXorModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private ByteArrayXorModification() { super(); } + /** + * Creates a new XOR modification with the specified parameters. + * + * @param xor The byte array to XOR with the original value + * @param startPosition The position in the original array to start the XOR operation + * @throws NullPointerException if xor is null + */ public ByteArrayXorModification(byte[] xor, int startPosition) { super(); - this.xor = xor; + this.xor = Objects.requireNonNull(xor, "XOR array must not be null"); this.startPosition = startPosition; } + /** + * Copy constructor. + * + *

Creates a deep copy of the XOR byte array to prevent unintended modifications. + * + * @param other The modification to copy + */ public ByteArrayXorModification(ByteArrayXorModification other) { super(other); xor = other.xor != null ? other.xor.clone() : null; startPosition = other.startPosition; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same XOR array and start position + */ @Override public ByteArrayXorModification createCopy() { return new ByteArrayXorModification(this); } + /** + * Modifies the input by applying an XOR operation with the configured XOR array. + * + *

The XOR operation starts at the specified position in the input array. If the operation + * would extend beyond the end of the input, only the overlapping portion is modified. + * + *

The modification handles special cases: + * + *

+ * + * @param input The byte array to modify + * @return A new byte array with the XOR operation applied, or null if the input is null + */ @Override protected byte[] modifyImplementationHook(byte[] input) { if (input == null) { @@ -72,22 +123,48 @@ protected byte[] modifyImplementationHook(byte[] input) { return result; } + /** + * Gets the byte array used for the XOR operation. + * + * @return The XOR byte array + */ public byte[] getXor() { return xor; } + /** + * Sets the byte array to use for the XOR operation. + * + * @param xor The new XOR byte array + */ public void setXor(byte[] xor) { this.xor = xor; } + /** + * Gets the position where the XOR operation starts in the original array. + * + * @return The start position for the XOR operation + */ public int getStartPosition() { return startPosition; } + /** + * Sets the position where the XOR operation should start in the original array. + * + * @param startPosition The new start position for the XOR operation + */ public void setStartPosition(int startPosition) { this.startPosition = startPosition; } + /** + * Computes a hash code for this modification. The hash code is based on the XOR array and start + * position. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -96,6 +173,13 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two ByteArrayXorModification + * instances are considered equal if they have the same XOR array and start position. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -114,6 +198,12 @@ public boolean equals(Object obj) { return Arrays.equals(xor, other.xor); } + /** + * Returns a string representation of this modification. The XOR array is formatted as a + * hexadecimal string for readability. + * + * @return A string describing this modification + */ @Override public String toString() { return "ByteArrayXorModification{" diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ModifiableByteArray.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ModifiableByteArray.java index 4f98986a..4fefefdf 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ModifiableByteArray.java +++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ModifiableByteArray.java @@ -16,57 +16,145 @@ import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.util.Arrays; +/** + * A modifiable variable implementation for byte arrays. + * + *

This class extends {@link ModifiableVariable} to provide runtime modification capabilities for + * byte array values. It supports various byte array-specific modifications such as: + * + *

+ * + * @see ModifiableVariable + * @see ByteArrayAppendValueModification + * @see ByteArrayPrependValueModification + * @see ByteArrayInsertValueModification + * @see ByteArrayDeleteModification + * @see ByteArrayDuplicateModification + * @see ByteArrayXorModification + * @see ByteArrayShuffleModification + */ @XmlRootElement @XmlAccessorType(XmlAccessType.PROPERTY) public class ModifiableByteArray extends ModifiableVariable { + /** The original byte array value before any modifications */ private byte[] originalValue; + /** Default constructor that creates an empty ModifiableByteArray with no original value. */ public ModifiableByteArray() { super(); } + /** + * Constructor that creates a ModifiableByteArray with the specified original value. + * + * @param originalValue The original byte array value + */ public ModifiableByteArray(byte[] originalValue) { super(); this.originalValue = originalValue; } + /** + * Copy constructor that creates a new ModifiableByteArray with the same original value and + * modifications as the provided instance. + * + *

Both the original value and assertion value are deep-copied using clone() to prevent + * unintended modifications. + * + * @param other The ModifiableByteArray to copy + */ public ModifiableByteArray(ModifiableByteArray other) { super(other); originalValue = other.originalValue != null ? other.originalValue.clone() : null; assertEquals = other.assertEquals != null ? other.assertEquals.clone() : null; } + /** + * Creates a deep copy of this ModifiableByteArray. + * + * @return A new ModifiableByteArray instance with the same properties + */ @Override public ModifiableByteArray createCopy() { return new ModifiableByteArray(this); } + /** + * Gets the original, unmodified byte array value. + * + *

The XML adapter ensures proper serialization of the byte array. + * + * @return The original byte array value + */ @Override @XmlJavaTypeAdapter(UnformattedByteArrayAdapter.class) public byte[] getOriginalValue() { return originalValue; } + /** + * Sets the original byte array value. + * + * @param originalValue The new original byte array value + */ @Override public void setOriginalValue(byte[] originalValue) { this.originalValue = originalValue; } + /** + * Gets the expected value for assertion validation. + * + *

The XML adapter ensures proper serialization of the byte array. + * + * @return The assertion value + */ @XmlJavaTypeAdapter(UnformattedByteArrayAdapter.class) public byte[] getAssertEquals() { return assertEquals; } + /** + * Sets the expected value for assertion validation. + * + * @param assertEquals The expected byte array value + */ public void setAssertEquals(byte[] assertEquals) { this.assertEquals = assertEquals; } + /** + * Checks if the modified value differs from the original value. + * + *

This method uses Arrays.equals() to properly compare the byte arrays. + * + * @return true if the value has been modified, false otherwise + * @throws IllegalStateException if the original value is null + */ @Override public boolean isOriginalValueModified() { - return originalValue != null && !Arrays.equals(originalValue, getValue()); + if (originalValue == null) { + throw new IllegalStateException("Original value must not be null"); + } else { + return !Arrays.equals(originalValue, getValue()); + } } + /** + * Validates whether the modified value matches the expected value (if set). + * + *

This method uses Arrays.equals() to properly compare the byte arrays. + * + * @return true if no assertion is set or if the current value equals the expected value + */ @Override public boolean validateAssertions() { boolean valid = true; @@ -78,6 +166,15 @@ public boolean validateAssertions() { return valid; } + /** + * Checks if this ModifiableByteArray is equal to another object. Two ModifiableByteArray + * instances are considered equal if they have the same modified value. + * + *

This method uses Arrays.equals() to properly compare the byte arrays. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -90,6 +187,14 @@ public boolean equals(Object obj) { return Arrays.equals(getValue(), that.getValue()); } + /** + * Computes a hash code for this ModifiableByteArray. The hash code is based on the modified + * value rather than the original value. + * + *

This method uses Arrays.hashCode() to properly compute the hash code for byte arrays. + * + * @return The hash code value + */ @Override public int hashCode() { int result = 17; @@ -97,6 +202,13 @@ public int hashCode() { return result; } + /** + * Returns a string representation of this ModifiableByteArray. + * + *

The byte arrays are converted to hexadecimal string representation for better readability. + * + * @return A string containing the original value and modifications + */ @Override public String toString() { return "ModifiableByteArray{" diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerAddModification.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerAddModification.java index 54eabdcf..adedd204 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerAddModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerAddModification.java @@ -11,30 +11,66 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that adds a constant value to a ModifiableInteger. + * + *

This modification adds a specified integer value (summand) to the input value when applied. It + * can be used to increment or decrement integer values at runtime. + * + * @see ModifiableInteger + */ @XmlRootElement public class IntegerAddModification extends VariableModification { - private Integer summand; + /** The value to add to the original integer */ + private int summand; - public IntegerAddModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private IntegerAddModification() { super(); } - public IntegerAddModification(Integer summand) { + /** + * Creates a new addition modification with the specified summand. + * + * @param summand The value to add to the original integer + */ + public IntegerAddModification(int summand) { super(); this.summand = summand; } + /** + * Copy constructor. + * + * @param other The modification to copy + */ public IntegerAddModification(IntegerAddModification other) { super(other); summand = other.summand; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same summand + */ @Override public IntegerAddModification createCopy() { return new IntegerAddModification(this); } + /** + * Modifies the input by adding the summand. + * + *

Note that this operation may cause integer overflow if the sum of the input and the + * summand exceeds Integer.MAX_VALUE or falls below Integer.MIN_VALUE. In such cases, the result + * will wrap around according to Java's integer arithmetic. + * + * @param input The integer value to modify + * @return The result of adding the summand to the input, or null if the input is null + */ @Override protected Integer modifyImplementationHook(Integer input) { if (input == null) { @@ -43,14 +79,29 @@ protected Integer modifyImplementationHook(Integer input) { return input + summand; } - public Integer getSummand() { + /** + * Gets the summand used for the addition. + * + * @return The value that will be added to the original integer + */ + public int getSummand() { return summand; } - public void setSummand(Integer summand) { + /** + * Sets the summand for the addition. + * + * @param summand The value that will be added to the original integer + */ + public void setSummand(int summand) { this.summand = summand; } + /** + * Computes a hash code for this modification. The hash code is based on the summand value. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -58,6 +109,13 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two IntegerAddModification instances + * are considered equal if they have the same summand. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +131,11 @@ public boolean equals(Object obj) { return Objects.equals(summand, other.summand); } + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type and summand + */ @Override public String toString() { return "IntegerAddModification{" + "summand=" + summand + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerExplicitValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerExplicitValueModification.java index 052706f7..2e5a64bd 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerExplicitValueModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerExplicitValueModification.java @@ -11,30 +11,67 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that replaces the original value with an explicitly defined value. + * + *

This modification ignores the original value of a {@link ModifiableInteger} and always returns + * a predefined integer value specified at initialization or via setter. + * + * @see ModifiableInteger + */ @XmlRootElement public class IntegerExplicitValueModification extends VariableModification { - protected Integer explicitValue; + /** The explicit value that will replace the original value */ + protected int explicitValue; - public IntegerExplicitValueModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private IntegerExplicitValueModification() { super(); } - public IntegerExplicitValueModification(Integer explicitValue) { + /** + * Creates a new modification with the specified explicit value. + * + * @param explicitValue The value that will replace the original value + */ + public IntegerExplicitValueModification(int explicitValue) { super(); this.explicitValue = explicitValue; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public IntegerExplicitValueModification(IntegerExplicitValueModification other) { super(other); explicitValue = other.explicitValue; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same explicit value + */ @Override public IntegerExplicitValueModification createCopy() { return new IntegerExplicitValueModification(this); } + /** + * Implements the modification by replacing the input with the explicit value. + * + *

This method simply returns the explicit value, completely ignoring the input parameter + * (except for null checks). + * + *

If the input is null, it preserves null-safety by returning null. + * + * @param input The original Integer value (ignored except for null check) + * @return The explicit value, or null if input was null + */ @Override protected Integer modifyImplementationHook(Integer input) { if (input == null) { @@ -43,21 +80,47 @@ protected Integer modifyImplementationHook(Integer input) { return explicitValue; } - public Integer getExplicitValue() { + /** + * Gets the explicit value that will replace the original value. + * + * @return The explicit value + */ + public int getExplicitValue() { return explicitValue; } - public void setExplicitValue(Integer explicitValue) { + /** + * Sets the explicit value that will replace the original value. + * + * @param explicitValue The new explicit value + */ + public void setExplicitValue(int explicitValue) { this.explicitValue = explicitValue; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the explicit value. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; - hash = 31 * hash + explicitValue; + hash = 31 * hash + Objects.hashCode(explicitValue); return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two IntegerExplicitValueModification objects are considered equal if they have the same + * explicit value. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +136,13 @@ public boolean equals(Object obj) { return Objects.equals(explicitValue, other.explicitValue); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and explicit value. + * + * @return A string representation of this object + */ @Override public String toString() { return "IntegerExplicitValueModification{" + "explicitValue=" + explicitValue + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerMultiplyModification.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerMultiplyModification.java index 9f3ab855..3f24618c 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerMultiplyModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerMultiplyModification.java @@ -11,30 +11,72 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that multiplies a ModifiableInteger by a constant factor. + * + *

This modification takes the original integer value and multiplies it by a specified factor + * when applied. It can be used to scale integer values at runtime. + * + * @see ModifiableInteger + */ @XmlRootElement public class IntegerMultiplyModification extends VariableModification { - private Integer factor; + /** The factor by which to multiply the original integer value */ + private int factor; - public IntegerMultiplyModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private IntegerMultiplyModification() { super(); } - public IntegerMultiplyModification(Integer factor) { + /** + * Creates a new modification with the specified multiplication factor. + * + *

This constructor sets the factor by which the original integer will be multiplied when the + * modification is applied. + * + * @param factor The factor to multiply the original value by + */ + public IntegerMultiplyModification(int factor) { super(); this.factor = factor; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public IntegerMultiplyModification(IntegerMultiplyModification other) { super(other); factor = other.factor; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same multiplication factor + */ @Override public IntegerMultiplyModification createCopy() { return new IntegerMultiplyModification(this); } + /** + * Implements the modification by multiplying the input by the factor. + * + *

This method multiplies the input integer by the factor specified during initialization or + * via {@link #setFactor(Integer)}. If the input is null, it returns null to preserve + * null-safety. + * + *

Note that this operation may result in integer overflow if the result exceeds the range of + * {@link Integer}, following regular Java integer logic. + * + * @param input The original integer value + * @return The result of multiplying the input by the factor, or null if input was null + */ @Override protected Integer modifyImplementationHook(Integer input) { if (input == null) { @@ -43,21 +85,48 @@ protected Integer modifyImplementationHook(Integer input) { return input * factor; } - public Integer getFactor() { + /** + * Gets the factor by which the original value will be multiplied. + * + * @return The multiplication factor + */ + public int getFactor() { return factor; } - public void setFactor(Integer factor) { + /** + * Sets the factor by which the original value will be multiplied. + * + * @param factor The new multiplication factor + * @throws NullPointerException if factor is null + */ + public void setFactor(int factor) { this.factor = factor; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the multiplication factor. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; - hash = 31 * hash + factor; + hash = 31 * hash + Objects.hashCode(factor); return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two IntegerMultiplyModification objects are considered equal if they have the same + * multiplication factor. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +142,13 @@ public boolean equals(Object obj) { return Objects.equals(factor, other.factor); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and the multiplication factor. + * + * @return A string representation of this object + */ @Override public String toString() { return "IntegerMultiplyModification{" + "factor=" + factor + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerShiftLeftModification.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerShiftLeftModification.java index 98f6c922..3e82ba74 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerShiftLeftModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerShiftLeftModification.java @@ -10,48 +10,103 @@ import de.rub.nds.modifiablevariable.VariableModification; import jakarta.xml.bind.annotation.XmlRootElement; +/** + * A modification that performs a left bit shift on a ModifiableInteger. + * + *

This modification shifts the bits of the input integer to the left by a specified number of + * positions when applied. It effectively multiplies the value by 2 raised to the power of the shift + * amount, which can be used to rapidly scale integer values at runtime. + * + * @see ModifiableInteger + * @see IntegerShiftRightModification + */ @XmlRootElement public class IntegerShiftLeftModification extends VariableModification { - private static final int MAX_SHIFT_MODIFIER = 32; - + /** The number of bit positions to shift left */ private int shift; - public IntegerShiftLeftModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private IntegerShiftLeftModification() { super(); } + /** + * Creates a new modification with the specified left shift amount. + * + * @param shift The number of bit positions to shift the value left + */ public IntegerShiftLeftModification(int shift) { super(); this.shift = shift; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public IntegerShiftLeftModification(IntegerShiftLeftModification other) { super(other); shift = other.shift; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same shift amount + */ @Override public IntegerShiftLeftModification createCopy() { return new IntegerShiftLeftModification(this); } + /** + * Implements the modification by shifting the input left by the specified number of bits. + * + *

This method performs the left shift operation on the input integer using the {@code <<} + * operator. If the input is null, it returns null to preserve null-safety. + * + *

A left shift by n bits is equivalent to multiplying by 2^n. + * + * @param input The original integer value + * @return The result of shifting the input left by the specified amount, or null if input is + * null + */ @Override protected Integer modifyImplementationHook(Integer input) { if (input == null) { return null; } - return input << shift % MAX_SHIFT_MODIFIER; + return input << shift; } + /** + * Gets the number of bits to shift left. + * + * @return The shift amount + */ public int getShift() { return shift; } + /** + * Sets the number of bits to shift left. + * + * @param shift The new shift amount + */ public void setShift(int shift) { this.shift = shift; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the shift amount. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -59,6 +114,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two IntegerShiftLeftModification objects are considered equal if they have the same shift + * amount. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -74,6 +138,13 @@ public boolean equals(Object obj) { return shift == other.shift; } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and shift amount. + * + * @return A string representation of this object + */ @Override public String toString() { return "IntegerShiftLeftModification{" + "shift=" + shift + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerShiftRightModification.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerShiftRightModification.java index 7b5a9379..50dfc385 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerShiftRightModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerShiftRightModification.java @@ -10,48 +10,101 @@ import de.rub.nds.modifiablevariable.VariableModification; import jakarta.xml.bind.annotation.XmlRootElement; +/** + * A modification that performs a signed right bit shift on a ModifiableInteger. + * + *

This modification shifts the bits of the input integer to the right by a specified number of + * positions when applied. It effectively divides the value by 2 raised to the power of the shift + * amount, which can be used to reduce integer values at runtime. + * + * @see ModifiableInteger + * @see IntegerShiftLeftModification + */ @XmlRootElement public class IntegerShiftRightModification extends VariableModification { - private static final int MAX_SHIFT_MODIFIER = 32; - + /** The number of bit positions to shift right */ private int shift; - public IntegerShiftRightModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private IntegerShiftRightModification() { super(); } + /** + * Creates a new modification with the specified right shift amount. + * + * @param shift The number of bit positions to shift the value right + */ public IntegerShiftRightModification(int shift) { super(); this.shift = shift; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public IntegerShiftRightModification(IntegerShiftRightModification other) { super(other); shift = other.shift; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same shift amount + */ @Override public IntegerShiftRightModification createCopy() { return new IntegerShiftRightModification(this); } + /** + * Implements the modification by shifting the input right by the specified number of bits. + * + *

This method performs the signed right shift operation on the input integer using the + * {@code >>} operator. If the input is null, it returns null to preserve null-safety. + * + * @param input The original integer value + * @return The result of shifting the input right by the specified amount, or null if input is + * null + */ @Override protected Integer modifyImplementationHook(Integer input) { if (input == null) { return null; } - return input >> shift % MAX_SHIFT_MODIFIER; + return input >> shift; } + /** + * Gets the number of bits to shift right. + * + * @return The shift amount + */ public int getShift() { return shift; } + /** + * Sets the number of bits to shift right. + * + * @param shift The new shift amount + */ public void setShift(int shift) { this.shift = shift; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the shift amount. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -59,6 +112,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two IntegerShiftRightModification objects are considered equal if they have the same shift + * amount. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -74,6 +136,13 @@ public boolean equals(Object obj) { return shift == other.shift; } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and shift amount. + * + * @return A string representation of this object + */ @Override public String toString() { return "IntegerShiftRightModification{" + "shift=" + shift + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerSubtractModification.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerSubtractModification.java index 26347252..420dc484 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerSubtractModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerSubtractModification.java @@ -11,30 +11,67 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that subtracts a constant value from a ModifiableInteger. + * + *

This modification subtracts a specified integer value (subtrahend) from the input value when + * applied. It can be used to decrement integer values at runtime. + * + * @see ModifiableInteger + * @see IntegerAddModification + */ @XmlRootElement public class IntegerSubtractModification extends VariableModification { - private Integer subtrahend; + /** The value to subtract from the original integer */ + private int subtrahend; - public IntegerSubtractModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private IntegerSubtractModification() { super(); } + /** + * Creates a new modification with the specified subtrahend. + * + * @param subtrahend The integer value to subtract from the original value + * @throws NullPointerException if subtrahend is null + */ public IntegerSubtractModification(Integer subtrahend) { super(); - this.subtrahend = subtrahend; + this.subtrahend = Objects.requireNonNull(subtrahend, "Subtrahend must not be null"); } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public IntegerSubtractModification(IntegerSubtractModification other) { super(other); subtrahend = other.subtrahend; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same subtrahend + */ @Override public IntegerSubtractModification createCopy() { return new IntegerSubtractModification(this); } + /** + * Implements the modification by subtracting the subtrahend from the input. + * + *

This method performs the subtraction operation on the input integer using the {@code -} + * operator. If the input is null, it returns null to preserve null-safety. + * + * @param input The original integer value + * @return The result of subtracting the subtrahend from the input, or null if input is null + */ @Override protected Integer modifyImplementationHook(Integer input) { if (input == null) { @@ -43,21 +80,47 @@ protected Integer modifyImplementationHook(Integer input) { return input - subtrahend; } - public Integer getSubtrahend() { + /** + * Gets the value being subtracted (the subtrahend). + * + * @return The subtrahend + */ + public int getSubtrahend() { return subtrahend; } - public void setSubtrahend(Integer subtrahend) { + /** + * Sets the value to subtract (the subtrahend). + * + * @param subtrahend The new subtrahend + */ + public void setSubtrahend(int subtrahend) { this.subtrahend = subtrahend; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the subtrahend value. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; - hash = 31 * hash + subtrahend; + hash = 31 * hash + Objects.hashCode(subtrahend); return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two IntegerSubtractModification objects are considered equal if they have the same + * subtrahend. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +136,13 @@ public boolean equals(Object obj) { return Objects.equals(subtrahend, other.subtrahend); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and subtrahend value. + * + * @return A string representation of this object + */ @Override public String toString() { return "IntegerSubtractModification{" + "subtrahend=" + subtrahend + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerSwapEndianModification.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerSwapEndianModification.java index 4a7fcdf7..15e291b1 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerSwapEndianModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerSwapEndianModification.java @@ -10,22 +10,57 @@ import de.rub.nds.modifiablevariable.VariableModification; import jakarta.xml.bind.annotation.XmlRootElement; +/** + * A modification that swaps the byte order (endianness) of a ModifiableInteger. + * + *

This modification reverses the byte order of an integer value when applied, effectively + * converting between big-endian and little-endian representations. + * + *

The implementation uses Java's built-in {@link Integer#reverseBytes(int)} method to perform an + * efficient, single-operation byte swap. + * + *

This modification is stateless as it has no configuration parameters. All instances of this + * class behave identically and are considered equal when compared. + * + * @see ModifiableInteger + * @see de.rub.nds.modifiablevariable.longint.LongSwapEndianModification + */ @XmlRootElement public class IntegerSwapEndianModification extends VariableModification { + /** Default constructor. */ public IntegerSwapEndianModification() { super(); } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public IntegerSwapEndianModification(IntegerSwapEndianModification other) { super(other); } + /** + * Creates a deep copy of this modification. + * + * @return A new instance of this modification + */ @Override public IntegerSwapEndianModification createCopy() { return new IntegerSwapEndianModification(this); } + /** + * Implements the modification by swapping the byte order of the input integer. + * + *

This method uses {@link Integer#reverseBytes(int)} to change the endianness of the input + * value. If the input is null, it returns null to preserve null-safety. + * + * @param input The original integer value + * @return The integer with reversed byte order, or null if input was null + */ @Override protected Integer modifyImplementationHook(Integer input) { if (input == null) { @@ -34,11 +69,28 @@ protected Integer modifyImplementationHook(Integer input) { return Integer.reverseBytes(input); } + /** + * Computes a hash code for this modification. + * + *

Since this modification is stateless, a constant hash code is returned. + * + * @return A constant hash code value for all instances of this class + */ @Override public int hashCode() { return 7; } + /** + * Compares this modification with another object for equality. + * + *

Since this modification is stateless, all instances of this class are considered equal to + * each other. + * + * @param obj The object to compare with + * @return {@code true} if the object is also an IntegerSwapEndianModification, {@code false} + * otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -50,6 +102,11 @@ public boolean equals(Object obj) { return getClass() == obj.getClass(); } + /** + * Returns a string representation of this modification. + * + * @return A string representation of this object + */ @Override public String toString() { return "IntegerSwapEndianModification{" + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerXorModification.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerXorModification.java index a557cb6a..cab3a5f7 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerXorModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerXorModification.java @@ -11,30 +11,66 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that applies a bitwise XOR operation to a ModifiableInteger. + * + *

This modification performs a bitwise XOR (exclusive OR) operation between the original integer + * value and a specified XOR mask when applied. It can be used to selectively flip specific bits in + * integer values at runtime. + * + * @see ModifiableInteger + */ @XmlRootElement public class IntegerXorModification extends VariableModification { - private Integer xor; + /** The XOR mask to apply to the original integer */ + private int xor; - public IntegerXorModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private IntegerXorModification() { super(); } - public IntegerXorModification(Integer xor) { + /** + * Creates a new modification with the specified XOR mask. + * + * @param xor The integer value to use as the XOR mask + */ + public IntegerXorModification(int xor) { super(); this.xor = xor; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public IntegerXorModification(IntegerXorModification other) { super(other); xor = other.xor; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same XOR mask + */ @Override public IntegerXorModification createCopy() { return new IntegerXorModification(this); } + /** + * Implements the modification by applying an XOR operation to the input. + * + *

This method performs the bitwise XOR operation on the input integer using the {@code ^} + * operator. If the input is null, it returns null to preserve null-safety. + * + * @param input The original integer value + * @return The result of XORing the input with the XOR mask, or null if input is null + */ @Override protected Integer modifyImplementationHook(Integer input) { if (input == null) { @@ -43,21 +79,46 @@ protected Integer modifyImplementationHook(Integer input) { return input ^ xor; } - public Integer getXor() { + /** + * Gets the XOR mask applied to the original value. + * + * @return The XOR mask + */ + public int getXor() { return xor; } - public void setXor(Integer xor) { + /** + * Sets the XOR mask to apply to the original value. + * + * @param xor The new XOR mask + */ + public void setXor(int xor) { this.xor = xor; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the XOR mask. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; - hash = 31 * hash + xor; + hash = 31 * hash + Objects.hashCode(xor); return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two IntegerXorModification objects are considered equal if they have the same XOR mask. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +134,13 @@ public boolean equals(Object obj) { return Objects.equals(xor, other.xor); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and XOR mask value. + * + * @return A string representation of this object + */ @Override public String toString() { return "IntegerXorModification{" + "xor=" + xor + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/ModifiableInteger.java b/src/main/java/de/rub/nds/modifiablevariable/integer/ModifiableInteger.java index bb51c4ed..03e7e897 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/integer/ModifiableInteger.java +++ b/src/main/java/de/rub/nds/modifiablevariable/integer/ModifiableInteger.java @@ -11,38 +11,88 @@ import de.rub.nds.modifiablevariable.util.ArrayConverter; import jakarta.xml.bind.annotation.XmlRootElement; +/** + * A modifiable variable implementation for Integer values. + * + *

This class extends {@link ModifiableVariable} to provide runtime modification capabilities for + * Integer values. It supports various integer-specific modifications like addition, subtraction, + * XOR operations, and more. + * + * @see ModifiableVariable + * @see IntegerAddModification + * @see IntegerSubtractModification + * @see IntegerXorModification + * @see IntegerShiftLeftModification + * @see IntegerShiftRightModification + * @see IntegerSwapEndianModification + * @see IntegerExplicitValueModification + */ @XmlRootElement public class ModifiableInteger extends ModifiableVariable { + /** The original integer value before any modifications */ private Integer originalValue; + /** Default constructor that creates an empty ModifiableInteger with no original value. */ public ModifiableInteger() { super(); } + /** + * Constructor that creates a ModifiableInteger with the specified original value. + * + * @param originalValue The original integer value + */ public ModifiableInteger(Integer originalValue) { super(); this.originalValue = originalValue; } + /** + * Copy constructor that creates a new ModifiableInteger with the same original value and + * modifications as the provided instance. + * + * @param other The ModifiableInteger to copy + */ public ModifiableInteger(ModifiableInteger other) { super(other); originalValue = other.originalValue; } + /** + * Creates a deep copy of this ModifiableInteger. + * + * @return A new ModifiableInteger instance with the same properties + */ @Override public ModifiableInteger createCopy() { return new ModifiableInteger(this); } + /** + * Gets the expected value for assertion validation. + * + * @return The assertion value + */ public Integer getAssertEquals() { return assertEquals; } + /** + * Sets the expected value for assertion validation. + * + * @param assertEquals The expected integer value + */ public void setAssertEquals(Integer assertEquals) { this.assertEquals = assertEquals; } + /** + * Checks if the modified value differs from the original value. + * + * @return true if the value has been modified, false otherwise + * @throws IllegalStateException if the original value is null + */ @Override public boolean isOriginalValueModified() { if (getOriginalValue() == null) { @@ -52,10 +102,23 @@ public boolean isOriginalValueModified() { } } + /** + * Converts the integer value to a byte array of the specified size. If the size is too small, + * the most significant bytes are truncated. If the size is too large, the byte array is padded + * with zeros. + * + * @param size The size of the resulting byte array + * @return The byte array representation of the integer + */ public byte[] getByteArray(int size) { return ArrayConverter.intToBytes(getValue(), size); } + /** + * Validates whether the modified value matches the expected value (if set). + * + * @return true if no assertion is set or if the current value equals the expected value + */ @Override public boolean validateAssertions() { boolean valid = true; @@ -67,21 +130,43 @@ public boolean validateAssertions() { return valid; } + /** + * Gets the original, unmodified integer value. + * + * @return The original value + */ @Override public Integer getOriginalValue() { return originalValue; } + /** + * Sets the original integer value. + * + * @param originalValue The new original value + */ @Override public void setOriginalValue(Integer originalValue) { this.originalValue = originalValue; } + /** + * Returns a string representation of this ModifiableInteger. + * + * @return A string containing the original value and modifications + */ @Override public String toString() { return "ModifiableInteger{" + "originalValue=" + originalValue + innerToString() + '}'; } + /** + * Checks if this ModifiableInteger is equal to another object. Two ModifiableInteger instances + * are considered equal if they have the same modified value. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -94,6 +179,12 @@ public boolean equals(Object obj) { return getValue() != null ? getValue().equals(that.getValue()) : that.getValue() == null; } + /** + * Computes a hash code for this ModifiableInteger. The hash code is based on the modified value + * rather than the original value. + * + * @return The hash code value + */ @Override public int hashCode() { int result = 17; diff --git a/src/main/java/de/rub/nds/modifiablevariable/length/ModifiableLengthField.java b/src/main/java/de/rub/nds/modifiablevariable/length/ModifiableLengthField.java index e77f0796..6ab9e4a0 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/length/ModifiableLengthField.java +++ b/src/main/java/de/rub/nds/modifiablevariable/length/ModifiableLengthField.java @@ -13,43 +13,105 @@ import jakarta.xml.bind.annotation.XmlAccessorType; import jakarta.xml.bind.annotation.XmlRootElement; +/** + * A specialized modifiable integer that represents the length of a byte array. + * + *

This class extends {@link ModifiableInteger} but instead of storing its own original value, it + * dynamically calculates its original value based on the length of a referenced byte array. This + * makes it suitable for representing length fields in protocols where the length needs to be + * synchronized with the actual content. + * + *

Note that attempting to set the original value directly will throw an + * UnsupportedOperationException, as the original value is derived from the referenced byte array. + */ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class ModifiableLengthField extends ModifiableInteger { + /** The byte array whose length this field represents */ private final ModifiableByteArray ref; + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private ModifiableLengthField() { + super(); + ref = null; + } + + /** + * Constructor that creates a ModifiableLengthField for the specified byte array. + * + * @param ref The byte array whose length this field will represent + */ public ModifiableLengthField(ModifiableByteArray ref) { super(); this.ref = ref; } + /** + * Copy constructor. + * + *

Note that this creates a new ModifiableLengthField that references the same + * ModifiableByteArray as the original, not a copy of the byte array. + * + * @param other The ModifiableLengthField to copy + */ public ModifiableLengthField(ModifiableLengthField other) { super(other); ref = other.ref; } + /** + * Creates a deep copy of this ModifiableLengthField. + * + * @return A new ModifiableLengthField instance referencing the same byte array + */ @Override public ModifiableLengthField createCopy() { return new ModifiableLengthField(this); } + /** + * Gets the original value of this length field, which is dynamically calculated as the length + * of the referenced byte array. + * + * @return The current length of the referenced byte array + */ @Override public Integer getOriginalValue() { return ref.getValue().length; } + /** + * This method is not supported for ModifiableLengthField, as the original value is always + * derived from the referenced byte array. + * + * @param originalValue This parameter is ignored + * @throws UnsupportedOperationException Always thrown when this method is called + */ @Override public void setOriginalValue(Integer originalValue) { throw new UnsupportedOperationException( "Cannot set original Value of ModifiableLengthField"); } + /** + * Returns a string representation of this ModifiableLengthField. + * + * @return A string containing the referenced byte array and modifications + */ @Override public String toString() { return "ModifiableLengthField{" + "ref=" + ref + super.toString() + "} "; } + /** + * Checks if this ModifiableLengthField is equal to another object. Two ModifiableLengthField + * instances are considered equal if they have the same modified value. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -62,6 +124,12 @@ public boolean equals(Object obj) { return ref != null ? getValue().equals(that.getValue()) : that.getValue() == null; } + /** + * Computes a hash code for this ModifiableLengthField. The hash code is based on the modified + * value. + * + * @return The hash code value + */ @Override public int hashCode() { int result = 17; diff --git a/src/main/java/de/rub/nds/modifiablevariable/logging/ExtendedPatternLayout.java b/src/main/java/de/rub/nds/modifiablevariable/logging/ExtendedPatternLayout.java index e35a58e9..24860cfc 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/logging/ExtendedPatternLayout.java +++ b/src/main/java/de/rub/nds/modifiablevariable/logging/ExtendedPatternLayout.java @@ -30,9 +30,33 @@ import org.apache.logging.log4j.util.Strings; /** - * A layout for LOG messages in the correct format and also for logging ByteArrays with good - * performance. The ExtendedPatternLayout is mostly copied from {@link - * org.apache.logging.log4j.core.layout.PatternLayout}. + * A specialized layout for formatting log messages with enhanced byte array handling. + * + *

This class extends the functionality of Log4j2's standard PatternLayout by adding specialized + * handling for byte array parameters in log messages. While the standard PatternLayout would format + * byte arrays using {@link Arrays#toString(byte[])}, which produces output like "[B@1a2b3c4]", this + * layout intercepts byte array parameters and formats them as readable hexadecimal strings using + * {@link ArrayConverter#bytesToHexString(byte[])}. + * + *

The layout supports all standard PatternLayout features including: + * + *

+ * + *

Additionally, it provides configuration options specific to byte array formatting: + * + *

+ * + *

The implementation is based on {@link org.apache.logging.log4j.core.layout.PatternLayout} with + * modifications for byte array handling. */ @Plugin( name = "ExtendedPatternLayout", @@ -40,12 +64,31 @@ elementType = "layout", printObject = true) public final class ExtendedPatternLayout extends AbstractStringLayout { + /** The default conversion pattern: "%m%n" (message followed by a newline) */ public static final String DEFAULT_CONVERSION_PATTERN = "%m%n"; + + /** + * The TTCC conversion pattern includes thread, time, category and context information: "%r [%t] + * %p %c %notEmpty{%x }- %m%n" + */ public static final String TTCC_CONVERSION_PATTERN = "%r [%t] %p %c %notEmpty{%x }- %m%n"; + + /** + * A simple conversion pattern with date, thread, priority, category and message: "%d [%t] %p %c + * - %m%n" + */ public static final String SIMPLE_CONVERSION_PATTERN = "%d [%t] %p %c - %m%n"; + + /** The key for the pattern converter in the configuration */ public static final String KEY = "Converter"; + + /** The pattern string used to format log events */ private final String conversionPattern; + + /** Pattern selector for dynamic pattern selection based on log event properties */ private final PatternSelector patternSelector; + + /** Serializer used to format log events into strings */ private final AbstractStringLayout.Serializer eventSerializer; private ExtendedPatternLayout( @@ -95,6 +138,11 @@ private ExtendedPatternLayout( .build(); } + /** + * Creates a new serializer builder for configuring a serializer. + * + * @return A new serializer builder instance + */ public static ExtendedPatternLayout.SerializerBuilder newSerializerBuilder() { return new ExtendedPatternLayout.SerializerBuilder(); } @@ -106,7 +154,17 @@ public boolean requiresLocation() { } /** - * @deprecated + * Creates a serializer with the specified parameters. + * + * @param configuration The configuration to use + * @param replace The regex replacement to apply to the formatted output + * @param pattern The conversion pattern to use for formatting + * @param defaultPattern The default pattern to use if the primary pattern is not available + * @param patternSelector Optional pattern selector for dynamic pattern selection + * @param alwaysWriteExceptions Whether to always include exception information in the output + * @param noConsoleNoAnsi Whether to disable ANSI escapes when output is not to a console + * @return A serializer configured with the specified parameters + * @deprecated Use the builder pattern with {@link #newSerializerBuilder()} instead */ @Deprecated public static AbstractStringLayout.Serializer createSerializer( @@ -128,6 +186,11 @@ public static AbstractStringLayout.Serializer createSerializer( return builder.build(); } + /** + * Returns the conversion pattern used by this layout. + * + * @return The pattern string used to format log events + */ public String getConversionPattern() { return conversionPattern; } @@ -141,15 +204,43 @@ public Map getContentFormat() { return result; } + /** + * Converts a LogEvent to a serialized string representation. + * + *

This method delegates to the configured event serializer to format the log event according + * to the pattern and configuration settings. + * + * @param event The LogEvent to serialize + * @return The formatted string representation of the log event + */ @Override public String toSerializable(LogEvent event) { return eventSerializer.toSerializable(event); } + /** + * Serializes a LogEvent into the provided StringBuilder. + * + *

This method is more efficient than {@link #toSerializable(LogEvent)} when the caller + * already has a StringBuilder, as it avoids creating intermediate string objects. + * + * @param event The LogEvent to serialize + * @param stringBuilder The StringBuilder to append the formatted event to + */ public void serialize(LogEvent event, StringBuilder stringBuilder) { eventSerializer.toSerializable(event, stringBuilder); } + /** + * Encodes a LogEvent to a byte buffer destination. + * + *

This method handles the complete serialization and encoding process for writing a log + * event to a destination. It first formats the event using the configured serializer, then + * encodes the resulting text using the configured charset. + * + * @param event The LogEvent to encode + * @param destination The destination to write the encoded event to + */ @Override public void encode(LogEvent event, ByteBufferDestination destination) { if (eventSerializer == null) { @@ -169,6 +260,16 @@ private static StringBuilder toText( return serializer.toSerializable(event, destination); } + /** + * Creates a pattern parser for the given configuration. + * + *

If the configuration already contains a pattern parser component with the key "Converter", + * that parser is returned. Otherwise, a new parser is created and registered with the + * configuration. + * + * @param config The configuration to create or retrieve a pattern parser for + * @return A pattern parser for the specified configuration + */ public static PatternParser createPatternParser(Configuration config) { if (config == null) { return new PatternParser(null, "Converter", LogEventPatternConverter.class); @@ -190,7 +291,19 @@ public String toString() { } /** - * @deprecated + * Creates a layout with the specified parameters. + * + * @param pattern The conversion pattern to use for formatting + * @param patternSelector Optional pattern selector for dynamic pattern selection + * @param config The configuration to use + * @param replace The regex replacement to apply to the formatted output + * @param charset The character set to use for encoding the output + * @param alwaysWriteExceptions Whether to always include exception information in the output + * @param noConsoleNoAnsi Whether to disable ANSI escapes when output is not to a console + * @param headerPattern The pattern to use for the header + * @param footerPattern The pattern to use for the footer + * @return A layout configured with the specified parameters + * @deprecated Use the builder pattern with {@link #newBuilder()} instead */ @PluginFactory @Deprecated @@ -218,23 +331,50 @@ public static ExtendedPatternLayout createLayout( .build(); } + /** + * Creates a layout with default settings. + * + * @return A layout configured with default settings + */ public static ExtendedPatternLayout createDefaultLayout() { return newBuilder().build(); } + /** + * Creates a layout with default settings and the specified configuration. + * + * @param configuration The configuration to use + * @return A layout configured with default settings and the specified configuration + */ public static ExtendedPatternLayout createDefaultLayout(Configuration configuration) { return newBuilder().withConfiguration(configuration).build(); } + /** + * Creates a new builder for configuring a layout. + * + * @return A new builder instance + */ @PluginBuilderFactory public static ExtendedPatternLayout.Builder newBuilder() { return new ExtendedPatternLayout.Builder(); } + /** + * Returns the serializer used to format log events. + * + * @return The event serializer + */ public AbstractStringLayout.Serializer getEventSerializer() { return eventSerializer; } + /** + * Builder for creating and configuring ExtendedPatternLayout instances. + * + *

This builder provides a fluent API for configuring all aspects of the layout, including + * patterns, formatters, character encoding, and display options. + */ public static final class Builder implements org.apache.logging.log4j.core.util.Builder { @PluginBuilderAttribute private String pattern; @@ -275,27 +415,57 @@ private static boolean useAnsiEscapeCodes() { return isPlatformSupportsAnsi || isJansiRequested; } + /** + * Sets the conversion pattern to use for formatting log events. + * + * @param pattern The pattern string + * @return This builder instance + */ public ExtendedPatternLayout.Builder withPattern(String pattern) { this.pattern = pattern; return this; } + /** + * Sets the pattern selector for dynamic pattern selection based on log event properties. + * + * @param patternSelector The pattern selector to use + * @return This builder instance + */ public ExtendedPatternLayout.Builder withPatternSelector(PatternSelector patternSelector) { this.patternSelector = patternSelector; return this; } + /** + * Sets the configuration to use for this layout. + * + * @param configuration The configuration + * @return This builder instance + */ public ExtendedPatternLayout.Builder withConfiguration(Configuration configuration) { this.configuration = configuration; return this; } + /** + * Sets the regex replacement to apply to the formatted output. + * + * @param regexReplacement The regex replacement + * @return This builder instance + */ public ExtendedPatternLayout.Builder withRegexReplacement( RegexReplacement regexReplacement) { this.regexReplacement = regexReplacement; return this; } + /** + * Sets the character set to use for encoding the output. + * + * @param charset The character set + * @return This builder instance + */ public ExtendedPatternLayout.Builder withCharset(Charset charset) { if (charset != null) { this.charset = charset; @@ -304,27 +474,57 @@ public ExtendedPatternLayout.Builder withCharset(Charset charset) { return this; } + /** + * Sets whether to always include exception information in the output. + * + * @param alwaysWriteExceptions Whether to always write exceptions + * @return This builder instance + */ public ExtendedPatternLayout.Builder withAlwaysWriteExceptions( boolean alwaysWriteExceptions) { this.alwaysWriteExceptions = alwaysWriteExceptions; return this; } + /** + * Sets whether to disable ANSI escape codes in the output. + * + * @param disableAnsi Whether to disable ANSI escape codes + * @return This builder instance + */ public ExtendedPatternLayout.Builder withDisableAnsi(boolean disableAnsi) { this.disableAnsi = disableAnsi; return this; } + /** + * Sets whether to disable ANSI escapes when output is not to a console. + * + * @param noConsoleNoAnsi Whether to disable ANSI when not writing to console + * @return This builder instance + */ public ExtendedPatternLayout.Builder withNoConsoleNoAnsi(boolean noConsoleNoAnsi) { this.noConsoleNoAnsi = noConsoleNoAnsi; return this; } + /** + * Sets the pattern to use for the header. + * + * @param header The header pattern + * @return This builder instance + */ public ExtendedPatternLayout.Builder withHeader(String header) { this.header = header; return this; } + /** + * Sets the pattern to use for the footer. + * + * @param footer The footer pattern + * @return This builder instance + */ public ExtendedPatternLayout.Builder withFooter(String footer) { this.footer = footer; return this; @@ -408,8 +608,26 @@ public String toString() { } } + /** + * Builder class for creating serializers for formatting log events. + * + *

This builder provides a fluent API for configuring all aspects of serialization, including + * patterns, pattern selectors, and formatting options. + */ public static class SerializerBuilder implements org.apache.logging.log4j.core.util.Builder { + + /** + * Creates a new SerializerBuilder with default settings. + * + *

This constructor initializes a builder with no configuration, pattern, pattern + * selector, or formatting options. These must be set using the appropriate setter methods + * before calling {@link #build()}. + */ + public SerializerBuilder() { + // Default constructor deliberately left empty + } + private Configuration configuration; private RegexReplacement replace; private String pattern; @@ -445,44 +663,92 @@ public AbstractStringLayout.Serializer build() { } } + /** + * Sets the configuration to use for this serializer. + * + * @param configuration The configuration + * @return This builder instance + */ public ExtendedPatternLayout.SerializerBuilder setConfiguration( Configuration configuration) { this.configuration = configuration; return this; } + /** + * Sets the regex replacement to apply to the formatted output. + * + * @param replace The regex replacement + * @return This builder instance + */ public ExtendedPatternLayout.SerializerBuilder setReplace(RegexReplacement replace) { this.replace = replace; return this; } + /** + * Sets the conversion pattern to use for formatting log events. + * + * @param pattern The pattern string + * @return This builder instance + */ public ExtendedPatternLayout.SerializerBuilder setPattern(String pattern) { this.pattern = pattern; return this; } + /** + * Sets the default pattern to use if the primary pattern is not available. + * + * @param defaultPattern The default pattern string + * @return This builder instance + */ public ExtendedPatternLayout.SerializerBuilder setDefaultPattern(String defaultPattern) { this.defaultPattern = defaultPattern; return this; } + /** + * Sets the pattern selector for dynamic pattern selection based on log event properties. + * + * @param patternSelector The pattern selector to use + * @return This builder instance + */ public ExtendedPatternLayout.SerializerBuilder setPatternSelector( PatternSelector patternSelector) { this.patternSelector = patternSelector; return this; } + /** + * Sets whether to always include exception information in the output. + * + * @param alwaysWriteExceptions Whether to always write exceptions + * @return This builder instance + */ public ExtendedPatternLayout.SerializerBuilder setAlwaysWriteExceptions( boolean alwaysWriteExceptions) { this.alwaysWriteExceptions = alwaysWriteExceptions; return this; } + /** + * Sets whether to disable ANSI escape codes in the output. + * + * @param disableAnsi Whether to disable ANSI escape codes + * @return This builder instance + */ public ExtendedPatternLayout.SerializerBuilder setDisableAnsi(boolean disableAnsi) { this.disableAnsi = disableAnsi; return this; } + /** + * Sets whether to disable ANSI escapes when output is not to a console. + * + * @param noConsoleNoAnsi Whether to disable ANSI when not writing to console + * @return This builder instance + */ public ExtendedPatternLayout.SerializerBuilder setNoConsoleNoAnsi(boolean noConsoleNoAnsi) { this.noConsoleNoAnsi = noConsoleNoAnsi; return this; @@ -514,6 +780,35 @@ public String toSerializable(LogEvent event) { return var3; } + /** + * Converts a LogEvent to a serialized string representation in the provided StringBuilder. + * + *

This method is the core implementation of the layout's formatting process: + * + *

    + *
  1. First, it applies all pattern formatters to build the base formatted string + *
  2. Then it applies any regex replacements if configured + *
  3. Finally, it performs the specialized byte array handling that sets this layout + * apart: + *
      + *
    • It identifies any byte array parameters in the log message + *
    • It locates the default string representation of these byte arrays in the + * builder + *
    • It replaces them with formatted hexadecimal strings using ArrayConverter + *
    + *
+ * + *

The byte array formatting is controlled by two static configuration options: + * + *

+ * + * @param event The LogEvent to serialize + * @param builder The StringBuilder to append the formatted event to + * @return The StringBuilder with the formatted event appended + */ @Override public StringBuilder toSerializable(LogEvent event, StringBuilder builder) { Arrays.stream(formatters).forEachOrdered(formatter -> formatter.format(event, builder)); @@ -535,8 +830,7 @@ public StringBuilder toSerializable(LogEvent event, StringBuilder builder) { for (Object param : event.getMessage().getParameters()) { // Replace all ByteArrays with the String representation of the ByteArray - // calculated - // by the ArrayConverter. + // calculated by the ArrayConverter. if (param != null && bArrayClass.equals(param.getClass())) { builder.replace( builder.indexOf(Arrays.toString((byte[]) param)), diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongAddModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongAddModification.java index dfc74ff9..e64c4473 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/longint/LongAddModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongAddModification.java @@ -11,30 +11,66 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that adds a constant value to a ModifiableLong. + * + *

This modification adds a specified long value (summand) to the input value when applied. It + * can be used to increment or decrement long values at runtime. + * + * @see ModifiableLong + */ @XmlRootElement public class LongAddModification extends VariableModification { - private Long summand; + /** The value to add to the original long */ + private long summand; - public LongAddModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private LongAddModification() { super(); } - public LongAddModification(Long summand) { + /** + * Creates a new addition modification with the specified summand. + * + * @param summand The value to add to the original long + */ + public LongAddModification(long summand) { super(); this.summand = summand; } + /** + * Copy constructor. + * + * @param other The modification to copy + */ public LongAddModification(LongAddModification other) { super(other); summand = other.summand; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same summand + */ @Override public LongAddModification createCopy() { return new LongAddModification(this); } + /** + * Modifies the input by adding the summand. + * + *

Note that this operation may cause long overflow if the sum of the input and the summand + * exceeds Long.MAX_VALUE or falls below Long.MIN_VALUE. In such cases, the result will wrap + * around according to Java's long arithmetic. + * + * @param input The long value to modify + * @return The result of adding the summand to the input, or null if the input is null + */ @Override protected Long modifyImplementationHook(Long input) { if (input == null) { @@ -43,14 +79,29 @@ protected Long modifyImplementationHook(Long input) { return input + summand; } - public Long getSummand() { + /** + * Gets the summand used for the addition. + * + * @return The value that will be added to the original long + */ + public long getSummand() { return summand; } - public void setSummand(Long summand) { + /** + * Sets the summand for the addition. + * + * @param summand The value that will be added to the original long + */ + public void setSummand(long summand) { this.summand = summand; } + /** + * Computes a hash code for this modification. The hash code is based on the summand value. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -58,6 +109,13 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two LongAddModification instances are + * considered equal if they have the same summand. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +131,11 @@ public boolean equals(Object obj) { return Objects.equals(summand, other.summand); } + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type and summand + */ @Override public String toString() { return "LongAddModification{" + "summand=" + summand + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongExplicitValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongExplicitValueModification.java index 16c86c65..4f35a917 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/longint/LongExplicitValueModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongExplicitValueModification.java @@ -11,30 +11,69 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that replaces the original value with an explicitly defined value. + * + *

This modification ignores the original value of a {@link ModifiableLong} and always returns a + * predefined long value specified at initialization or via setter. + * + * @see ModifiableLong + * @see de.rub.nds.modifiablevariable.integer.IntegerExplicitValueModification + */ @XmlRootElement public class LongExplicitValueModification extends VariableModification { - protected Long explicitValue; + /** The explicit value that will replace the original value */ + protected long explicitValue; - public LongExplicitValueModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private LongExplicitValueModification() { super(); } - public LongExplicitValueModification(Long explicitValue) { + /** + * Creates a new modification with the specified explicit value. + * + * @param explicitValue The value that will replace the original value + */ + public LongExplicitValueModification(long explicitValue) { super(); this.explicitValue = explicitValue; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public LongExplicitValueModification(LongExplicitValueModification other) { super(other); explicitValue = other.explicitValue; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same explicit value + */ @Override public LongExplicitValueModification createCopy() { return new LongExplicitValueModification(this); } + /** + * Implements the modification by replacing the input with the explicit value. + * + *

This method simply returns the explicit value, completely ignoring the input parameter + * (except for null checks). This provides a straightforward way to override values in a + * protocol message. + * + *

If the input is null, it preserves null-safety by returning null. + * + * @param input The original Long value (ignored except for null check) + * @return The explicit value, or null if input was null + */ @Override protected Long modifyImplementationHook(Long input) { if (input == null) { @@ -43,14 +82,31 @@ protected Long modifyImplementationHook(Long input) { return explicitValue; } - public Long getExplicitValue() { + /** + * Gets the explicit value that will replace the original value. + * + * @return The explicit value + */ + public long getExplicitValue() { return explicitValue; } - public void setExplicitValue(Long explicitValue) { + /** + * Sets the explicit value that will replace the original value. + * + * @param explicitValue The new explicit value + */ + public void setExplicitValue(long explicitValue) { this.explicitValue = explicitValue; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the explicit value. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -58,6 +114,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two LongExplicitValueModification objects are considered equal if they have the same + * explicit value. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +138,13 @@ public boolean equals(Object obj) { return Objects.equals(explicitValue, other.explicitValue); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and explicit value. + * + * @return A string representation of this object + */ @Override public String toString() { return "LongExplicitValueModification{" + "explicitValue=" + explicitValue + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongMultiplyModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongMultiplyModification.java index ff602bc3..2ece6f22 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/longint/LongMultiplyModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongMultiplyModification.java @@ -11,30 +11,68 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that multiplies a ModifiableLong by a constant factor. + * + *

This modification takes the original long value and multiplies it by a specified factor when + * applied. It can be used to scale long values at runtime. + * + * @see ModifiableLong + */ @XmlRootElement public class LongMultiplyModification extends VariableModification { - private Long factor; + /** The factor to multiply by */ + private long factor; - public LongMultiplyModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private LongMultiplyModification() { super(); } - public LongMultiplyModification(Long factor) { + /** + * Creates a new modification with the specified multiplication factor. + * + * @param factor The long value to multiply the original value by + */ + public LongMultiplyModification(long factor) { super(); this.factor = factor; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public LongMultiplyModification(LongMultiplyModification other) { super(other); factor = other.factor; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same multiplication factor + */ @Override public LongMultiplyModification createCopy() { return new LongMultiplyModification(this); } + /** + * Implements the modification by multiplying the input by the factor. + * + *

This method performs the multiplication operation on the input long using the {@code *} + * operator. If the input is null, it returns null to preserve null-safety. + * + *

Note that this operation may result in overflow if the result exceeds the range of {@link + * Long}, which can be useful for testing boundary conditions and overflow handling. + * + * @param input The original long value + * @return The result of multiplying the input by the factor, or null if input is null + */ @Override protected Long modifyImplementationHook(Long input) { if (input == null) { @@ -43,14 +81,31 @@ protected Long modifyImplementationHook(Long input) { return input * factor; } - public Long getFactor() { + /** + * Gets the factor used for multiplication. + * + * @return The multiplication factor + */ + public long getFactor() { return factor; } - public void setFactor(Long factor) { + /** + * Sets the factor to use for multiplication. + * + * @param factor The new multiplication factor + */ + public void setFactor(long factor) { this.factor = factor; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the multiplication factor. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -58,6 +113,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two LongMultiplyModification objects are considered equal if they have the same + * multiplication factor. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +137,13 @@ public boolean equals(Object obj) { return Objects.equals(factor, other.factor); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and factor value. + * + * @return A string representation of this object + */ @Override public String toString() { return "LongMultiplyModification{" + "factor=" + factor + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongShiftLeftModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongShiftLeftModification.java index 2b783bea..9f1d9549 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/longint/LongShiftLeftModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongShiftLeftModification.java @@ -11,48 +11,101 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that performs a left bit shift on a ModifiableLong. + * + *

This modification shifts the bits of the input long to the left by a specified number of + * positions when applied. It effectively multiplies the value by 2 raised to the power of the shift + * amount, which can be used to rapidly scale long values at runtime. + * + * @see ModifiableLong + * @see LongShiftRightModification + */ @XmlRootElement public class LongShiftLeftModification extends VariableModification { - private static final int MAX_SHIFT_MODIFIER = 64; - + /** The number of bit positions to shift left */ private int shift; - public LongShiftLeftModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private LongShiftLeftModification() { super(); } + /** + * Creates a new modification with the specified left shift amount. + * + * @param shift The number of bit positions to shift the value left + */ public LongShiftLeftModification(int shift) { super(); this.shift = shift; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public LongShiftLeftModification(LongShiftLeftModification other) { super(other); shift = other.shift; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same shift amount + */ @Override public LongShiftLeftModification createCopy() { return new LongShiftLeftModification(this); } + /** + * Implements the modification by shifting the input left by the specified number of bits. + * + *

This method performs the left shift operation on the input long using the {@code <<} + * operator. If the input is null, it returns null to preserve null-safety. + * + * @param input The original long value + * @return The result of shifting the input left by the specified amount, or null if input is + * null + */ @Override protected Long modifyImplementationHook(Long input) { if (input == null) { return null; } - return input << shift % MAX_SHIFT_MODIFIER; + return input << shift; } + /** + * Gets the number of bits to shift left. + * + * @return The shift amount + */ public int getShift() { return shift; } + /** + * Sets the number of bits to shift left. + * + * @param shift The new shift amount + */ public void setShift(int shift) { this.shift = shift; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the shift amount. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -60,6 +113,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two LongShiftLeftModification objects are considered equal if they have the same shift + * amount. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -75,6 +137,13 @@ public boolean equals(Object obj) { return Objects.equals(shift, other.shift); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and shift amount. + * + * @return A string representation of this object + */ @Override public String toString() { return "LongShiftLeftModification{" + "shift=" + shift + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongShiftRightModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongShiftRightModification.java index 9374ec48..c3590526 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/longint/LongShiftRightModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongShiftRightModification.java @@ -11,48 +11,101 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that performs a signed right bit shift on a ModifiableLong. + * + *

This modification shifts the bits of the input long to the right by a specified number of + * positions when applied. It effectively divides the value by 2 raised to the power of the shift + * amount, which can be used to reduce long values at runtime. + * + * @see ModifiableLong + * @see LongShiftLeftModification + */ @XmlRootElement public class LongShiftRightModification extends VariableModification { - private static final int MAX_SHIFT_MODIFIER = 64; - + /** The number of bit positions to shift right */ private int shift; - public LongShiftRightModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private LongShiftRightModification() { super(); } + /** + * Creates a new modification with the specified right shift amount. + * + * @param shift The number of bit positions to shift the value right + */ public LongShiftRightModification(int shift) { super(); this.shift = shift; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public LongShiftRightModification(LongShiftRightModification other) { super(other); shift = other.shift; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same shift amount + */ @Override public LongShiftRightModification createCopy() { return new LongShiftRightModification(this); } + /** + * Implements the modification by shifting the input right by the specified number of bits. + * + *

This method performs the signed right shift operation on the input long using the {@code + * >>} operator. If the input is null, it returns null to preserve null-safety. + * + * @param input The original long value + * @return The result of shifting the input right by the specified amount, or null if input is + * null + */ @Override protected Long modifyImplementationHook(Long input) { if (input == null) { return null; } - return input >> shift % MAX_SHIFT_MODIFIER; + return input >> shift; } + /** + * Gets the number of bits to shift right. + * + * @return The shift amount + */ public int getShift() { return shift; } + /** + * Sets the number of bits to shift right. + * + * @param shift The new shift amount + */ public void setShift(int shift) { this.shift = shift; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the shift amount. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -60,6 +113,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two LongShiftRightModification objects are considered equal if they have the same shift + * amount. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -75,6 +137,13 @@ public boolean equals(Object obj) { return Objects.equals(shift, other.shift); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and shift amount. + * + * @return A string representation of this object + */ @Override public String toString() { return "LongShiftRightModification{" + "shift=" + shift + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongSubtractModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongSubtractModification.java index 20f0265b..5a8b23af 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/longint/LongSubtractModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongSubtractModification.java @@ -11,30 +11,69 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that subtracts a constant value from a ModifiableLong. + * + *

This modification subtracts a specified long value (subtrahend) from the input value when + * applied. It can be used to decrement long values at runtime. + * + * @see ModifiableLong + * @see LongAddModification + */ @XmlRootElement public class LongSubtractModification extends VariableModification { - private Long subtrahend; + /** The value to subtract from the original long */ + private long subtrahend; - public LongSubtractModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private LongSubtractModification() { super(); } - public LongSubtractModification(Long subtrahend) { + /** + * Creates a new modification with the specified subtrahend. + * + * @param subtrahend The long value to subtract from the original value + */ + public LongSubtractModification(long subtrahend) { super(); this.subtrahend = subtrahend; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public LongSubtractModification(LongSubtractModification other) { super(other); subtrahend = other.subtrahend; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same subtrahend + */ @Override public LongSubtractModification createCopy() { return new LongSubtractModification(this); } + /** + * Implements the modification by subtracting the subtrahend from the input. + * + *

This method performs the subtraction operation on the input long using the {@code -} + * operator. If the input is null, it returns null to preserve null-safety. + * + *

Note that this operation may result in underflow if the result is less than {@link + * Long#MIN_VALUE}, which can be useful for testing boundary conditions and underflow handling. + * + * @param input The original long value + * @return The result of subtracting the subtrahend from the input, or null if input is null + */ @Override protected Long modifyImplementationHook(Long input) { if (input == null) { @@ -43,14 +82,31 @@ protected Long modifyImplementationHook(Long input) { return input - subtrahend; } - public Long getSubtrahend() { + /** + * Gets the value being subtracted (the subtrahend). + * + * @return The subtrahend + */ + public long getSubtrahend() { return subtrahend; } - public void setSubtrahend(Long subtrahend) { + /** + * Sets the value to subtract (the subtrahend). + * + * @param subtrahend The new subtrahend + */ + public void setSubtrahend(long subtrahend) { this.subtrahend = subtrahend; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the subtrahend value. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -58,6 +114,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two LongSubtractModification objects are considered equal if they have the same + * subtrahend. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +138,13 @@ public boolean equals(Object obj) { return Objects.equals(subtrahend, other.subtrahend); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and subtrahend value. + * + * @return A string representation of this object + */ @Override public String toString() { return "LongSubtractModification{" + "subtrahend=" + subtrahend + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongSwapEndianModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongSwapEndianModification.java index ae0050da..7e5f775f 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/longint/LongSwapEndianModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongSwapEndianModification.java @@ -10,22 +10,63 @@ import de.rub.nds.modifiablevariable.VariableModification; import jakarta.xml.bind.annotation.XmlRootElement; +/** + * A modification that swaps the byte order (endianness) of a ModifiableLong. + * + *

This modification reverses the byte order of a long value when applied, effectively converting + * between big-endian and little-endian representations. It can be used to test how systems handle + * different byte ordering conventions at runtime. + * + *

This modification is stateless as it has no configuration parameters. All instances of this + * class behave identically and are considered equal when compared. + * + * @see ModifiableLong + * @see de.rub.nds.modifiablevariable.integer.IntegerSwapEndianModification + */ @XmlRootElement public class LongSwapEndianModification extends VariableModification { + /** Default constructor. */ public LongSwapEndianModification() { super(); } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public LongSwapEndianModification(LongSwapEndianModification other) { super(other); } + /** + * Creates a deep copy of this modification. + * + * @return A new instance of the same type + */ @Override public LongSwapEndianModification createCopy() { return new LongSwapEndianModification(this); } + /** + * Implements the modification by reversing the byte order of the input. + * + *

This method uses {@link Long#reverseBytes(long)} to swap the endianness of the input + * value. If the input is null, it returns null to preserve null-safety. + * + *

The bytes are swapped in the following way: + * + *

+     * Byte:  0  1  2  3  4  5  6  7
+     *        ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓
+     * Byte:  7  6  5  4  3  2  1  0
+     * 
+ * + * @param input The original long value + * @return The value with bytes in reversed order, or null if input is null + */ @Override protected Long modifyImplementationHook(Long input) { if (input == null) { @@ -34,11 +75,28 @@ protected Long modifyImplementationHook(Long input) { return Long.reverseBytes(input); } + /** + * Computes a hash code for this modification. + * + *

Since this modification is stateless (has no fields), it returns a fixed value as its hash + * code. + * + * @return A fixed hash code value for this object + */ @Override public int hashCode() { return 7; } + /** + * Compares this modification with another object for equality. + * + *

Two LongSwapEndianModification objects are considered equal if they are of the same class, + * since the modification is stateless. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -50,6 +108,13 @@ public boolean equals(Object obj) { return getClass() == obj.getClass(); } + /** + * Returns a string representation of this modification. + * + *

The string includes only the class name since this modification is stateless. + * + * @return A string representation of this object + */ @Override public String toString() { return "LongSwapEndianModification{" + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongXorModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongXorModification.java index b21ae19e..fffa22ae 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/longint/LongXorModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongXorModification.java @@ -11,30 +11,66 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that applies a bitwise XOR operation to a ModifiableLong. + * + *

This modification performs a bitwise XOR (exclusive OR) operation between the original long + * value and a specified XOR mask when applied. It can be used to selectively flip specific bits in + * long values at runtime. + * + * @see ModifiableLong + */ @XmlRootElement public class LongXorModification extends VariableModification { - private Long xor; + /** The XOR mask to apply to the original long */ + private long xor; - public LongXorModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private LongXorModification() { super(); } - public LongXorModification(Long xor) { + /** + * Creates a new modification with the specified XOR mask. + * + * @param xor The long value to use as the XOR mask + */ + public LongXorModification(long xor) { super(); this.xor = xor; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public LongXorModification(LongXorModification other) { super(other); xor = other.xor; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same XOR mask + */ @Override public LongXorModification createCopy() { return new LongXorModification(this); } + /** + * Implements the modification by applying an XOR operation to the input. + * + *

This method performs the bitwise XOR operation on the input long using the {@code ^} + * operator. If the input is null, it returns null to preserve null-safety. + * + * @param input The original long value + * @return The result of XORing the input with the XOR mask, or null if input is null + */ @Override protected Long modifyImplementationHook(Long input) { if (input == null) { @@ -43,14 +79,31 @@ protected Long modifyImplementationHook(Long input) { return input ^ xor; } - public Long getXor() { + /** + * Gets the XOR mask applied to the original value. + * + * @return The XOR mask + */ + public long getXor() { return xor; } - public void setXor(Long xor) { + /** + * Sets the XOR mask to apply to the original value. + * + * @param xor The new XOR mask + */ + public void setXor(long xor) { this.xor = xor; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based solely on the XOR mask. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -58,6 +111,14 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two LongXorModification objects are considered equal if they have the same XOR mask. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +134,13 @@ public boolean equals(Object obj) { return Objects.equals(xor, other.xor); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name and XOR mask value. + * + * @return A string representation of this object + */ @Override public String toString() { return "LongXorModification{" + "xor=" + xor + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/ModifiableLong.java b/src/main/java/de/rub/nds/modifiablevariable/longint/ModifiableLong.java index 70c0bd8d..b5a9bff1 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/longint/ModifiableLong.java +++ b/src/main/java/de/rub/nds/modifiablevariable/longint/ModifiableLong.java @@ -11,47 +11,140 @@ import de.rub.nds.modifiablevariable.util.ArrayConverter; import jakarta.xml.bind.annotation.XmlRootElement; +/** + * A modifiable long integer variable. + * + *

This class extends {@link ModifiableVariable} to provide runtime modification capabilities for + * Java's primitive {@code long} values (wrapped as {@link Long} objects). It allows for various + * transformations to be applied to long values during program execution, making it useful for + * testing scenarios where long-typed values need to be manipulated. + * + *

Modifications specific to long integers include addition, subtraction, multiplication, XOR + * operations, bit shifts, endian swaps, and explicit value replacements. These modifications are + * represented by corresponding classes in the same package. + * + * @see ModifiableVariable + * @see LongAddModification + * @see LongSubtractModification + * @see LongMultiplyModification + * @see LongXorModification + * @see LongShiftLeftModification + * @see LongShiftRightModification + * @see LongSwapEndianModification + * @see LongExplicitValueModification + */ @XmlRootElement public class ModifiableLong extends ModifiableVariable { + /** The original, unmodified value of this variable */ private Long originalValue; + /** + * Default constructor creating an uninitialized ModifiableLong. + * + *

The originalValue is set to null, requiring it to be set later before meaningful + * modifications can be applied. + */ public ModifiableLong() { super(); } + /** + * Creates a new ModifiableLong with the specified original value. + * + * @param originalValue The initial value to store and potentially modify + */ public ModifiableLong(Long originalValue) { super(); this.originalValue = originalValue; } + /** + * Copy constructor creating a deep copy of the provided ModifiableLong. + * + *

This constructor copies both the modification sequence and the original value. + * + * @param other The ModifiableLong to copy + */ public ModifiableLong(ModifiableLong other) { super(other); originalValue = other.originalValue; } + /** + * Creates a deep copy of this ModifiableLong. + * + * @return A new ModifiableLong instance with the same modification sequence and original value + */ @Override public ModifiableLong createCopy() { return new ModifiableLong(this); } + /** + * Gets the assertion validation value for this variable. + * + *

This value is used in {@link #validateAssertions()} to verify that the modified value + * matches the expected value. + * + * @return The expected value for assertion validation + */ public Long getAssertEquals() { return assertEquals; } + /** + * Sets the assertion validation value for this variable. + * + *

This value is used to validate that modifications produce the expected result through the + * {@link #validateAssertions()} method. + * + * @param assertEquals The expected value for assertion validation + */ public void setAssertEquals(Long assertEquals) { this.assertEquals = assertEquals; } + /** + * Checks if the current value differs from the original value. + * + *

This method determines whether any modifications have effectively changed the value from + * its original state. + * + * @return {@code true} if the original value has been modified, {@code false} otherwise + * @throws IllegalStateException if the original value has not been set + */ @Override public boolean isOriginalValueModified() { - return originalValue != null && originalValue.compareTo(getValue()) != 0; + if (originalValue == null) { + throw new IllegalStateException( + "Original value must be set before checking for modifications"); + } + return !originalValue.equals(getValue()); } + /** + * Converts the modified long value to a byte array of the specified size. + * + *

This method uses {@link ArrayConverter} to convert the current value to a byte array. The + * resulting array will have the specified size, with padding or truncation as necessary. + * + * @param size The desired size of the resulting byte array + * @return A byte array representation of the current value with the specified size + */ public byte[] getByteArray(int size) { return ArrayConverter.longToBytes(getValue(), size); } + /** + * Validates that the current value matches the expected value. + * + *

If an assertion value has been set with {@link #setAssertEquals(Long)}, this method checks + * if the current value equals that assertion value. + * + * @return {@code true} if no assertion is set or if the assertion passes, {@code false} + * otherwise + */ @Override public boolean validateAssertions() { boolean valid = true; @@ -63,21 +156,50 @@ public boolean validateAssertions() { return valid; } + /** + * Gets the original, unmodified value of this variable. + * + * @return The original value as set during initialization or by {@link #setOriginalValue(Long)} + */ @Override public Long getOriginalValue() { return originalValue; } + /** + * Sets the original value of this variable. + * + *

This method updates the base value to which modifications are applied. + * + * @param originalValue The new original value + */ @Override public void setOriginalValue(Long originalValue) { this.originalValue = originalValue; } + /** + * Returns a string representation of this ModifiableLong. + * + *

The string includes the original value and details about any applied modifications. + * + * @return A string representation of this object + */ @Override public String toString() { return "ModifiableLong{" + "originalValue=" + originalValue + innerToString() + '}'; } + /** + * Compares this ModifiableLong with another object for equality. + * + *

Two ModifiableLong objects are considered equal if their current values (after applying + * modifications) are equal, regardless of the original values or the sequence of modifications + * applied to reach those values. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -90,6 +212,14 @@ public boolean equals(Object obj) { return getValue() != null ? getValue().equals(that.getValue()) : that.getValue() == null; } + /** + * Computes a hash code for this ModifiableLong. + * + *

The hash code is based on the current value after modifications have been applied, not on + * the original value or the sequence of modifications. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int result = 17; diff --git a/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteAddModification.java b/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteAddModification.java index d24dda63..c553de2c 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteAddModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteAddModification.java @@ -11,30 +11,67 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that adds a constant value to a ModifiableByte. + * + *

This modification adds a specified byte value (summand) to the input value when applied. It + * can be used to increment or decrement byte values at runtime. + * + * @see ModifiableByte + * @see ByteSubtractModification + */ @XmlRootElement public class ByteAddModification extends VariableModification { - private Byte summand; + /** The value to be added to the original byte */ + private byte summand; - public ByteAddModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private ByteAddModification() { super(); } - public ByteAddModification(Byte summand) { + /** + * Creates a new addition modification with the specified summand. + * + * @param summand The value to add to the original byte + */ + public ByteAddModification(byte summand) { super(); this.summand = summand; } + /** + * Copy constructor. + * + * @param other The ByteAddModification to copy from + */ public ByteAddModification(ByteAddModification other) { super(other); summand = other.summand; } + /** + * Creates a copy of this modification. + * + * @return A new ByteAddModification instance with the same properties + */ @Override public ByteAddModification createCopy() { return new ByteAddModification(this); } + /** + * Modifies the input by adding the summand. + * + *

Note that this operation may cause byte overflow if the sum of the input and the summand + * exceeds Byte.MAX_VALUE (127) or falls below Byte.MIN_VALUE (-128). In such cases, the result + * will wrap around according to Java's two's complement arithmetic. + * + * @param input The byte value to modify + * @return The result of adding the summand to the input, or null if the input is null + */ @Override protected Byte modifyImplementationHook(Byte input) { if (input == null) { @@ -43,14 +80,29 @@ protected Byte modifyImplementationHook(Byte input) { return (byte) (input + summand); } - public Byte getSummand() { + /** + * Gets the summand value used for the addition. + * + * @return The summand value + */ + public byte getSummand() { return summand; } - public void setSummand(Byte summand) { + /** + * Sets the summand value to be used for the addition. + * + * @param summand The byte value to add to the original value + */ + public void setSummand(byte summand) { this.summand = summand; } + /** + * Computes the hash code for this object. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -58,6 +110,12 @@ public int hashCode() { return hash; } + /** + * Compares this ByteAddModification with another object for equality. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +131,11 @@ public boolean equals(Object obj) { return Objects.equals(summand, other.summand); } + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type and summand value + */ @Override public String toString() { return "ByteAddModification{" + "summand=" + summand + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteExplicitValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteExplicitValueModification.java index 8ad69330..289a6116 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteExplicitValueModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteExplicitValueModification.java @@ -11,30 +11,66 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that replaces the original byte with an explicitly defined value. + * + *

This modification ignores the original value of a {@link ModifiableByte} and always returns a + * predefined byte value specified at initialization or via setter. + * + * @see ModifiableByte + */ @XmlRootElement public class ByteExplicitValueModification extends VariableModification { - protected Byte explicitValue; + /** The value that will replace the original byte */ + protected byte explicitValue; - public ByteExplicitValueModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private ByteExplicitValueModification() { super(); } - public ByteExplicitValueModification(Byte explicitValue) { + /** + * Constructor with a specified explicit value. + * + * @param explicitValue The byte value that will replace the original value + */ + public ByteExplicitValueModification(byte explicitValue) { super(); this.explicitValue = explicitValue; } + /** + * Copy constructor. + * + * @param other The ByteExplicitValueModification to copy from + */ public ByteExplicitValueModification(ByteExplicitValueModification other) { super(other); explicitValue = other.explicitValue; } + /** + * Creates a copy of this modification. + * + * @return A new ByteExplicitValueModification instance with the same properties + */ @Override public ByteExplicitValueModification createCopy() { return new ByteExplicitValueModification(this); } + /** + * Implements the modification by returning the explicit value. + * + *

This method ignores the input value and always returns the explicit value set during + * initialization or via {@link #setExplicitValue(Byte)}. If the input is null, it returns null + * to preserve null-safety. + * + * @param input The original byte value (ignored except for null check) + * @return The explicit value that replaces the original value, or null if input is null + */ @Override protected Byte modifyImplementationHook(Byte input) { if (input == null) { @@ -43,14 +79,29 @@ protected Byte modifyImplementationHook(Byte input) { return explicitValue; } - public Byte getExplicitValue() { + /** + * Gets the explicit value that will replace the original value. + * + * @return The explicit byte value + */ + public byte getExplicitValue() { return explicitValue; } - public void setExplicitValue(Byte explicitValue) { + /** + * Sets the explicit value that will replace the original value. + * + * @param explicitValue The new byte value to use + */ + public void setExplicitValue(byte explicitValue) { this.explicitValue = explicitValue; } + /** + * Computes the hash code for this object. The hash code is based solely on the explicit value. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -58,6 +109,13 @@ public int hashCode() { return hash; } + /** + * Compares this ByteExplicitValueModification with another object for equality. Two + * ByteExplicitValueModifications are considered equal if their explicit values are equal. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +131,11 @@ public boolean equals(Object obj) { return Objects.equals(explicitValue, other.explicitValue); } + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type and explicit value + */ @Override public String toString() { return "ByteExplicitValueModification{" + "explicitValue=" + explicitValue + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteSubtractModification.java b/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteSubtractModification.java index c422e60c..0dd4d4c8 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteSubtractModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteSubtractModification.java @@ -11,30 +11,66 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that subtracts a constant value from a ModifiableByte. + * + *

This modification subtracts a specified byte value (subtrahend) from the input value when + * applied. It can be used to decrement byte values at runtime. + * + * @see ModifiableByte + */ @XmlRootElement public class ByteSubtractModification extends VariableModification { - private Byte subtrahend; + /** The value to be subtracted from the original byte */ + private byte subtrahend; - public ByteSubtractModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private ByteSubtractModification() { super(); } - public ByteSubtractModification(Byte subtrahend) { + /** + * Creates a new subtraction modification with the specified subtrahend. + * + * @param subtrahend The value to subtract from the original byte + */ + public ByteSubtractModification(byte subtrahend) { super(); this.subtrahend = subtrahend; } + /** + * Copy constructor. + * + * @param other The ByteSubtractModification to copy from + */ public ByteSubtractModification(ByteSubtractModification other) { super(other); subtrahend = other.subtrahend; } + /** + * Creates a copy of this modification. + * + * @return A new ByteSubtractModification instance with the same properties + */ @Override public ByteSubtractModification createCopy() { return new ByteSubtractModification(this); } + /** + * Modifies the input by subtracting the subtrahend. + * + *

Note that this operation may cause byte underflow if the result falls below + * Byte.MIN_VALUE. In such cases, the result will wrap around according to Java's two's + * complement arithmetic. + * + * @param input The byte value to modify + * @return The result of subtracting the subtrahend from the input, or null if the input is null + */ @Override protected Byte modifyImplementationHook(Byte input) { if (input == null) { @@ -43,14 +79,29 @@ protected Byte modifyImplementationHook(Byte input) { return (byte) (input - subtrahend); } - public Byte getSubtrahend() { + /** + * Gets the subtrahend value used for the subtraction. + * + * @return The subtrahend value + */ + public byte getSubtrahend() { return subtrahend; } - public void setSubtrahend(Byte subtrahend) { + /** + * Sets the subtrahend value to be used for the subtraction. + * + * @param subtrahend The byte value to subtract from the original value + */ + public void setSubtrahend(byte subtrahend) { this.subtrahend = subtrahend; } + /** + * Computes the hash code for this object. The hash code is based solely on the subtrahend. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -58,6 +109,13 @@ public int hashCode() { return hash; } + /** + * Compares this ByteSubtractModification with another object for equality. Two modifications + * are considered equal if they are of the same class and their subtrahend values are equal. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +131,11 @@ public boolean equals(Object obj) { return Objects.equals(subtrahend, other.subtrahend); } + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type and subtrahend value + */ @Override public String toString() { return "ByteSubtractModification{" + "subtrahend=" + subtrahend + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteXorModification.java b/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteXorModification.java index 9b0ffc6e..e40fc1c7 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteXorModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteXorModification.java @@ -11,30 +11,69 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; +/** + * A modification that applies an XOR operation to a ModifiableByte. + * + *

This modification performs a bitwise XOR operation between a specified byte value (the xor + * mask) and the input byte when applied. + * + * @see ModifiableByte + */ @XmlRootElement public class ByteXorModification extends VariableModification { - private Byte xor; + /** The byte value to XOR with the input byte */ + private byte xor; - public ByteXorModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private ByteXorModification() { super(); } - public ByteXorModification(Byte xor) { + /** + * Creates a new XOR modification with the specified byte value. + * + * @param xor The byte value to XOR with the input + */ + public ByteXorModification(byte xor) { super(); this.xor = xor; } + /** + * Copy constructor. + * + * @param other The modification to copy + */ public ByteXorModification(ByteXorModification other) { super(other); xor = other.xor; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same XOR value + */ @Override public ByteXorModification createCopy() { return new ByteXorModification(this); } + /** + * Modifies the input by applying an XOR operation with the configured XOR value. + * + *

This method uses Java's bitwise XOR operator (^) to perform the operation. + * + *

Note that this operation may cause byte overflow according to Java's two's complement + * arithmetic. For example, if a bit is set in both the input and XOR mask, the result will have + * that bit cleared. + * + * @param input The byte value to modify + * @return The result of XORing the input with the configured value, or null if the input is + * null + */ @Override protected Byte modifyImplementationHook(Byte input) { if (input == null) { @@ -43,14 +82,29 @@ protected Byte modifyImplementationHook(Byte input) { return (byte) (input ^ xor); } - public Byte getXor() { + /** + * Gets the byte value used for the XOR operation. + * + * @return The XOR byte value + */ + public byte getXor() { return xor; } - public void setXor(Byte xor) { + /** + * Sets the byte value to use for the XOR operation. + * + * @param xor The new XOR byte value + */ + public void setXor(byte xor) { this.xor = xor; } + /** + * Computes a hash code for this modification. The hash code is based on the XOR value. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -58,6 +112,13 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two ByteXorModification instances are + * considered equal if they have the same XOR value. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -73,6 +134,11 @@ public boolean equals(Object obj) { return Objects.equals(xor, other.xor); } + /** + * Returns a string representation of this modification. + * + * @return A string describing this modification and its XOR value + */ @Override public String toString() { return "ByteXorModification{" + "xor=" + xor + '}'; diff --git a/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ModifiableByte.java b/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ModifiableByte.java index bc8adc22..1b89f69d 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ModifiableByte.java +++ b/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ModifiableByte.java @@ -10,43 +10,97 @@ import de.rub.nds.modifiablevariable.ModifiableVariable; import jakarta.xml.bind.annotation.XmlRootElement; +/** + * A modifiable variable implementation for single byte values. + * + *

This class extends {@link ModifiableVariable} to provide runtime modification capabilities for + * Byte values. It supports various byte-specific modifications such as addition, subtraction, XOR + * operations, and more. + * + *

I many cases it is beneficial to use ModifiableByteArray instead of ModifiableByte, as it + * allows for more uniform treatment in the code. + */ @XmlRootElement public class ModifiableByte extends ModifiableVariable { + /** The original byte value before any modifications */ private Byte originalValue; + /** Default constructor that creates an empty ModifiableByte with no original value. */ public ModifiableByte() { super(); } + /** + * Constructor that creates a ModifiableByte with the specified original value. + * + * @param originalValue The original byte value + */ public ModifiableByte(Byte originalValue) { super(); this.originalValue = originalValue; } + /** + * Copy constructor that creates a new ModifiableByte with the same original value and + * modifications as the provided instance. + * + * @param other The ModifiableByte to copy + */ public ModifiableByte(ModifiableByte other) { super(other); originalValue = other.originalValue; } + /** + * Creates a deep copy of this ModifiableByte. + * + * @return A new ModifiableByte instance with the same properties + */ @Override public ModifiableByte createCopy() { return new ModifiableByte(this); } + /** + * Gets the expected value for assertion validation. + * + * @return The assertion value + */ public Byte getAssertEquals() { return assertEquals; } + /** + * Sets the expected value for assertion validation. + * + * @param assertEquals The expected byte value + */ public void setAssertEquals(Byte assertEquals) { this.assertEquals = assertEquals; } + /** + * Checks if the modified value differs from the original value. + * + *

This method compares bytes using their natural ordering via the compareTo method. + * + * @return true if the value has been modified, false otherwise + * @throws IllegalStateException if the original value is not set + */ @Override public boolean isOriginalValueModified() { - return originalValue != null && originalValue.compareTo(getValue()) != 0; + if (originalValue == null) { + throw new IllegalStateException("Original value must be set before modification"); + } + return originalValue.compareTo(getValue()) != 0; } + /** + * Validates whether the modified value matches the expected value (if set). + * + * @return true if no assertion is set or if the current value equals the expected value + */ @Override public boolean validateAssertions() { boolean valid = true; @@ -58,21 +112,43 @@ public boolean validateAssertions() { return valid; } + /** + * Gets the original, unmodified byte value. + * + * @return The original value + */ @Override public Byte getOriginalValue() { return originalValue; } + /** + * Sets the original byte value. + * + * @param originalValue The new original value + */ @Override public void setOriginalValue(Byte originalValue) { this.originalValue = originalValue; } + /** + * Returns a string representation of this ModifiableByte. + * + * @return A string containing the original value and modifications + */ @Override public String toString() { return "ModifiableByte{" + "originalValue=" + originalValue + innerToString() + '}'; } + /** + * Checks if this ModifiableByte is equal to another object. Two ModifiableByte instances are + * considered equal if they have the same modified value. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -85,6 +161,12 @@ public boolean equals(Object obj) { return getValue() != null ? getValue().equals(that.getValue()) : that.getValue() == null; } + /** + * Computes a hash code for this ModifiableByte. The hash code is based on the modified value + * rather than the original value. + * + * @return The hash code value + */ @Override public int hashCode() { int result = 17; diff --git a/src/main/java/de/rub/nds/modifiablevariable/string/ModifiableString.java b/src/main/java/de/rub/nds/modifiablevariable/string/ModifiableString.java index a373b3c4..05889e9e 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/string/ModifiableString.java +++ b/src/main/java/de/rub/nds/modifiablevariable/string/ModifiableString.java @@ -17,49 +17,115 @@ import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.nio.charset.StandardCharsets; +/** + * A modifiable variable implementation for String values. + * + *

This class extends {@link ModifiableVariable} to provide runtime modification capabilities for + * String values. It supports various string-specific modifications such as appending, prepending, + * inserting and deleting. + * + *

This class uses property-based XML access and the {@link IllegalStringAdapter} to handle + * proper serialization of strings that might contain characters that are problematic in XML. + * + * @see ModifiableVariable + * @see StringAppendModification + * @see StringPrependModification + * @see StringInsertModification + * @see StringDeleteModification + */ @XmlRootElement @XmlAccessorType(XmlAccessType.PROPERTY) public class ModifiableString extends ModifiableVariable { + /** The original string value before any modifications */ protected String originalValue; + /** Default constructor that creates an empty ModifiableString with no original value. */ public ModifiableString() { super(); } + /** + * Constructor that creates a ModifiableString with the specified original value. + * + * @param originalValue The original string value + */ public ModifiableString(String originalValue) { super(); this.originalValue = originalValue; } + /** + * Copy constructor that creates a new ModifiableString with the same original value and + * modifications as the provided instance. + * + * @param other The ModifiableString to copy + */ public ModifiableString(ModifiableString other) { super(other); originalValue = other.originalValue; } + /** + * Creates a deep copy of this ModifiableString. + * + * @return A new ModifiableString instance with the same properties + */ @Override public ModifiableString createCopy() { return new ModifiableString(this); } + /** + * Gets the expected value for assertion validation. + * + *

Uses a special XML adapter to handle strings with characters that might be problematic in + * XML serialization. + * + * @return The assertion value + */ @XmlJavaTypeAdapter(IllegalStringAdapter.class) public String getAssertEquals() { return assertEquals; } + /** + * Sets the expected value for assertion validation. + * + * @param assertEquals The expected string value + */ public void setAssertEquals(String assertEquals) { this.assertEquals = assertEquals; } + /** + * Checks if the modified value differs from the original value. + * + *

This method compares strings using their natural ordering via the compareTo method. + * + * @return true if the value has been modified, false otherwise + */ @Override public boolean isOriginalValueModified() { return originalValue != null && originalValue.compareTo(getValue()) != 0; } - public byte[] getByteArray(int size) { + /** + * Converts the string value to a byte array using ISO-8859-1 encoding. + * + * @return The byte array representation of the string using ISO-8859-1 encoding + */ + public byte[] getByteArray() { return getValue().getBytes(StandardCharsets.ISO_8859_1); } + /** + * Validates whether the modified value matches the expected value (if set). + * + *

This method compares strings using their natural ordering via the compareTo method. + * + * @return true if no assertion is set or if the current value equals the expected value + */ @Override public boolean validateAssertions() { boolean valid = true; @@ -71,17 +137,38 @@ public boolean validateAssertions() { return valid; } + /** + * Gets the original, unmodified string value. + * + *

Uses a special XML adapter to handle strings with characters that might be problematic in + * XML serialization. + * + * @return The original value + */ @Override @XmlJavaTypeAdapter(IllegalStringAdapter.class) public String getOriginalValue() { return originalValue; } + /** + * Sets the original string value. + * + * @param originalValue The new original value + */ @Override public void setOriginalValue(String originalValue) { this.originalValue = originalValue; } + /** + * Returns a string representation of this ModifiableString. + * + *

The original value is escaped using backslash escaping to make control characters and + * other special characters readable. + * + * @return A string containing the escaped original value and modifications + */ @Override public String toString() { return "ModifiableString{" @@ -92,6 +179,13 @@ public String toString() { + '}'; } + /** + * Checks if this ModifiableString is equal to another object. Two ModifiableString instances + * are considered equal if they have the same modified value. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -104,6 +198,12 @@ public boolean equals(Object obj) { return getValue() != null ? getValue().equals(that.getValue()) : that.getValue() == null; } + /** + * Computes a hash code for this ModifiableString. The hash code is based on the modified value + * rather than the original value. + * + * @return The hash code value + */ @Override public int hashCode() { int result = 17; diff --git a/src/main/java/de/rub/nds/modifiablevariable/string/StringAppendValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/string/StringAppendValueModification.java index 5a494254..08696e47 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/string/StringAppendValueModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/string/StringAppendValueModification.java @@ -15,32 +15,70 @@ import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.util.Objects; -/** Modification that appends a string to the original value. */ +/** + * A modification that appends a string to the end of a ModifiableString. + * + *

This modification takes the original string and adds a specified string to its end when + * applied. It can be used to add text to the end of string values at runtime. + * + * @see ModifiableString + * @see StringPrependValueModification + * @see StringInsertValueModification + */ @XmlRootElement public class StringAppendValueModification extends VariableModification { + /** The string value to append to the input */ @XmlJavaTypeAdapter(IllegalStringAdapter.class) private String appendValue; - public StringAppendValueModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private StringAppendValueModification() { super(); } + /** + * Creates a new append modification with the specified string value. + * + * @param appendValue The string to append to the input + * @throws NullPointerException if appendValue is null + */ public StringAppendValueModification(String appendValue) { super(); - this.appendValue = appendValue; + this.appendValue = Objects.requireNonNull(appendValue, "AppendValue must not be null"); } + /** + * Copy constructor. + * + * @param other The modification to copy + */ public StringAppendValueModification(StringAppendValueModification other) { super(other); appendValue = other.appendValue; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same append value + */ @Override public StringAppendValueModification createCopy() { return new StringAppendValueModification(this); } + /** + * Modifies the input by appending the specified string value. + * + *

This method creates a new string by concatenating the original input string with the + * append value. The implementation uses Java's built-in string concatenation, which creates a + * new string object, preserving the immutability of the original string. + * + * @param input The original string to modify + * @return A new string with the append value added at the end, or null if the input is null + */ @Override protected String modifyImplementationHook(String input) { if (input == null) { @@ -49,14 +87,29 @@ protected String modifyImplementationHook(String input) { return input + appendValue; } + /** + * Gets the string value that will be appended to the input. + * + * @return The string to append + */ public String getAppendValue() { return appendValue; } + /** + * Sets the string value that will be appended to the input. + * + * @param appendValue The new string to append + */ public void setAppendValue(String appendValue) { - this.appendValue = appendValue; + this.appendValue = Objects.requireNonNull(appendValue, "AppendValue must not be null"); } + /** + * Computes a hash code for this modification. The hash code is based on the append value. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -64,6 +117,13 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two StringAppendValueModification + * instances are considered equal if they have the same append value. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -79,6 +139,14 @@ public boolean equals(Object obj) { return Objects.equals(appendValue, other.appendValue); } + /** + * Returns a string representation of this modification. + * + *

The append value is escaped using backslash escaping to make control characters and other + * special characters readable. + * + * @return A string describing this modification + */ @Override public String toString() { return "StringAppendValueModification{" diff --git a/src/main/java/de/rub/nds/modifiablevariable/string/StringDeleteModification.java b/src/main/java/de/rub/nds/modifiablevariable/string/StringDeleteModification.java index 9ba8ff91..d07cbf9d 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/string/StringDeleteModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/string/StringDeleteModification.java @@ -11,35 +11,85 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.util.Objects; -/** Modification that deletes part of a string from the original value. */ +/** + * A modification that deletes a portion of a ModifiableString. + * + *

This modification removes a specified number of characters from the original string starting + * at a specified position when applied. It can be used to create truncated or partial string data + * at runtime. + * + * @see ModifiableString + * @see StringInsertValueModification + */ @XmlRootElement public class StringDeleteModification extends VariableModification { + /** The number of characters to delete */ private int count; + /** The position from which to start deletion (0-based index) */ private int startPosition; - public StringDeleteModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private StringDeleteModification() { super(); } + /** + * Creates a new modification with the specified parameters. + * + *

This constructor sets the position at which to start deletion and the number of characters + * to delete. + * + * @param startPosition The position from which to start deletion (0-based index) + * @param count The number of characters to delete + */ public StringDeleteModification(int startPosition, int count) { super(); this.startPosition = startPosition; this.count = count; } + /** + * Copy constructor for creating a deep copy of an existing modification. + * + * @param other The modification to copy + */ public StringDeleteModification(StringDeleteModification other) { super(other); count = other.count; startPosition = other.startPosition; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same deletion parameters + */ @Override public StringDeleteModification createCopy() { return new StringDeleteModification(this); } + /** + * Modifies the input by removing characters from the specified position. + * + *

This method creates a new string with the specified section removed. It effectively takes + * the characters before the deletion point, then concatenates them with the characters after + * the deletion point, creating a shorter string. + * + *

+ * + * @param input The original string + * @return A new string with the specified portion removed, or null if the input is null, or the + * original string if it's empty + */ @Override protected String modifyImplementationHook(String input) { if (input == null) { @@ -64,22 +114,49 @@ protected String modifyImplementationHook(String input) { return new StringBuilder(input).delete(deleteStartPosition, deleteEndPosition).toString(); } + /** + * Gets the number of characters to delete. + * + * @return The number of characters to delete + */ public int getCount() { return count; } + /** + * Sets the number of characters to delete. + * + * @param count The new number of characters to delete + */ public void setCount(int count) { this.count = count; } + /** + * Gets the position from which to start deletion. + * + * @return The start position (0-based index) + */ public int getStartPosition() { return startPosition; } + /** + * Sets the position from which to start deletion. + * + * @param startPosition The new start position (0-based index) + */ public void setStartPosition(int startPosition) { this.startPosition = startPosition; } + /** + * Computes a hash code for this modification. + * + *

The hash code is based on the count and start position. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -88,6 +165,15 @@ public int hashCode() { return hash; } + /** + * Compares this modification with another object for equality. + * + *

Two StringDeleteModification objects are considered equal if they have the same count and + * start position. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -106,6 +192,13 @@ public boolean equals(Object obj) { return Objects.equals(count, other.count); } + /** + * Returns a string representation of this modification. + * + *

The string includes the class name, count, and start position. + * + * @return A string representation of this object + */ @Override public String toString() { return "StringDeleteModification{" diff --git a/src/main/java/de/rub/nds/modifiablevariable/string/StringExplicitValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/string/StringExplicitValueModification.java index e5dc57bd..d2856644 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/string/StringExplicitValueModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/string/StringExplicitValueModification.java @@ -15,31 +15,67 @@ import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.util.Objects; +/** + * A modification that replaces the original string with an explicitly defined value. + * + *

This modification ignores the original value and always returns a predefined string specified + * at initialization or via setter. It can be used to inject specific string content regardless of + * the original value. + * + * @see ModifiableString + */ @XmlRootElement public class StringExplicitValueModification extends VariableModification { + /** The explicit string that will replace the original value */ @XmlJavaTypeAdapter(IllegalStringAdapter.class) - protected String explicitValue; + private String explicitValue; - public StringExplicitValueModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private StringExplicitValueModification() { super(); } + /** + * Creates a new explicit value modification with the specified value. + * + * @param explicitValue The string that will replace the original value + */ public StringExplicitValueModification(String explicitValue) { super(); - this.explicitValue = explicitValue; + this.explicitValue = + Objects.requireNonNull(explicitValue, "ExplicitValue must not be null"); } + /** + * Copy constructor. + * + * @param other The modification to copy + */ public StringExplicitValueModification(StringExplicitValueModification other) { super(other); explicitValue = other.explicitValue; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same explicit value + */ @Override public StringExplicitValueModification createCopy() { return new StringExplicitValueModification(this); } + /** + * Modifies the input by replacing it with the explicit value. + * + *

This method ignores the input value and always returns the explicit value. + * + * @param input The original string (ignored except for null check) + * @return The explicit value, or null if input was null + */ @Override protected String modifyImplementationHook(String input) { if (input == null) { @@ -48,14 +84,30 @@ protected String modifyImplementationHook(String input) { return explicitValue; } + /** + * Gets the explicit value that will replace the original value. + * + * @return The explicit string + */ public String getExplicitValue() { return explicitValue; } + /** + * Sets the explicit value that will replace the original value. + * + * @param explicitValue The new explicit string to use + */ public void setExplicitValue(String explicitValue) { - this.explicitValue = explicitValue; + this.explicitValue = + Objects.requireNonNull(explicitValue, "ExplicitValue must not be null"); } + /** + * Computes a hash code for this modification. The hash code is based on the explicit value. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -63,6 +115,13 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two StringExplicitValueModification + * instances are considered equal if they have the same explicit value. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -78,6 +137,11 @@ public boolean equals(Object obj) { return Objects.equals(explicitValue, other.explicitValue); } + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type and explicit value + */ @Override public String toString() { return "StringExplicitValueModification{" diff --git a/src/main/java/de/rub/nds/modifiablevariable/string/StringInsertValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/string/StringInsertValueModification.java index d58ca3fd..9774026e 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/string/StringInsertValueModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/string/StringInsertValueModification.java @@ -15,36 +15,76 @@ import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.util.Objects; -/** Modification that inserts a string to the original value. */ +/** + * A modification that inserts a string at a specified position within the original string. + * + *

This modification inserts additional text at the specified position in the input string. It + * handles special cases such as negative positions and positions beyond the string length. + * + * @see ModifiableString + * @see StringDeleteModification + * @see StringAppendValueModification + * @see StringPrependValueModification + */ @XmlRootElement public class StringInsertValueModification extends VariableModification { + /** The string to insert into the original string */ @XmlJavaTypeAdapter(IllegalStringAdapter.class) private String insertValue; + /** The position at which to insert the string (0-based index) */ private int startPosition; - public StringInsertValueModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private StringInsertValueModification() { super(); } + /** + * Creates a new insertion modification with the specified value and position. + * + * @param insertValue The string to insert into the original string + * @param startPosition The position at which to insert the string (0-based index) + */ public StringInsertValueModification(String insertValue, int startPosition) { super(); - this.insertValue = insertValue; + this.insertValue = Objects.requireNonNull(insertValue, "InsertValue must not be null"); this.startPosition = startPosition; } + /** + * Copy constructor. + * + * @param other The modification to copy + */ public StringInsertValueModification(StringInsertValueModification other) { super(other); insertValue = other.insertValue; startPosition = other.startPosition; } + /** + * Creates a deep copy of this modification. + * + * @return A new instance with the same insert value and position + */ @Override public StringInsertValueModification createCopy() { return new StringInsertValueModification(this); } + /** + * Modifies the input by inserting the specified string at the given position. + * + *

If the position is negative, it wraps around to insert from the end of the string. If the + * position exceeds the string length, it's adjusted using modulo arithmetic. Insertion at the + * end of the string is also supported, effectivly resulting in an append. + * + * @param input The string to modify + * @return A new string with the insertion applied, or null if input was null + */ @Override protected String modifyImplementationHook(String input) { if (input == null) { @@ -59,22 +99,48 @@ protected String modifyImplementationHook(String input) { return new StringBuilder(input).insert(insertPosition, insertValue).toString(); } + /** + * Gets the string that will be inserted into the original string. + * + * @return The string to insert + */ public String getInsertValue() { return insertValue; } + /** + * Sets the string that will be inserted into the original string. + * + * @param insertValue The new string to insert + */ public void setInsertValue(String insertValue) { - this.insertValue = insertValue; + this.insertValue = Objects.requireNonNull(insertValue, "InsertValue must not be null"); } + /** + * Gets the position at which the string will be inserted. + * + * @return The insertion position (0-based index) + */ public int getStartPosition() { return startPosition; } + /** + * Sets the position at which the string will be inserted. + * + * @param startPosition The new insertion position (0-based index) + */ public void setStartPosition(int startPosition) { this.startPosition = startPosition; } + /** + * Computes a hash code for this modification. The hash code is based on the insert value and + * position. + * + * @return The hash code value + */ @Override public int hashCode() { int hash = 7; @@ -83,6 +149,13 @@ public int hashCode() { return hash; } + /** + * Checks if this modification is equal to another object. Two StringInsertValueModification + * instances are considered equal if they have the same insert value and start position. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -101,6 +174,11 @@ public boolean equals(Object obj) { return Objects.equals(insertValue, other.insertValue); } + /** + * Returns a string representation of this modification. + * + * @return A string containing the modification type, insert value, and position + */ @Override public String toString() { return "StringInsertValueModification{" diff --git a/src/main/java/de/rub/nds/modifiablevariable/string/StringPrependValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/string/StringPrependValueModification.java index c0176754..643320cd 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/string/StringPrependValueModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/string/StringPrependValueModification.java @@ -15,32 +15,75 @@ import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.util.Objects; -/** Modification that prepends a string to the original value. */ +/** + * A modification that prepends a string to the beginning of a ModifiableString. + * + *

This modification takes the original string and adds a specified string to its beginning when + * applied. It can be used to add text to the start of string values at runtime, which is + * particularly useful for testing protocol implementations. + * + * @see ModifiableString + * @see StringAppendValueModification + * @see StringInsertValueModification + */ @XmlRootElement public class StringPrependValueModification extends VariableModification { + /** The string value to be prepended to the original string */ @XmlJavaTypeAdapter(IllegalStringAdapter.class) private String prependValue; - public StringPrependValueModification() { + /** Default constructor for serialization. */ + @SuppressWarnings("unused") + private StringPrependValueModification() { super(); } + /** + * Creates a new prepend modification with the specified value. + * + * @param prependValue The string to prepend to the original string + * @throws NullPointerException if prependValue is null + */ public StringPrependValueModification(String prependValue) { super(); - this.prependValue = prependValue; + this.prependValue = Objects.requireNonNull(prependValue, "PrependValue must not be null"); } + /** + * Copy constructor. + * + * @param other The StringPrependValueModification to copy from + */ public StringPrependValueModification(StringPrependValueModification other) { super(other); prependValue = other.prependValue; } + /** + * Creates a copy of this modification. + * + * @return A new StringPrependValueModification instance with the same properties + */ @Override public StringPrependValueModification createCopy() { return new StringPrependValueModification(this); } + /** + * Modifies the input by prepending the specified string value. + * + *

This method creates a new string by concatenating the prepend value with the original + * input string. The implementation uses Java's built-in string concatenation, which creates a + * new string object, preserving the immutability of the original string. + * + *

This concatenation approach ensures efficient string creation while maintaining correct + * behavior even with special characters or Unicode strings. + * + * @param input The original string to modify + * @return A new string with the prepend value added at the beginning, or null if the input is + * null + */ @Override protected String modifyImplementationHook(String input) { if (input == null) { @@ -49,14 +92,30 @@ protected String modifyImplementationHook(String input) { return prependValue + input; } + /** + * Gets the string value used for prepending. + * + * @return The prepend value + */ public String getPrependValue() { return prependValue; } + /** + * Sets the string value to be prepended to the original value. + * + * @param prependValue The string to prepend to the original string + * @throws NullPointerException if prependValue is null + */ public void setPrependValue(String prependValue) { - this.prependValue = prependValue; + this.prependValue = Objects.requireNonNull(prependValue, "PrependValue must not be null"); } + /** + * Computes the hash code for this object. + * + * @return A hash code value for this object + */ @Override public int hashCode() { int hash = 7; @@ -64,6 +123,12 @@ public int hashCode() { return hash; } + /** + * Compares this StringPrependValueModification with another object for equality. + * + * @param obj The object to compare with + * @return true if the objects are equal, false otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -79,6 +144,12 @@ public boolean equals(Object obj) { return Objects.equals(prependValue, other.prependValue); } + /** + * Returns a string representation of this modification. The prepend value is escaped to make + * non-printable characters visible. + * + * @return A string containing the modification type and escaped prepend value + */ @Override public String toString() { return "StringPrependValueModification{" diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/ArrayConverter.java b/src/main/java/de/rub/nds/modifiablevariable/util/ArrayConverter.java index 99b9c038..15c70374 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/ArrayConverter.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/ArrayConverter.java @@ -12,19 +12,36 @@ import java.math.BigInteger; import java.util.List; -/** A utility class to handle arrays and array conversions */ +/** + * A utility class for array conversions and manipulations. + * + *

This class provides methods for: + * + *

+ * + *

All methods are static, and the class cannot be instantiated. + */ public final class ArrayConverter { + /** Private constructor to prevent instantiation of this utility class. */ private ArrayConverter() { super(); } /** - * Takes a long value and converts it to 8 bytes (needed for example to convert SQN numbers in - * TLS records) + * Converts a long value to an 8-byte array representing a 64-bit unsigned integer. * - * @param value long value - * @return long represented by 8 bytes + *

This method uses big-endian byte order (most significant byte first), which is the network + * byte order and the standard for many protocols. + * + * @param value The long value to convert + * @return A byte array of length 8 representing the value in big-endian order */ public static byte[] longToUint64Bytes(long value) { byte[] result = new byte[8]; @@ -39,7 +56,17 @@ public static byte[] longToUint64Bytes(long value) { return result; } - /** Note: This will truncate the long */ + /** + * Converts a long value to a 6-byte array representing a 48-bit unsigned integer. + * + *

This method uses big-endian byte order (most significant byte first). The highest 16 bits + * of the long value will be truncated. + * + *

48-bit values are sometimes used in networking protocols for timestamps or identifiers. + * + * @param value The long value to convert (highest 16 bits will be truncated) + * @return A byte array of length 6 representing the value in big-endian order + */ public static byte[] longToUint48Bytes(long value) { byte[] output = new byte[6]; output[0] = (byte) (value >>> 40); @@ -52,10 +79,16 @@ public static byte[] longToUint48Bytes(long value) { } /** - * Takes an int value and converts it to 4 bytes + * Converts a long value to a 4-byte array representing a 32-bit unsigned integer. * - * @param value int value - * @return int represented by 4 bytes + *

This method uses big-endian byte order (most significant byte first). Only the lowest 32 + * bits of the long value are used; higher bits are truncated. + * + *

This is commonly used for 32-bit protocol fields like sequence numbers, timestamps, and + * message lengths. + * + * @param value The long value to convert (highest 32 bits will be truncated) + * @return A byte array of length 4 representing the value in big-endian order */ public static byte[] longToUint32Bytes(long value) { byte[] result = new byte[4]; @@ -66,6 +99,17 @@ public static byte[] longToUint32Bytes(long value) { return result; } + /** + * Converts an 8-byte array representing a 64-bit unsigned integer to a long value. + * + *

This method uses big-endian byte order (most significant byte first), which is the network + * byte order and the standard for many protocols. + * + *

This is the inverse operation of {@link #longToUint64Bytes(long)}. + * + * @param bytes The byte array of length 8 to convert + * @return The long value represented by the byte array + */ public static long uInt64BytesToLong(byte[] bytes) { return (long) (bytes[0] & 0xFF) << 56 | (long) (bytes[1] & 0xFF) << 48 @@ -77,6 +121,17 @@ public static long uInt64BytesToLong(byte[] bytes) { | (long) (bytes[7] & 0xFF); } + /** + * Converts a 4-byte array representing a 32-bit unsigned integer to a long value. + * + *

This method uses big-endian byte order (most significant byte first), which is the network + * byte order and the standard for many protocols. + * + *

This is the inverse operation of {@link #longToUint32Bytes(long)}. + * + * @param bytes The byte array of length 4 to convert + * @return The long value represented by the byte array + */ public static long uInt32BytesToLong(byte[] bytes) { return (long) (bytes[0] & 0xFF) << 24 | (bytes[1] & 0xFF) << 16 @@ -85,7 +140,7 @@ public static long uInt32BytesToLong(byte[] bytes) { } /** - * Takes an integer value and stores its last bytes into a byte array + * Takes an integer value and stores its last bytes into a byte array of a given size. * * @param value integer value * @param size byte size of the new integer byte array @@ -162,6 +217,18 @@ public static long bytesToLong(byte[] value) { return result; } + /** + * Converts a byte array to a hexadecimal string representation. + * + *

This method automatically determines whether to use pretty-printing based on the array + * length. If the array has more than 15 bytes, pretty-printing is enabled for better + * readability. + * + *

If the input array is null, an empty array is used. + * + * @param array The byte array to convert + * @return A string representation of the bytes in hexadecimal format + */ public static String bytesToHexString(byte[] array) { if (array == null) { array = new byte[0]; @@ -170,6 +237,18 @@ public static String bytesToHexString(byte[] array) { return bytesToHexString(array, usePrettyPrinting); } + /** + * Converts a byte array to a hexadecimal string representation with optional pretty-printing. + * + *

When pretty-printing is enabled, the output includes newlines and spacing to improve + * readability of longer byte sequences. + * + *

If the input array is null, an empty array is used. + * + * @param array The byte array to convert + * @param usePrettyPrinting Whether to use pretty-printing formatting + * @return A string representation of the bytes in hexadecimal format + */ public static String bytesToHexString(byte[] array, boolean usePrettyPrinting) { if (array == null) { array = new byte[0]; @@ -177,6 +256,27 @@ public static String bytesToHexString(byte[] array, boolean usePrettyPrinting) { return bytesToHexString(array, usePrettyPrinting, true); } + /** + * Converts a byte array to a hexadecimal string representation with detailed formatting + * options. + * + *

This method provides full control over the formatting: + * + *

+ * + *

If the input array is null, an empty array is used. + * + * @param array The byte array to convert + * @param usePrettyPrinting Whether to use pretty-printing formatting + * @param initialNewLine Whether to begin with a new line (only applies if pretty-printing is + * enabled) + * @return A string representation of the bytes in hexadecimal format + */ public static String bytesToHexString( byte[] array, boolean usePrettyPrinting, boolean initialNewLine) { StringBuilder result = new StringBuilder(); @@ -200,15 +300,54 @@ public static String bytesToHexString( return result.toString(); } + /** + * Converts a ModifiableByteArray to a hexadecimal string representation. + * + *

This method automatically determines whether to use pretty-printing based on the array + * length. If the array has more than 15 bytes, pretty-printing is enabled for better + * readability. + * + * @param array The ModifiableByteArray to convert + * @return A string representation of the bytes in hexadecimal format + */ public static String bytesToHexString(ModifiableByteArray array) { return bytesToHexString(array.getValue()); } + /** + * Converts a ModifiableByteArray to a hexadecimal string representation with optional + * pretty-printing. + * + *

When pretty-printing is enabled, the output includes newlines and spacing to improve + * readability of longer byte sequences. + * + * @param array The ModifiableByteArray to convert + * @param usePrettyPrinting Whether to use pretty-printing formatting + * @return A string representation of the bytes in hexadecimal format + */ public static String bytesToHexString(ModifiableByteArray array, boolean usePrettyPrinting) { - return bytesToHexString(array.getValue(), usePrettyPrinting, true); } + /** + * Converts a ModifiableByteArray to a hexadecimal string representation with detailed + * formatting options. + * + *

This method provides full control over the formatting: + * + *

+ * + * @param array The ModifiableByteArray to convert + * @param usePrettyPrinting Whether to use pretty-printing formatting + * @param initialNewLine Whether to begin with a new line (only applies if pretty-printing is + * enabled) + * @return A string representation of the bytes in hexadecimal format + */ public static String bytesToHexString( ModifiableByteArray array, boolean usePrettyPrinting, boolean initialNewLine) { return bytesToHexString(array.getValue(), usePrettyPrinting, initialNewLine); @@ -228,6 +367,20 @@ public static String bytesToRawHexString(byte[] array) { return result.toString(); } + /** + * Concatenates multiple arrays of the same type into a single array. + * + *

This generic method works with arrays of any reference type. It creates a new array that + * contains all elements from the input arrays in the order they are provided. + * + *

If any of the input arrays is null, it is skipped without causing an error. However, at + * least one non-null array must be provided. + * + * @param The component type of the arrays + * @param arrays The arrays to concatenate + * @return A new array containing all elements from the input arrays + * @throws IllegalArgumentException if arrays is null or empty + */ @SafeVarargs public static T[] concatenate(T[]... arrays) { if (arrays == null || arrays.length == 0) { @@ -252,6 +405,19 @@ public static T[] concatenate(T[]... arrays) { return result; } + /** + * Concatenates multiple byte arrays into a single byte array. + * + *

This method creates a new byte array that contains all elements from the input arrays in + * the order they are provided. + * + *

If any of the input arrays is null, it is skipped without causing an error. However, at + * least one non-null array must be provided. + * + * @param arrays The byte arrays to concatenate + * @return A new byte array containing all elements from the input arrays + * @throws IllegalArgumentException if arrays is null or empty + */ public static byte[] concatenate(byte[]... arrays) { if (arrays == null || arrays.length == 0) { throw new IllegalArgumentException( @@ -274,6 +440,18 @@ public static byte[] concatenate(byte[]... arrays) { return result; } + /** + * Concatenates two byte arrays, using only a specified number of bytes from the second array. + * + *

This method is similar to {@link #concatenate(byte[]...)}, but allows you to limit how + * many bytes are taken from the second array. This is useful when you need to append only a + * portion of one array to another. + * + * @param array1 The first byte array (used in its entirety) + * @param array2 The second byte array (used partially) + * @param numberOfArray2Bytes The number of bytes to use from array2 + * @return A new byte array containing array1 followed by the specified portion of array2 + */ public static byte[] concatenate(byte[] array1, byte[] array2, int numberOfArray2Bytes) { int length = array1.length + numberOfArray2Bytes; byte[] result = new byte[length]; @@ -282,6 +460,15 @@ public static byte[] concatenate(byte[] array1, byte[] array2, int numberOfArray return result; } + /** + * Replaces all zero bytes in an array with non-zero values. + * + *

This method modifies the input array in-place by replacing any bytes with value 0x00 with + * the value 0x01. This can be useful in cryptographic contexts where zero bytes might cause + * special behaviors that need to be avoided. + * + * @param array The byte array to modify (modified in-place) + */ public static void makeArrayNonZero(byte[] array) { for (int i = 0; i < array.length; i++) { if (array[i] == 0) { @@ -291,24 +478,37 @@ public static void makeArrayNonZero(byte[] array) { } /** - * Takes a BigInteger value and returns its byte array representation filled with 0x00 bytes to - * achieve the block size length. + * Converts a BigInteger to a byte array with specific output size padding. * - * @param value big integer to be converted - * @param blockSize block size to be achieved - * @param removeSignByte in a case the removeSignByte is set, the sign byte is removed (in case - * the byte array contains one) - * @return big integer represented in bytes, padded to a specific block size + *

This method is particularly useful for cryptographic operations that require values to be + * padded to specific block sizes. + * + *

The resulting array will have a length that is a multiple of the specified size. If the + * BigInteger's byte representation is not of the specified size, the array will be padded with + * leading zeros. + * + *

Special cases: + * + *

+ * + * @param value The BigInteger to convert + * @param expectedLength The expecxted length to align the output to + * @param removeSignByte Whether to remove the sign byte (if present) before padding + * @return A byte array representation of the BigInteger, padded to be a multiple of the block + * size */ public static byte[] bigIntegerToByteArray( - BigInteger value, int blockSize, boolean removeSignByte) { - if (blockSize == 0) { + BigInteger value, int expectedLength, boolean removeSignByte) { + if (expectedLength == 0) { return new byte[0]; } else if (value.equals(BigInteger.ZERO)) { - return new byte[blockSize]; + return new byte[expectedLength]; } byte[] array = value.toByteArray(); - int remainder = array.length % blockSize; + int remainder = array.length % expectedLength; byte[] result = array; byte[] tmp; @@ -316,13 +516,13 @@ public static byte[] bigIntegerToByteArray( tmp = new byte[result.length - 1]; System.arraycopy(result, 1, tmp, 0, tmp.length); result = tmp; - remainder = tmp.length % blockSize; + remainder = tmp.length % expectedLength; } if (remainder > 0) { // add zeros to fit size - tmp = new byte[result.length + blockSize - remainder]; - System.arraycopy(result, 0, tmp, blockSize - remainder, result.length); + tmp = new byte[result.length + expectedLength - remainder]; + System.arraycopy(result, 0, tmp, expectedLength - remainder, result.length); result = tmp; } @@ -330,8 +530,8 @@ public static byte[] bigIntegerToByteArray( } /** - * Takes a BigInteger value and returns its byte array representation, if necessary the sign - * byte is removed. + * Takes a BigInteger value and returns its (unsigned) byte array representation, if necessary + * the sign byte is removed. * * @param value big integer to be converted * @return big integer represented in bytes @@ -459,6 +659,18 @@ public static Integer indexOf(byte[] outerArray, byte[] innerArray) { return null; } + /** + * Converts a signed byte to an unsigned int. + * + *

In Java, bytes are signed 8-bit values ranging from -128 to 127. This method converts a + * byte to an unsigned int value (0-255) by masking with 0xFF. + * + *

This is particularly useful when dealing with network protocols or file formats where + * bytes are often interpreted as unsigned values. + * + * @param b The byte to convert + * @return The unsigned int value (0-255) corresponding to the byte + */ public static int byteToUnsignedInt(byte b) { return b & 0xff; } diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/BadFixedRandom.java b/src/main/java/de/rub/nds/modifiablevariable/util/BadFixedRandom.java index b874a58e..200e9853 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/BadFixedRandom.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/BadFixedRandom.java @@ -10,21 +10,40 @@ import java.util.Random; /** - * A fake random number generator for testing. This generator will always return the byte "retVal" - * passed to the constructor. + * A deterministic random number generator that always returns the same byte value. + * + *

This class extends Java's {@link Random} class but overrides its behavior to always return a + * fixed byte value instead of generating truly random values. It is designed specifically for + * testing scenarios where predictable, reproducible "random" values are required. + * + *

Note that this implementation only overrides the {@link #nextBytes(byte[])} method; other + * methods from the {@link Random} superclass are not overridden and may still produce pseudo-random + * values that don't match the fixed byte value. */ public class BadFixedRandom extends Random { + /** The fixed byte value that will be returned for all "random" bytes */ private final byte retVal; + /** + * Creates a new fixed random generator with the specified return value. + * + * @param retVal The byte value that will be returned by this generator + */ public BadFixedRandom(byte retVal) { super(); this.retVal = retVal; } /** - * Fills a user-supplied byte array with the fixed byte given at object initialization. The - * number of "random" bytes produced is equal to the length of the byte array. + * Fills a user-supplied byte array with the fixed byte given at object initialization. + * + *

Instead of generating random values, this method simply fills the entire array with the + * fixed byte value specified in the constructor. + * + *

The number of "random" bytes produced is equal to the length of the byte array. + * + * @param bytes The byte array to be filled with the fixed value */ @Override public void nextBytes(byte[] bytes) { diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/BadRandom.java b/src/main/java/de/rub/nds/modifiablevariable/util/BadRandom.java index b858e6fc..d7e1dd7c 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/BadRandom.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/BadRandom.java @@ -12,25 +12,74 @@ import java.security.SecureRandomSpi; import java.util.Random; +/** + * A deterministic, insecure implementation of SecureRandom for testing purposes. + * + *

This class extends SecureRandom but delegates all random number generation to a + * java.util.Random instance, which is not cryptographically secure but is deterministic when + * initialized with a fixed seed. This makes it useful for testing security protocols where + * reproducible "randomness" is needed. + * + *

The primary use case is testing protocol implementations that rely on SecureRandom where we + * need to control the "random" values to create reproducible test cases. + */ public class BadRandom extends SecureRandom { + /** The underlying Random instance that provides the "random" values */ private Random random; + /** + * Default constructor that creates a BadRandom with a fixed seed of 0. + * + *

This ensures reproducible behavior across test runs. + */ public BadRandom() { super(); random = new Random(0); } + /** + * Creates a BadRandom that delegates to the specified Random instance. + * + *

The seed parameter is ignored, as the provided Random instance is used directly. + * + * @param random The Random instance to use for generating values + * @param seed Ignored parameter (for API compatibility) + * @deprecated Use {@link #BadRandom(Random)} instead + */ + @Deprecated public BadRandom(Random random, byte[] seed) { super(); this.random = random; } + public BadRandom(Random random) { + super(); + this.random = random; + } + + /** + * Creates a BadRandom with custom Random, SecureRandomSpi, and Provider. + * + *

Only the Random instance is actually used; the other parameters are ignored. + * + * @param random The Random instance to use for generating values + * @param secureRandomSpi Ignored parameter (for API compatibility) + * @param provider Ignored parameter (for API compatibility) + * @deprecated Use {@link #BadRandom(Random)} instead + */ + @Deprecated public BadRandom(Random random, SecureRandomSpi secureRandomSpi, Provider provider) { super(); this.random = random; } + /** + * Generates a seed byte array using the underlying Random instance. + * + * @param numBytes The number of bytes to generate + * @return A byte array of the specified length with "random" values + */ @Override public byte[] generateSeed(int numBytes) { byte[] ray = new byte[numBytes]; @@ -38,56 +87,109 @@ public byte[] generateSeed(int numBytes) { return ray; } + /** + * Fills the provided byte array with random bytes from the underlying Random instance. + * + * @param bytes The byte array to fill with random values + */ @Override public synchronized void nextBytes(byte[] bytes) { random.nextBytes(bytes); } + /** + * Sets a new seed for the random number generation by creating a new Random instance. + * + * @param seed The seed value for the new Random instance + */ @Override public void setSeed(long seed) { random = new Random(seed); } + /** Setting seed is meaningless in this implementation and does nothing. */ @Override - public synchronized void setSeed(byte[] seed) { - throw new UnsupportedOperationException(); - } - + public synchronized void setSeed(byte[] seed) {} + + /** + * Returns a warning message instead of an algorithm name to make it clear that this is not a + * secure random implementation. + * + * @return A warning message about the insecurity of this class + */ @Override public String getAlgorithm() { return "WARNING: We use a very insecure PRNG. THIS IS NOT A SECURE RANDOM OBJECT. USE FOR TESTING ONLY"; } + /** + * Returns the next pseudorandom integer from the underlying Random instance. + * + * @return A pseudorandom integer + */ @Override public int nextInt() { return random.nextInt(); } + /** + * Returns a pseudorandom integer between 0 (inclusive) and the specified bound (exclusive). + * + * @param bound The upper bound (exclusive) for the random value + * @return A pseudorandom integer in the range [0, bound) + */ @Override public int nextInt(int bound) { return random.nextInt(bound); } + /** + * Returns the next pseudorandom long value from the underlying Random instance. + * + * @return A pseudorandom long value + */ @Override public long nextLong() { return random.nextLong(); } + /** + * Returns the next pseudorandom boolean value from the underlying Random instance. + * + * @return A pseudorandom boolean value + */ @Override public boolean nextBoolean() { return random.nextBoolean(); } + /** + * Returns the next pseudorandom float value from the underlying Random instance. + * + * @return A pseudorandom float in the range [0.0, 1.0) + */ @Override public float nextFloat() { return random.nextFloat(); } + /** + * Returns the next pseudorandom double value from the underlying Random instance. + * + * @return A pseudorandom double in the range [0.0, 1.0) + */ @Override public double nextDouble() { return random.nextDouble(); } + /** + * Returns the next pseudorandom, Gaussian ("normally") distributed double value from the + * underlying Random instance. + * + * @return A pseudorandom double from a Gaussian distribution with mean 0.0 and standard + * deviation 1.0 + */ @Override public synchronized double nextGaussian() { return random.nextGaussian(); diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/ComparableByteArray.java b/src/main/java/de/rub/nds/modifiablevariable/util/ComparableByteArray.java index 018daa1e..9a49a717 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/ComparableByteArray.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/ComparableByteArray.java @@ -9,23 +9,64 @@ import java.util.Arrays; +/** + * A wrapper for byte arrays that provides proper content-based equality and hash code. + * + *

Java arrays are reference types that do not override {@link Object#equals(Object)} or {@link + * Object#hashCode()}, making them unsuitable for use as keys in hash-based collections or for + * content-based equality comparisons. This class wraps a byte array and provides implementations of + * {@code equals()} and {@code hashCode()} that compare and hash based on the content of the array, + * not its reference. + * + *

This class is particularly useful in: + * + *

+ */ public class ComparableByteArray { + /** The wrapped byte array */ private byte[] array; + /** + * Creates a new comparable wrapper for the given byte array. + * + * @param array The byte array to wrap + */ public ComparableByteArray(byte[] array) { super(); this.array = array; } + /** + * Gets the wrapped byte array. + * + * @return The wrapped byte array + */ public byte[] getArray() { return array; } + /** + * Sets the wrapped byte array. + * + * @param array The new byte array to wrap + */ public void setArray(byte[] array) { this.array = array; } + /** + * Computes a hash code for this object based on the content of the wrapped array. + * + *

This implementation uses {@link Arrays#hashCode(byte[])} to ensure that arrays with the + * same content produce the same hash code. + * + * @return A hash code value based on the content of the wrapped array + */ @Override public int hashCode() { int hash = 7; @@ -33,6 +74,16 @@ public int hashCode() { return hash; } + /** + * Compares this object with another for equality based on array content. + * + *

Two ComparableByteArray objects are considered equal if their wrapped arrays contain the + * same sequence of bytes. This implementation uses {@link Arrays#equals(byte[], byte[])} for + * the comparison. + * + * @param obj The object to compare with + * @return {@code true} if the objects are equal based on array content, {@code false} otherwise + */ @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/IllegalStringAdapter.java b/src/main/java/de/rub/nds/modifiablevariable/util/IllegalStringAdapter.java index a3f33fcf..779c1fb6 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/IllegalStringAdapter.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/IllegalStringAdapter.java @@ -10,13 +10,72 @@ import jakarta.xml.bind.annotation.adapters.XmlAdapter; import org.apache.commons.text.StringEscapeUtils; +/** + * XML adapter for handling strings that may contain illegal or escape characters. + * + *

This adapter provides a mechanism to safely include strings containing special characters, + * control characters, or characters that would be illegal in XML in JAXB-serialized XML documents. + * It works by escaping such characters using Java string escape sequences when writing to XML, and + * unescaping them when reading from XML. + * + *

The adapter uses Apache Commons Text's {@link StringEscapeUtils} to perform the escaping and + * unescaping. This handles escaping of common special characters like: + * + *

+ * + *

Usage example: + * + *

{@code
+ * public class MyClass {
+ *     @XmlElement
+ *     @XmlJavaTypeAdapter(IllegalStringAdapter.class)
+ *     private String data = "Line 1\nLine 2"; // Contains a newline that needs escaping
+ * }
+ * }
+ * + *

With this adapter, the string will be properly escaped in XML, allowing for safe serialization + * and deserialization of strings containing special characters. + */ public class IllegalStringAdapter extends XmlAdapter { + /** + * Creates a new adapter for handling strings with illegal or escape characters. + * + *

This default constructor initializes the adapter with no special configuration, as all + * functionality is provided by the marshal and unmarshal methods. + */ + public IllegalStringAdapter() { + super(); + } + + /** + * Converts an escaped string representation from XML back to its original form. + * + *

This method unescapes Java escape sequences to restore the original string with its + * special characters. + * + * @param value The escaped string to convert + * @return The unescaped string + */ @Override public String unmarshal(String value) { return StringEscapeUtils.unescapeJava(value); } + /** + * Converts a string to an escaped representation for XML. + * + *

This method escapes special characters using Java escape sequences to ensure they can be + * safely included in XML. + * + * @param value The string to escape + * @return The escaped string + */ @Override public String marshal(String value) { return StringEscapeUtils.escapeJava(value); diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/Modifiable.java b/src/main/java/de/rub/nds/modifiablevariable/util/Modifiable.java index 4fbfb764..6d9b1ae9 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/Modifiable.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/Modifiable.java @@ -58,13 +58,47 @@ import de.rub.nds.modifiablevariable.string.StringPrependValueModification; import java.math.BigInteger; -@SuppressWarnings("unused") +/** + * A factory class providing convenient methods for creating modifiable variables with various + * modifications. + * + *

This utility class serves as a central access point for creating variables that can be + * dynamically modified at runtime. It provides a fluent API for common modification operations + * across all supported variable types. + * + *

Each factory method creates a new modifiable variable with the specified modification + * pre-configured. The methods are organized by operation type (add, xor, explicit, etc.) and + * overloaded to support different data types. + * + *

Usage example: + * + *

{@code
+ * // Create a modifiable integer that will add 42 to its input
+ * ModifiableInteger addMod = Modifiable.add(42);
+ * addMod.setOriginalValue(10);
+ * Integer result = addMod.getValue(); // Returns 52
+ *
+ * // Create a modifiable byte array that explicitly sets a value
+ * ModifiableByteArray explicitMod = Modifiable.explicit(new byte[]{1, 2, 3});
+ * explicitMod.setOriginalValue(new byte[]{4, 5, 6});
+ * byte[] result = explicitMod.getValue(); // Returns {1, 2, 3} regardless of original value
+ * }
+ * + *

This class is not meant to be instantiated as it only provides static factory methods. + */ public final class Modifiable { + /** Private constructor to prevent instantiation of this utility class. */ private Modifiable() { super(); } + /** + * Creates a new ModifiableByteArray with the specified modification applied. + * + * @param modification The modification to apply to the byte array + * @return A new ModifiableByteArray with the specified modification + */ private static ModifiableByteArray getModifiableByteArrayWithModification( VariableModification modification) { ModifiableByteArray modifiableByteArray = new ModifiableByteArray(); @@ -72,6 +106,12 @@ private static ModifiableByteArray getModifiableByteArrayWithModification( return modifiableByteArray; } + /** + * Creates a new ModifiableByte with the specified modification applied. + * + * @param modification The modification to apply to the byte + * @return A new ModifiableByte with the specified modification + */ private static ModifiableByte getModifiableByteWithModification( VariableModification modification) { ModifiableByte modifiableByte = new ModifiableByte(); @@ -79,6 +119,12 @@ private static ModifiableByte getModifiableByteWithModification( return modifiableByte; } + /** + * Creates a new ModifiableInteger with the specified modification applied. + * + * @param modification The modification to apply to the integer + * @return A new ModifiableInteger with the specified modification + */ private static ModifiableInteger getModifiableIntegerWithModification( VariableModification modification) { ModifiableInteger modifiableInteger = new ModifiableInteger(); @@ -86,6 +132,12 @@ private static ModifiableInteger getModifiableIntegerWithModification( return modifiableInteger; } + /** + * Creates a new ModifiableBigInteger with the specified modification applied. + * + * @param modification The modification to apply to the BigInteger + * @return A new ModifiableBigInteger with the specified modification + */ private static ModifiableBigInteger getModifiableBigIntegerWithModification( VariableModification modification) { ModifiableBigInteger modifiableBigInteger = new ModifiableBigInteger(); @@ -93,6 +145,12 @@ private static ModifiableBigInteger getModifiableBigIntegerWithModification( return modifiableBigInteger; } + /** + * Creates a new ModifiableLong with the specified modification applied. + * + * @param modification The modification to apply to the long + * @return A new ModifiableLong with the specified modification + */ private static ModifiableLong getModifiableLongWithModification( VariableModification modification) { ModifiableLong modifiableLong = new ModifiableLong(); @@ -100,6 +158,12 @@ private static ModifiableLong getModifiableLongWithModification( return modifiableLong; } + /** + * Creates a new ModifiableBoolean with the specified modification applied. + * + * @param modification The modification to apply to the boolean + * @return A new ModifiableBoolean with the specified modification + */ private static ModifiableBoolean getModifiableBooleanWithModification( VariableModification modification) { ModifiableBoolean modifiableBoolean = new ModifiableBoolean(); @@ -107,6 +171,12 @@ private static ModifiableBoolean getModifiableBooleanWithModification( return modifiableBoolean; } + /** + * Creates a new ModifiableString with the specified modification applied. + * + * @param modification The modification to apply to the string + * @return A new ModifiableString with the specified modification + */ private static ModifiableString getModifiableStringWithModification( VariableModification modification) { ModifiableString modifiableString = new ModifiableString(); @@ -114,178 +184,512 @@ private static ModifiableString getModifiableStringWithModification( return modifiableString; } + /** + * Creates a ModifiableByteArray that prepends the specified value to the original byte array. + * + * @param perpendValue The byte array to prepend to the original value + * @return A ModifiableByteArray that prepends the specified value + * @see de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray + * @see de.rub.nds.modifiablevariable.bytearray.ByteArrayPrependValueModification + */ public static ModifiableByteArray prepend(byte[] perpendValue) { return getModifiableByteArrayWithModification( new ByteArrayPrependValueModification(perpendValue)); } + /** + * Creates a ModifiableString that prepends the specified value to the original string. + * + * @param perpendValue The string to prepend to the original value + * @return A ModifiableString that prepends the specified value + * @see de.rub.nds.modifiablevariable.string.ModifiableString + * @see de.rub.nds.modifiablevariable.string.StringPrependValueModification + */ public static ModifiableString prepend(String perpendValue) { return getModifiableStringWithModification( new StringPrependValueModification(perpendValue)); } + /** + * Creates a ModifiableByteArray that appends the specified value to the original byte array. + * + * @param appendValue The byte array to append to the original value + * @return A ModifiableByteArray that appends the specified value + * @see de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray + * @see de.rub.nds.modifiablevariable.bytearray.ByteArrayAppendValueModification + */ public static ModifiableByteArray append(byte[] appendValue) { return getModifiableByteArrayWithModification( new ByteArrayAppendValueModification(appendValue)); } + /** + * Creates a ModifiableString that appends the specified value to the original string. + * + * @param appendValue The string to append to the original value + * @return A ModifiableString that appends the specified value + * @see de.rub.nds.modifiablevariable.string.ModifiableString + * @see de.rub.nds.modifiablevariable.string.StringAppendValueModification + */ public static ModifiableString append(String appendValue) { return getModifiableStringWithModification(new StringAppendValueModification(appendValue)); } + /** + * Creates a ModifiableByteArray that replaces the original value with the specified explicit + * value. + * + * @param explicitValue The byte array to use as the explicit value + * @return A ModifiableByteArray that returns the explicit value + * @see de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray + * @see de.rub.nds.modifiablevariable.bytearray.ByteArrayExplicitValueModification + */ public static ModifiableByteArray explicit(byte[] explicitValue) { return getModifiableByteArrayWithModification( new ByteArrayExplicitValueModification(explicitValue)); } + /** + * Creates a ModifiableByte that replaces the original value with the specified explicit value. + * + * @param explicitValue The byte to use as the explicit value + * @return A ModifiableByte that returns the explicit value + * @see de.rub.nds.modifiablevariable.singlebyte.ModifiableByte + * @see de.rub.nds.modifiablevariable.singlebyte.ByteExplicitValueModification + */ public static ModifiableByte explicit(Byte explicitValue) { return getModifiableByteWithModification(new ByteExplicitValueModification(explicitValue)); } + /** + * Creates a ModifiableInteger that replaces the original value with the specified explicit + * value. + * + * @param explicitValue The integer to use as the explicit value + * @return A ModifiableInteger that returns the explicit value + * @see de.rub.nds.modifiablevariable.integer.ModifiableInteger + * @see de.rub.nds.modifiablevariable.integer.IntegerExplicitValueModification + */ public static ModifiableInteger explicit(Integer explicitValue) { return getModifiableIntegerWithModification( new IntegerExplicitValueModification(explicitValue)); } + /** + * Creates a ModifiableBigInteger that replaces the original value with the specified explicit + * value. + * + * @param explicitValue The BigInteger to use as the explicit value + * @return A ModifiableBigInteger that returns the explicit value + * @see de.rub.nds.modifiablevariable.biginteger.ModifiableBigInteger + * @see de.rub.nds.modifiablevariable.biginteger.BigIntegerExplicitValueModification + */ public static ModifiableBigInteger explicit(BigInteger explicitValue) { return getModifiableBigIntegerWithModification( new BigIntegerExplicitValueModification(explicitValue)); } + /** + * Creates a ModifiableLong that replaces the original value with the specified explicit value. + * + * @param explicitValue The long to use as the explicit value + * @return A ModifiableLong that returns the explicit value + * @see de.rub.nds.modifiablevariable.longint.ModifiableLong + * @see de.rub.nds.modifiablevariable.longint.LongExplicitValueModification + */ public static ModifiableLong explicit(Long explicitValue) { return getModifiableLongWithModification(new LongExplicitValueModification(explicitValue)); } + /** + * Creates a ModifiableBoolean that replaces the original value with the specified explicit + * value. + * + * @param explicitValue The boolean to use as the explicit value + * @return A ModifiableBoolean that returns the explicit value + * @see de.rub.nds.modifiablevariable.bool.ModifiableBoolean + * @see de.rub.nds.modifiablevariable.bool.BooleanExplicitValueModification + */ public static ModifiableBoolean explicit(Boolean explicitValue) { return getModifiableBooleanWithModification( new BooleanExplicitValueModification(explicitValue)); } + /** + * Creates a ModifiableString that replaces the original value with the specified explicit + * value. + * + * @param explicitValue The string to use as the explicit value + * @return A ModifiableString that returns the explicit value + * @see de.rub.nds.modifiablevariable.string.ModifiableString + * @see de.rub.nds.modifiablevariable.string.StringExplicitValueModification + */ public static ModifiableString explicit(String explicitValue) { return getModifiableStringWithModification( new StringExplicitValueModification(explicitValue)); } + /** + * Creates a ModifiableByteArray that inserts the specified value at the given position. + * + * @param insertValue The byte array to insert + * @param position The position at which to insert the value (0-indexed) + * @return A ModifiableByteArray that inserts the specified value at the given position + * @see de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray + * @see de.rub.nds.modifiablevariable.bytearray.ByteArrayInsertValueModification + */ public static ModifiableByteArray insert(byte[] insertValue, int position) { return getModifiableByteArrayWithModification( new ByteArrayInsertValueModification(insertValue, position)); } + /** + * Creates a ModifiableString that inserts the specified value at the given position. + * + * @param insertValue The string to insert + * @param position The position at which to insert the value (0-indexed) + * @return A ModifiableString that inserts the specified value at the given position + * @see de.rub.nds.modifiablevariable.string.ModifiableString + * @see de.rub.nds.modifiablevariable.string.StringInsertValueModification + */ public static ModifiableString insert(String insertValue, int position) { return getModifiableStringWithModification( new StringInsertValueModification(insertValue, position)); } + /** + * Creates a ModifiableByteArray that applies an XOR operation with the specified value. + * + * @param xor The byte array to use in the XOR operation + * @param position The position at which to start the XOR operation + * @return A ModifiableByteArray that applies the XOR operation + * @see de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray + * @see de.rub.nds.modifiablevariable.bytearray.ByteArrayXorModification + */ public static ModifiableByteArray xor(byte[] xor, int position) { return getModifiableByteArrayWithModification(new ByteArrayXorModification(xor, position)); } + /** + * Creates a ModifiableByte that applies an XOR operation with the specified value. + * + * @param xor The byte to use in the XOR operation + * @return A ModifiableByte that applies the XOR operation + * @see de.rub.nds.modifiablevariable.singlebyte.ModifiableByte + * @see de.rub.nds.modifiablevariable.singlebyte.ByteXorModification + */ public static ModifiableByte xor(Byte xor) { return getModifiableByteWithModification(new ByteXorModification(xor)); } + /** + * Creates a ModifiableInteger that applies an XOR operation with the specified value. + * + * @param xor The integer to use in the XOR operation + * @return A ModifiableInteger that applies the XOR operation + * @see de.rub.nds.modifiablevariable.integer.ModifiableInteger + * @see de.rub.nds.modifiablevariable.integer.IntegerXorModification + */ public static ModifiableInteger xor(Integer xor) { return getModifiableIntegerWithModification(new IntegerXorModification(xor)); } + /** + * Creates a ModifiableBigInteger that applies an XOR operation with the specified value. + * + * @param xor The BigInteger to use in the XOR operation + * @return A ModifiableBigInteger that applies the XOR operation + * @see de.rub.nds.modifiablevariable.biginteger.ModifiableBigInteger + * @see de.rub.nds.modifiablevariable.biginteger.BigIntegerXorModification + */ public static ModifiableBigInteger xor(BigInteger xor) { return getModifiableBigIntegerWithModification(new BigIntegerXorModification(xor)); } + /** + * Creates a ModifiableLong that applies an XOR operation with the specified value. + * + * @param xor The long to use in the XOR operation + * @return A ModifiableLong that applies the XOR operation + * @see de.rub.nds.modifiablevariable.longint.ModifiableLong + * @see de.rub.nds.modifiablevariable.longint.LongXorModification + */ public static ModifiableLong xor(Long xor) { return getModifiableLongWithModification(new LongXorModification(xor)); } + /** + * Creates a ModifiableInteger that swaps the byte order (endianness) of the original integer. + * + * @return A ModifiableInteger that swaps the byte order of the original value + * @see de.rub.nds.modifiablevariable.integer.ModifiableInteger + * @see de.rub.nds.modifiablevariable.integer.IntegerSwapEndianModification + */ public static ModifiableInteger swapEndianIntger() { return getModifiableIntegerWithModification(new IntegerSwapEndianModification()); } + /** + * Creates a ModifiableLong that swaps the byte order (endianness) of the original long. + * + * @return A ModifiableLong that swaps the byte order of the original value + * @see de.rub.nds.modifiablevariable.longint.ModifiableLong + * @see de.rub.nds.modifiablevariable.longint.LongSwapEndianModification + */ public static ModifiableLong swapEndianLong() { return getModifiableLongWithModification(new LongSwapEndianModification()); } + /** + * Creates a ModifiableByte that adds the specified value to the original byte. + * + * @param summand The byte to add to the original value + * @return A ModifiableByte that adds the specified value + * @see de.rub.nds.modifiablevariable.singlebyte.ModifiableByte + * @see de.rub.nds.modifiablevariable.singlebyte.ByteAddModification + */ public static ModifiableByte add(Byte summand) { return getModifiableByteWithModification(new ByteAddModification(summand)); } + /** + * Creates a ModifiableInteger that adds the specified value to the original integer. + * + * @param summand The integer to add to the original value + * @return A ModifiableInteger that adds the specified value + * @see de.rub.nds.modifiablevariable.integer.ModifiableInteger + * @see de.rub.nds.modifiablevariable.integer.IntegerAddModification + */ public static ModifiableInteger add(Integer summand) { return getModifiableIntegerWithModification(new IntegerAddModification(summand)); } + /** + * Creates a ModifiableBigInteger that adds the specified value to the original BigInteger. + * + * @param summand The BigInteger to add to the original value + * @return A ModifiableBigInteger that adds the specified value + * @see de.rub.nds.modifiablevariable.biginteger.ModifiableBigInteger + * @see de.rub.nds.modifiablevariable.biginteger.BigIntegerAddModification + */ public static ModifiableBigInteger add(BigInteger summand) { return getModifiableBigIntegerWithModification(new BigIntegerAddModification(summand)); } + /** + * Creates a ModifiableLong that adds the specified value to the original long. + * + * @param summand The long to add to the original value + * @return A ModifiableLong that adds the specified value + * @see de.rub.nds.modifiablevariable.longint.ModifiableLong + * @see de.rub.nds.modifiablevariable.longint.LongAddModification + */ public static ModifiableLong add(Long summand) { return getModifiableLongWithModification(new LongAddModification(summand)); } + /** + * Creates a ModifiableByte that subtracts the specified value from the original byte. + * + * @param subtrahend The byte to subtract from the original value + * @return A ModifiableByte that subtracts the specified value + * @see de.rub.nds.modifiablevariable.singlebyte.ModifiableByte + * @see de.rub.nds.modifiablevariable.singlebyte.ByteSubtractModification + */ public static ModifiableByte sub(Byte subtrahend) { return getModifiableByteWithModification(new ByteSubtractModification(subtrahend)); } + /** + * Creates a ModifiableInteger that subtracts the specified value from the original integer. + * + * @param subtrahend The integer to subtract from the original value + * @return A ModifiableInteger that subtracts the specified value + * @see de.rub.nds.modifiablevariable.integer.ModifiableInteger + * @see de.rub.nds.modifiablevariable.integer.IntegerSubtractModification + */ public static ModifiableInteger sub(Integer subtrahend) { return getModifiableIntegerWithModification(new IntegerSubtractModification(subtrahend)); } + /** + * Creates a ModifiableBigInteger that subtracts the specified value from the original + * BigInteger. + * + * @param subtrahend The BigInteger to subtract from the original value + * @return A ModifiableBigInteger that subtracts the specified value + * @see de.rub.nds.modifiablevariable.biginteger.ModifiableBigInteger + * @see de.rub.nds.modifiablevariable.biginteger.BigIntegerSubtractModification + */ public static ModifiableBigInteger sub(BigInteger subtrahend) { return getModifiableBigIntegerWithModification( new BigIntegerSubtractModification(subtrahend)); } + /** + * Creates a ModifiableLong that subtracts the specified value from the original long. + * + * @param subtrahend The long to subtract from the original value + * @return A ModifiableLong that subtracts the specified value + * @see de.rub.nds.modifiablevariable.longint.ModifiableLong + * @see de.rub.nds.modifiablevariable.longint.LongSubtractModification + */ public static ModifiableLong sub(Long subtrahend) { return getModifiableLongWithModification(new LongSubtractModification(subtrahend)); } + /** + * Creates a ModifiableByteArray that deletes a portion of the original byte array. + * + * @param startPosition The position from which to start deleting (0-indexed) + * @param count The number of bytes to delete + * @return A ModifiableByteArray that deletes the specified portion + * @see de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray + * @see de.rub.nds.modifiablevariable.bytearray.ByteArrayDeleteModification + */ public static ModifiableByteArray delete(int startPosition, int count) { return getModifiableByteArrayWithModification( new ByteArrayDeleteModification(startPosition, count)); } - public static ModifiableByteArray shuffle(byte[] shuffle) { + /** + * Creates a ModifiableByteArray that shuffles the original byte array. + * + * @param shuffle The byte array defining the shuffle pattern + * @return A ModifiableByteArray that shuffles according to the specified pattern + * @see de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray + * @see de.rub.nds.modifiablevariable.bytearray.ByteArrayShuffleModification + */ + public static ModifiableByteArray shuffle(int[] shuffle) { return getModifiableByteArrayWithModification(new ByteArrayShuffleModification(shuffle)); } + /** + * Creates a ModifiableByteArray that duplicates the original byte array. + * + * @return A ModifiableByteArray that duplicates the original value + * @see de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray + * @see de.rub.nds.modifiablevariable.bytearray.ByteArrayDuplicateModification + */ public static ModifiableByteArray duplicate() { return getModifiableByteArrayWithModification(new ByteArrayDuplicateModification()); } + /** + * Creates a ModifiableBoolean that toggles the original boolean value. + * + * @return A ModifiableBoolean that toggles the original value + * @see de.rub.nds.modifiablevariable.bool.ModifiableBoolean + * @see de.rub.nds.modifiablevariable.bool.BooleanToggleModification + */ public static ModifiableBoolean toggle() { return getModifiableBooleanWithModification(new BooleanToggleModification()); } + /** + * Creates a ModifiableBigInteger that shifts the original BigInteger to the left. + * + * @param shift The number of bits to shift left + * @return A ModifiableBigInteger that shifts the original value left + * @see de.rub.nds.modifiablevariable.biginteger.ModifiableBigInteger + * @see de.rub.nds.modifiablevariable.biginteger.BigIntegerShiftLeftModification + */ public static ModifiableBigInteger shiftLeftBigInteger(Integer shift) { return getModifiableBigIntegerWithModification(new BigIntegerShiftLeftModification(shift)); } + /** + * Creates a ModifiableInteger that shifts the original integer to the left. + * + * @param shift The number of bits to shift left + * @return A ModifiableInteger that shifts the original value left + * @see de.rub.nds.modifiablevariable.integer.ModifiableInteger + * @see de.rub.nds.modifiablevariable.integer.IntegerShiftLeftModification + */ public static ModifiableInteger shiftLeft(Integer shift) { return getModifiableIntegerWithModification(new IntegerShiftLeftModification(shift)); } + /** + * Creates a ModifiableLong that shifts the original long to the left. + * + * @param shift The number of bits to shift left + * @return A ModifiableLong that shifts the original value left + * @see de.rub.nds.modifiablevariable.longint.ModifiableLong + * @see de.rub.nds.modifiablevariable.longint.LongShiftLeftModification + */ public static ModifiableLong shiftLeftLong(Integer shift) { return getModifiableLongWithModification(new LongShiftLeftModification(shift)); } + /** + * Creates a ModifiableBigInteger that shifts the original BigInteger to the right. + * + * @param shift The number of bits to shift right + * @return A ModifiableBigInteger that shifts the original value right + * @see de.rub.nds.modifiablevariable.biginteger.ModifiableBigInteger + * @see de.rub.nds.modifiablevariable.biginteger.BigIntegerShiftRightModification + */ public static ModifiableBigInteger shiftRightBigInteger(Integer shift) { return getModifiableBigIntegerWithModification(new BigIntegerShiftRightModification(shift)); } + /** + * Creates a ModifiableInteger that shifts the original integer to the right. + * + * @param shift The number of bits to shift right + * @return A ModifiableInteger that shifts the original value right + * @see de.rub.nds.modifiablevariable.integer.ModifiableInteger + * @see de.rub.nds.modifiablevariable.integer.IntegerShiftRightModification + */ public static ModifiableInteger shiftRight(Integer shift) { return getModifiableIntegerWithModification(new IntegerShiftRightModification(shift)); } + /** + * Creates a ModifiableLong that shifts the original long to the right. + * + * @param shift The number of bits to shift right + * @return A ModifiableLong that shifts the original value right + * @see de.rub.nds.modifiablevariable.longint.ModifiableLong + * @see de.rub.nds.modifiablevariable.longint.LongShiftRightModification + */ public static ModifiableLong shiftRightLong(Integer shift) { return getModifiableLongWithModification(new LongShiftRightModification(shift)); } + /** + * Creates a ModifiableBigInteger that multiplies the original BigInteger. + * + * @param factor The BigInteger to multiply with the original value + * @return A ModifiableBigInteger that multiplies the original value + * @see de.rub.nds.modifiablevariable.biginteger.ModifiableBigInteger + * @see de.rub.nds.modifiablevariable.biginteger.BigIntegerMultiplyModification + */ public static ModifiableBigInteger multiplyBigInteger(BigInteger factor) { return getModifiableBigIntegerWithModification(new BigIntegerMultiplyModification(factor)); } + /** + * Creates a ModifiableInteger that multiplies the original integer. + * + * @param factor The integer to multiply with the original value + * @return A ModifiableInteger that multiplies the original value + * @see de.rub.nds.modifiablevariable.integer.ModifiableInteger + * @see de.rub.nds.modifiablevariable.integer.IntegerMultiplyModification + */ public static ModifiableInteger multiply(Integer factor) { return getModifiableIntegerWithModification(new IntegerMultiplyModification(factor)); } + /** + * Creates a ModifiableLong that multiplies the original long. + * + * @param factor The long to multiply with the original value + * @return A ModifiableLong that multiplies the original value + * @see de.rub.nds.modifiablevariable.longint.ModifiableLong + * @see de.rub.nds.modifiablevariable.longint.LongMultiplyModification + */ public static ModifiableLong multiply(Long factor) { return getModifiableLongWithModification(new LongMultiplyModification(factor)); } diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/ModifiableVariableAnalyzer.java b/src/main/java/de/rub/nds/modifiablevariable/util/ModifiableVariableAnalyzer.java index 83968b83..326c129f 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/ModifiableVariableAnalyzer.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/ModifiableVariableAnalyzer.java @@ -15,41 +15,65 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +/** + * Utility class for analyzing and discovering modifiable variables in arbitrary objects. + * + *

This class provides static methods to find and inspect modifiable variables within objects, + * including the ability to recursively scan complex object hierarchies. It uses reflection to + * locate fields that are either of type ModifiableVariable or are annotated with {@link + * HoldsModifiableVariable}. + * + *

This class cannot be instantiated and all methods are static. + */ public final class ModifiableVariableAnalyzer { - private static final Logger LOGGER = LogManager.getLogger(ModifiableVariableAnalyzer.class); + /** Logger for this class */ + private static final Logger LOGGER = LogManager.getLogger(); + /** Private constructor to prevent instantiation of this utility class. */ private ModifiableVariableAnalyzer() { super(); } /** - * Lists all the modifiable variables declared in the given class + * Finds all fields of type ModifiableVariable in the given object. + * + *

This method uses reflection to discover all fields in the object's class hierarchy that + * extend ModifiableVariable. It does not include fields from nested objects. * - * @param object Analyzed object - * @return A list of modifiable variable fields for the given object + * @param object The object to analyze + * @return A list of Field objects representing all ModifiableVariable fields in the object */ public static List getAllModifiableVariableFields(Object object) { return ReflectionHelper.getFieldsUpTo(object.getClass(), null, ModifiableVariable.class); } /** - * Returns a random field representing a modifiable variable in the given class + * Selects a random ModifiableVariable field from the given object. * - * @param object Analyzed object - * @return A random field representing a modifiable variable + *

This method is useful for randomized testing where a random field needs to be selected for + * modification. It uses the {@link RandomHelper} to ensure deterministic behavior in tests. + * + * @param object The object from which to select a random ModifiableVariable field + * @return A randomly selected Field object representing a ModifiableVariable. Returns null if + * the object does not contain any ModifiableVariable fields. */ public static Field getRandomModifiableVariableField(Object object) { List fields = getAllModifiableVariableFields(object); + if (fields.isEmpty()) { + return null; + } int randomField = RandomHelper.getRandom().nextInt(fields.size()); return fields.get(randomField); } /** - * Returns true if the given object contains a modifiable variable + * Determines whether an object contains any ModifiableVariable fields. * - * @param object Analyzed object - * @return True if the object contains a modifiable variable. + *

This method checks if the object has at least one field that extends ModifiableVariable. + * + * @param object The object to check + * @return true if the object contains at least one ModifiableVariable field, false otherwise */ public static boolean isModifiableVariableHolder(Object object) { List fields = getAllModifiableVariableFields(object); @@ -57,12 +81,18 @@ public static boolean isModifiableVariableHolder(Object object) { } /** - * Returns a list of all ModifiableVariableFields (object-field representations) for a given - * object. + * Recursively finds all ModifiableVariable fields in an object and its nested objects. + * + *

This method creates a flat list of ModifiableVariableField objects, which pair the + * containing object with its ModifiableVariable field. This representation makes it easier to + * manipulate the fields directly. * - * @param object Analyzed object - * @return A list of objects with their modifiable variable fields (only objects with modifiable - * variables are selected) + *

The method traverses the entire object graph, following fields annotated with {@link + * HoldsModifiableVariable}, and including collection and array elements. + * + * @param object The root object to analyze + * @return A list of ModifiableVariableField objects representing all ModifiableVariable fields + * in the object hierarchy */ public static List getAllModifiableVariableFieldsRecursively( Object object) { @@ -78,11 +108,23 @@ public static List getAllModifiableVariableFieldsRecurs } /** - * Returns a list of all the modifiable variable holders in the object, including this instance. + * Recursively finds all objects that contain ModifiableVariable fields. + * + *

This method traverses the object graph, starting from the given object, and identifies all + * objects that contain ModifiableVariable fields. For each such object, it creates a + * ModifiableVariableListHolder that pairs the object with its ModifiableVariable fields. + * + *

The traversal follows these rules: + * + *

* - * @param object Analyzed object - * @return A list of objects with their modifiable variable fields (only objects with modifiable - * variables are selected) + * @param object The root object to analyze + * @return A list of ModifiableVariableListHolder objects, each containing an object and its + * ModifiableVariable fields */ public static List getAllModifiableVariableHoldersRecursively( Object object) { @@ -112,7 +154,7 @@ public static List getAllModifiableVariableHolders } } } catch (IllegalAccessException | IllegalArgumentException ex) { - LOGGER.debug( + LOGGER.warn( "Accessing field {} of type {} not possible: {}", field.getName(), field.getType(), @@ -123,9 +165,14 @@ public static List getAllModifiableVariableHolders } /** - * @param list Analyzed list - * @return A list of objects with their modifiable variable fields (only objects with modifiable - * variables are selected) + * Finds all ModifiableVariable holders within a list of objects. + * + *

This helper method recursively processes each non-null element in the list to find objects + * that contain ModifiableVariable fields. + * + * @param list The list of objects to analyze + * @return A list of ModifiableVariableListHolder objects, each containing an object and its + * ModifiableVariable fields */ public static List getAllModifiableVariableHoldersFromList( List list) { @@ -141,9 +188,14 @@ public static List getAllModifiableVariableHolders } /** - * @param array Analyzed array of objects - * @return A list of objects with their modifiable variable fields (only objects with modifiable - * variables are selected) + * Finds all ModifiableVariable holders within an array of objects. + * + *

This helper method recursively processes each element in the array to find objects that + * contain ModifiableVariable fields. + * + * @param array The array of objects to analyze + * @return A list of ModifiableVariableListHolder objects, each containing an object and its + * ModifiableVariable fields */ public static List getAllModifiableVariableHoldersFromArray( Object[] array) { diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/ModifiableVariableField.java b/src/main/java/de/rub/nds/modifiablevariable/util/ModifiableVariableField.java index 95e3dd4e..938269eb 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/ModifiableVariableField.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/ModifiableVariableField.java @@ -10,39 +10,81 @@ import de.rub.nds.modifiablevariable.ModifiableVariable; import java.lang.reflect.Field; -/** Represents an object with its modifiable variable field. */ +/** + * A wrapper class that pairs an object with one of its ModifiableVariable fields. + * + *

This class is used to represent the relationship between an object and a specific + * ModifiableVariable field within it. + * + *

The class provides methods to access both the containing object and the field, as well as a + * convenience method to directly access the ModifiableVariable instance. + */ public class ModifiableVariableField { + /** The object containing the ModifiableVariable field */ private Object object; + /** The Field object representing the ModifiableVariable */ private Field field; - public ModifiableVariableField() { - super(); - } - + /** + * Constructor that creates a ModifiableVariableField with the specified object and field. + * + * @param o The object containing the ModifiableVariable field + * @param field The Field object representing the ModifiableVariable + */ public ModifiableVariableField(Object o, Field field) { super(); object = o; this.field = field; } + /** + * Gets the object containing the ModifiableVariable field. + * + * @return The containing object + */ public Object getObject() { return object; } + /** + * Sets the object containing the ModifiableVariable field. + * + * @param object The new containing object + */ public void setObject(Object object) { this.object = object; } + /** + * Gets the Field object representing the ModifiableVariable. + * + * @return The Field object + */ public Field getField() { return field; } + /** + * Sets the Field object representing the ModifiableVariable. + * + * @param field The new Field object + */ public void setField(Field field) { this.field = field; } + /** + * Gets the actual ModifiableVariable instance from the object. + * + *

This method uses reflection to access the field in the object, making the field accessible + * if necessary. + * + * @return The ModifiableVariable instance + * @throws IllegalArgumentException If the field is not accessible or does not exist + * @throws IllegalAccessException If the field cannot be accessed + */ public ModifiableVariable getModifiableVariable() throws IllegalArgumentException, IllegalAccessException { field.setAccessible(true); diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/ModifiableVariableListHolder.java b/src/main/java/de/rub/nds/modifiablevariable/util/ModifiableVariableListHolder.java index 732eb483..8411beca 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/ModifiableVariableListHolder.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/ModifiableVariableListHolder.java @@ -11,37 +11,69 @@ import java.util.List; /** - * Represents a modifiable variable holder (an object containing at least one ModifiableVariable - * field), containing a list of its ModifiableVariable fields + * A holder class that pairs an object with a list of its ModifiableVariable fields. + * + *

This class is used to represent the relationship between an object and all of its + * ModifiableVariable fields. It's particularly useful when working with the results of + * reflection-based analysis, as it preserves the context needed to access and manipulate the + * fields. + * + *

Unlike {@link ModifiableVariableField}, which represents a single field in an object, this + * class represents all ModifiableVariable fields in an object, making it useful for operations that + * need to work with all modifiable fields in an object. */ public class ModifiableVariableListHolder { + /** The object containing the ModifiableVariable fields */ private Object object; + /** The list of Field objects representing the ModifiableVariables in the object */ private List fields; - public ModifiableVariableListHolder() { - super(); - } - + /** + * Constructor that creates a ModifiableVariableListHolder with the specified object and fields. + * + * @param o The object containing the ModifiableVariable fields + * @param fields The list of Field objects representing ModifiableVariables in the object + */ public ModifiableVariableListHolder(Object o, List fields) { super(); object = o; this.fields = fields; } + /** + * Gets the object containing the ModifiableVariable fields. + * + * @return The containing object + */ public Object getObject() { return object; } + /** + * Sets the object containing the ModifiableVariable fields. + * + * @param object The new containing object + */ public void setObject(Object object) { this.object = object; } + /** + * Gets the list of Field objects representing the ModifiableVariables in the object. + * + * @return The list of Field objects + */ public List getFields() { return fields; } + /** + * Sets the list of Field objects representing the ModifiableVariables in the object. + * + * @param fields The new list of Field objects + */ public void setFields(List fields) { this.fields = fields; } diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/RandomHelper.java b/src/main/java/de/rub/nds/modifiablevariable/util/RandomHelper.java index 78aaf980..21878a31 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/RandomHelper.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/RandomHelper.java @@ -9,10 +9,29 @@ import java.util.Random; +/** + * Utility class for obtaining and managing random number generators. + * + *

This class provides access to a singleton Random instance with a fixed seed (0), ensuring + * reproducible "random" behavior across test runs. It also provides access to specialized random + * number generators used for testing purposes. + * + *

The fixed seed ensures that any test using this generator will produce consistent results + * across multiple runs, which is essential for deterministic and reproducible testing. + */ public final class RandomHelper { + /** Singleton Random instance with a fixed seed */ private static Random random; + /** + * Gets the singleton Random instance with a fixed seed of 0. + * + *

The fixed seed ensures reproducible "random" behavior across test runs. If the Random + * instance hasn't been initialized yet, this method initializes it. + * + * @return A Random instance with a fixed seed of 0 + */ public static Random getRandom() { if (random == null) { random = new Random(0); @@ -20,14 +39,32 @@ public static Random getRandom() { return random; } + /** + * Gets a BadRandom instance that can be used for security testing. + * + *

BadRandom extends SecureRandom but uses the deterministic Random internally, making it + * predictable while still conforming to the SecureRandom API. This is useful for testing + * cryptographic protocols with controlled "randomness". + * + * @return A BadRandom instance that uses the singleton Random internally + */ public static BadRandom getBadSecureRandom() { - return new BadRandom(getRandom(), null); + return new BadRandom(getRandom()); } + /** + * Sets the singleton Random instance to a specific Random object. + * + *

This method allows for replacing the default Random instance with a custom one, which can + * be useful for testing with different seeds or alternative random number generators. + * + * @param random The Random instance to use as the singleton + */ public static void setRandom(Random random) { RandomHelper.random = random; } + /** Private constructor to prevent instantiation of this utility class. */ private RandomHelper() { super(); } diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/ReflectionHelper.java b/src/main/java/de/rub/nds/modifiablevariable/util/ReflectionHelper.java index 699fc39d..589b3f4c 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/ReflectionHelper.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/ReflectionHelper.java @@ -14,24 +14,50 @@ import java.util.LinkedList; import java.util.List; +/** + * Utility class providing reflection-based helper methods. + * + *

This class contains static methods for common reflection operations used throughout the + * modifiable variable framework, such as: + * + *

    + *
  • Finding fields in a class hierarchy + *
  • Filtering fields by type + *
  • Extracting values from fields + *
  • Working with generic type parameters + *
+ * + *

The methods in this class make it easier to work with reflection in a consistent way, reducing + * code duplication and centralizing reflection-related logic. + * + *

This class cannot be instantiated and all methods are static. + */ public final class ReflectionHelper { + /** Private constructor to prevent instantiation of this utility class. */ private ReflectionHelper() { super(); } /** - * Source: ... - * Retrieves all fields (all access levels) from all classes up the class hierarchy starting - * with {@code startClass} stopping with and not including {@code exclusiveParent}. Generally - * {@code Object.class} should be passed as {@code exclusiveParent}. + * Retrieves all fields from a class and its superclasses, optionally filtering by type. + * + *

This method traverses the class hierarchy starting from the specified class and collects + * all fields (regardless of access level) from each class in the hierarchy. The traversal stops + * when it reaches (but does not include) the specified exclusive parent class. * - * @param startClass the class whose fields should be retrieved - * @param exclusiveParent if not null, the base class of startClass whose fields should not be - * retrieved. - * @param filterClass class that should be used as a type filter - * @return list of fields included in the class and its ancestors + *

The fields can be optionally filtered by type, including only those that are assignable + * from the specified filter class. If the filter class is null, all fields are included. + * + *

Source: + * Stack Overflow: List all private fields of a Java object + * + * @param startClass The class from which to start collecting fields + * @param exclusiveParent The parent class at which to stop collecting fields (exclusive), + * typically Object.class + * @param filterClass The class to use as a type filter, or null to include all fields + * @return A list of Field objects from the class hierarchy, optionally filtered by type */ public static List getFieldsUpTo( Class startClass, Class exclusiveParent, Class filterClass) { @@ -52,7 +78,17 @@ public static List getFieldsUpTo( return currentClassFields; } - /** Takes a list of fields and returns only fields which are subclasses of the filterClass */ + /** + * Filters a list of fields to include only those whose type is assignable from the specified + * class. + * + *

This helper method is used to filter fields by their type. If the filter class is null, + * all fields are included in the result. + * + * @param fields The list of fields to filter + * @param filterClass The class to use as a filter, or null to include all fields + * @return A list containing only the fields whose type is assignable from the filter class + */ private static List filterFieldList(List fields, Class filterClass) { List filteredFields = new LinkedList<>(); @@ -65,6 +101,17 @@ private static List filterFieldList(List fields, Class filterCl return filteredFields; } + /** + * Extracts the values of the specified fields from an object. + * + *

This method uses reflection to access each field in the list and retrieve its value from + * the specified object. The fields are made accessible before retrieval. + * + * @param object The object from which to retrieve field values + * @param fields The list of fields whose values should be retrieved + * @return A list of values corresponding to the specified fields + * @throws IllegalAccessException If any field cannot be accessed + */ public static List getValuesFromFieldList(Object object, List fields) throws IllegalAccessException { List list = new LinkedList<>(); @@ -77,6 +124,19 @@ public static List getValuesFromFieldList(Object object, List fie return list; } + /** + * Retrieves the actual type arguments of an object's generic superclass. + * + *

This method is useful for working with generic types at runtime, allowing access to the + * specific type parameters used in a subclass of a generic class. + * + *

For example, if a class extends {@code ArrayList}, this method would return an + * array containing {@code String.class}. + * + * @param object The object whose generic type parameters should be retrieved + * @return An array of Type objects representing the actual type arguments, or null if the + * object's superclass is not a parameterized type + */ public static Type[] getParameterizedTypes(Object object) { Type superclassType = object.getClass().getGenericSuperclass(); diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/StringUtil.java b/src/main/java/de/rub/nds/modifiablevariable/util/StringUtil.java index a2e0102a..ba127343 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/StringUtil.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/StringUtil.java @@ -7,9 +7,19 @@ */ package de.rub.nds.modifiablevariable.util; +/** + * Utility class for string manipulation operations. + * + *

This class provides utility methods for handling strings in ways that are commonly needed + * across the ModifiableVariable framework, particularly for formatting and escaping strings for + * logging or display purposes. + * + *

The primary function is to handle non-printable or non-ASCII characters by converting them to + * their escape sequence equivalents, ensuring that all string content can be safely represented in + * logs, debug output, or other text-based contexts. + */ public final class StringUtil { - // Private constructor, because this is a utility class that is not meant - // to be instantiated. + /** Private constructor to prevent instantiation of this utility class. */ private StringUtil() { super(); } diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/SuppressingBooleanAdapter.java b/src/main/java/de/rub/nds/modifiablevariable/util/SuppressingBooleanAdapter.java index f16a0de9..5ad63e5e 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/SuppressingBooleanAdapter.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/SuppressingBooleanAdapter.java @@ -10,10 +10,57 @@ import jakarta.xml.bind.annotation.adapters.XmlAdapter; import java.util.Objects; +/** + * Abstract base adapter for boolean values that suppresses specific boolean values in XML. + * + *

This adapter provides a mechanism to omit specific boolean values (true or false) from the + * serialized XML, making the XML more concise by not including elements with default values. The + * specific value to suppress is determined by concrete subclasses. + * + *

When unmarshaling (reading XML), if the element is missing or null, the adapter returns the + * value that was suppressed during marshaling. This ensures that even if a value is not present in + * XML, the correct default value is used. + * + *

When marshaling (writing XML), if the boolean value matches the value to suppress, the adapter + * returns null, which causes JAXB to omit the element from the XML output entirely. + * + *

This pattern is useful for reducing XML verbosity by omitting default values. For example, if + * a field defaults to true, using {@link SuppressingTrueBooleanAdapter} will only include the field + * in XML if its value is false. + */ public abstract class SuppressingBooleanAdapter extends XmlAdapter { + /** + * Creates a new SuppressingBooleanAdapter. + * + *

This constructor initializes a base adapter instance. Concrete subclasses must implement + * the {@link #getValueToSuppress()} method to specify which boolean value should be suppressed + * in the XML representation. + */ + protected SuppressingBooleanAdapter() { + super(); + } + + /** + * Returns the boolean value that should be suppressed in the XML representation. + * + *

This method must be implemented by concrete subclasses to specify which value (true or + * false) should be omitted from the XML output. + * + * @return The boolean value to suppress in XML + */ public abstract Boolean getValueToSuppress(); + /** + * Converts a string representation to a Boolean value. + * + *

If the input is null (meaning the element was missing from the XML), this method returns + * the value that was suppressed during marshaling. Otherwise, it parses the string as a boolean + * value. + * + * @param v The string representation to convert + * @return The corresponding Boolean value, or the suppressed value if v is null + */ @Override public Boolean unmarshal(String v) { if (v == null) { @@ -23,6 +70,16 @@ public Boolean unmarshal(String v) { } } + /** + * Converts a Boolean value to its string representation for XML. + * + *

If the input value matches the value to suppress (or is null), this method returns null, + * which causes JAXB to omit the element from the XML output entirely. Otherwise, it returns the + * string representation of the boolean value. + * + * @param v The Boolean value to convert + * @return The string representation, or null if the value should be suppressed + */ @Override public String marshal(Boolean v) { if (Objects.equals(v, getValueToSuppress()) || v == null) { diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/SuppressingFalseBooleanAdapter.java b/src/main/java/de/rub/nds/modifiablevariable/util/SuppressingFalseBooleanAdapter.java index 174cd639..c3fb2768 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/SuppressingFalseBooleanAdapter.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/SuppressingFalseBooleanAdapter.java @@ -7,8 +7,53 @@ */ package de.rub.nds.modifiablevariable.util; +/** + * XML adapter that suppresses false boolean values in XML serialization. + * + *

This concrete implementation of {@link SuppressingBooleanAdapter} specifically suppresses the + * {@code false} value when marshaling to XML. This means that boolean fields with a value of {@code + * false} will be omitted from the XML output, making the XML more concise when {@code false} is the + * default or common value. + * + *

When unmarshaling XML, if an element is missing, this adapter will interpret that as a {@code + * false} value. + * + *

Usage example: + * + *

{@code
+ * public class MyClass {
+ *     @XmlElement
+ *     @XmlJavaTypeAdapter(SuppressingFalseBooleanAdapter.class)
+ *     private Boolean disabled = false; // This will not appear in XML unless true
+ * }
+ * }
+ * + *

With this adapter, in the example above, the "disabled" element will only appear in the XML if + * its value is {@code true}. If it's {@code false} (the default), the element will be omitted, + * resulting in more compact XML. + * + *

This adapter is complementary to {@link SuppressingTrueBooleanAdapter}, which suppresses + * {@code true} values instead. + */ public class SuppressingFalseBooleanAdapter extends SuppressingBooleanAdapter { + /** + * Creates a new adapter that suppresses false boolean values in XML. + * + *

This constructor initializes an adapter that will omit the false value from XML output, + * making false the default value when an element is missing. + */ + public SuppressingFalseBooleanAdapter() { + super(); + } + + /** + * Returns the boolean value to suppress in the XML representation. + * + *

This implementation suppresses the {@code false} value. + * + * @return {@code Boolean.FALSE} + */ @Override public Boolean getValueToSuppress() { return Boolean.FALSE; diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/SuppressingTrueBooleanAdapter.java b/src/main/java/de/rub/nds/modifiablevariable/util/SuppressingTrueBooleanAdapter.java index a8a2a66d..eb409988 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/SuppressingTrueBooleanAdapter.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/SuppressingTrueBooleanAdapter.java @@ -7,7 +7,50 @@ */ package de.rub.nds.modifiablevariable.util; +/** + * XML adapter that suppresses true boolean values in XML serialization. + * + *

This concrete implementation of {@link SuppressingBooleanAdapter} specifically suppresses the + * {@code true} value when marshaling to XML. This means that boolean fields with a value of {@code + * true} will be omitted from the XML output, making the XML more concise when {@code true} is the + * default or common value. + * + *

When unmarshaling XML, if an element is missing, this adapter will interpret that as a {@code + * true} value. + * + *

Usage example: + * + *

{@code
+ * public class MyClass {
+ *     @XmlElement
+ *     @XmlJavaTypeAdapter(SuppressingTrueBooleanAdapter.class)
+ *     private Boolean enabled = true; // This will not appear in XML unless false
+ * }
+ * }
+ * + *

With this adapter, in the example above, the "enabled" element will only appear in the XML if + * its value is {@code false}. If it's {@code true} (the default), the element will be omitted, + * resulting in more compact XML. + */ public class SuppressingTrueBooleanAdapter extends SuppressingBooleanAdapter { + + /** + * Creates a new adapter that suppresses true boolean values in XML. + * + *

This constructor initializes an adapter that will omit the true value from XML output, + * making true the default value when an element is missing. + */ + public SuppressingTrueBooleanAdapter() { + super(); + } + + /** + * Returns the boolean value to suppress in the XML representation. + * + *

This implementation suppresses the {@code true} value. + * + * @return {@code Boolean.TRUE} + */ @Override public Boolean getValueToSuppress() { return Boolean.TRUE; diff --git a/src/main/java/de/rub/nds/modifiablevariable/util/UnformattedByteArrayAdapter.java b/src/main/java/de/rub/nds/modifiablevariable/util/UnformattedByteArrayAdapter.java index 8cbcd9ae..8ef88a17 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/util/UnformattedByteArrayAdapter.java +++ b/src/main/java/de/rub/nds/modifiablevariable/util/UnformattedByteArrayAdapter.java @@ -9,15 +9,70 @@ import jakarta.xml.bind.annotation.adapters.XmlAdapter; +/** + * XML adapter for converting between byte arrays and their hexadecimal string representations. + * + *

This adapter is used with JAXB annotations to customize how byte arrays are serialized to and + * deserialized from XML. It provides a compact, unformatted hexadecimal representation without any + * whitespace, spaces, or line breaks. + * + *

When unmarshaling (reading XML), the adapter removes all whitespace from the input string + * before converting it to a byte array, making it more tolerant of different formatting styles in + * the source XML. + * + *

When marshaling (writing XML), the adapter produces a continuous hexadecimal string without + * any formatting characters, resulting in more compact XML. + * + *

Usage example: + * + *

{@code
+ * public class MyClass {
+ *     @XmlElement
+ *     @XmlJavaTypeAdapter(UnformattedByteArrayAdapter.class)
+ *     private byte[] data;
+ * }
+ * }
+ * + *

With this adapter, a byte array like {@code {0x01, 0x02, 0x03}} would be serialized as the + * string {@code "010203"} in XML rather than the default format. + */ public class UnformattedByteArrayAdapter extends XmlAdapter { + /** + * Creates a new adapter for converting between byte arrays and their hexadecimal + * representations. + * + *

This constructor initializes the adapter with no special configuration, as all + * functionality is provided by the marshal and unmarshal methods. + */ + public UnformattedByteArrayAdapter() { + super(); + } + + /** + * Converts a hexadecimal string representation to a byte array. + * + *

This method removes all whitespace from the input string before converting it to a byte + * array, making it tolerant of different formatting styles in the XML. + * + * @param value The hexadecimal string to convert + * @return The corresponding byte array + */ @Override public byte[] unmarshal(String value) { - value = value.replaceAll("\\s", ""); return ArrayConverter.hexStringToByteArray(value); } + /** + * Converts a byte array to its hexadecimal string representation. + * + *

This method produces a compact representation without any whitespace or formatting + * characters. + * + * @param value The byte array to convert + * @return The hexadecimal string representation + */ @Override public String marshal(byte[] value) { return ArrayConverter.bytesToHexString(value, false, false); diff --git a/src/test/java/de/rub/nds/modifiablevariable/FileConfigurationExceptionTest.java b/src/test/java/de/rub/nds/modifiablevariable/FileConfigurationExceptionTest.java deleted file mode 100644 index 932fd265..00000000 --- a/src/test/java/de/rub/nds/modifiablevariable/FileConfigurationExceptionTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * ModifiableVariable - A Variable Concept for Runtime Modifications - * - * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH - * - * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 - */ -package de.rub.nds.modifiablevariable; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertSame; - -import org.junit.jupiter.api.Test; - -public class FileConfigurationExceptionTest { - - @Test - public void testDefaultConstructor() { - FileConfigurationException exception = new FileConfigurationException(); - - assertNull(exception.getMessage()); - assertNull(exception.getCause()); - } - - @Test - public void testConstructorWithException() { - IllegalArgumentException cause = new IllegalArgumentException("Test cause"); - FileConfigurationException exception = new FileConfigurationException(cause); - - assertNotNull(exception.getMessage()); - assertSame(cause, exception.getCause()); - } - - @Test - public void testConstructorWithMessageAndException() { - String message = "Test error message"; - IllegalArgumentException cause = new IllegalArgumentException("Test cause"); - FileConfigurationException exception = new FileConfigurationException(message, cause); - - assertEquals(message, exception.getMessage()); - assertSame(cause, exception.getCause()); - } -} diff --git a/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModificationTest.java index 265e2c43..6470775b 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModificationTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModificationTest.java @@ -110,7 +110,7 @@ public void testEqualsAndHashCode() { @Test public void testGetterAndSetter() { - BigIntegerShiftLeftModification modification = new BigIntegerShiftLeftModification(); + BigIntegerShiftLeftModification modification = new BigIntegerShiftLeftModification(5); int shift = 25; modification.setShift(shift); diff --git a/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftRightModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftRightModificationTest.java index 24dc271a..9a726c64 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftRightModificationTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftRightModificationTest.java @@ -116,7 +116,7 @@ public void testEqualsAndHashCode() { @Test public void testGetterAndSetter() { - BigIntegerShiftRightModification modification = new BigIntegerShiftRightModification(); + BigIntegerShiftRightModification modification = new BigIntegerShiftRightModification(5); int shift = 25; modification.setShift(shift); diff --git a/src/test/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayShuffleModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayShuffleModificationTest.java index b719da2f..b9a9b67b 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayShuffleModificationTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayShuffleModificationTest.java @@ -23,9 +23,9 @@ public class ByteArrayShuffleModificationTest { public void setUp() { b1 = new ByteArrayShuffleModification( - new byte[] {0, 2, 1, 3}); // Swap positions 0 and 2, 1 and 3 - b2 = new ByteArrayShuffleModification(new byte[] {0, 2, 1, 3}); - b3 = new ByteArrayShuffleModification(new byte[] {1, 3, 0, 2}); // Different shuffle pattern + new int[] {0, 2, 1, 3}); // Swap positions 0 and 2, 1 and 3 + b2 = new ByteArrayShuffleModification(new int[] {0, 2, 1, 3}); + b3 = new ByteArrayShuffleModification(new int[] {1, 3, 0, 2}); // Different shuffle pattern b4 = new Object(); } @@ -61,7 +61,7 @@ public void testModifyImplementationHookLargeArray() { } // Create a shuffle modification for a large array - byte[] shufflePattern = new byte[] {0, 50, 1, 100, 10, (byte) 200, 20, (byte) 150}; + int[] shufflePattern = new int[] {0, 50, 1, 100, 10, (byte) 200, 20, (byte) 150}; ByteArrayShuffleModification largeShuffle = new ByteArrayShuffleModification(shufflePattern); @@ -87,15 +87,15 @@ public void testCreateCopy() { /** Test of getShuffle method, of class ByteArrayShuffleModification. */ @Test public void testGetShuffle() { - assertArrayEquals(new byte[] {0, 2, 1, 3}, b1.getShuffle()); + assertArrayEquals(new int[] {0, 2, 1, 3}, b1.getShuffle()); } /** Test of setShuffle method, of class ByteArrayShuffleModification. */ @Test public void testSetShuffle() { - ByteArrayShuffleModification mod = new ByteArrayShuffleModification(); - mod.setShuffle(new byte[] {5, 6, 7, 8}); - assertArrayEquals(new byte[] {5, 6, 7, 8}, mod.getShuffle()); + ByteArrayShuffleModification mod = new ByteArrayShuffleModification(new int[] {1, 2, 3}); + mod.setShuffle(new int[] {5, 6, 7, 8}); + assertArrayEquals(new int[] {5, 6, 7, 8}, mod.getShuffle()); } /** Test of hashCode method, of class ByteArrayShuffleModification. */ @@ -127,10 +127,10 @@ public void testEquals() { /** Test of toString method, of class ByteArrayShuffleModification. */ @Test public void testToString() { - String expected = "ByteArrayShuffleModification{shuffle=00 02 01 03}"; + String expected = "ByteArrayShuffleModification{shuffle=[0, 2, 1, 3]}"; assertEquals(expected, b1.toString()); - String expected3 = "ByteArrayShuffleModification{shuffle=01 03 00 02}"; + String expected3 = "ByteArrayShuffleModification{shuffle=[1, 3, 0, 2]}"; assertEquals(expected3, b3.toString()); } } diff --git a/src/test/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayXorModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayXorModificationTest.java index fce5eb66..dd1dcaca 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayXorModificationTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayXorModificationTest.java @@ -83,7 +83,7 @@ public void testGetXor() { /** Test of setXor method, of class ByteArrayXorModification. */ @Test public void testSetXor() { - ByteArrayXorModification mod = new ByteArrayXorModification(); + ByteArrayXorModification mod = new ByteArrayXorModification(new byte[] {0x01, 0x02}, 0); mod.setXor(new byte[] {0x0A, 0x0B}); assertArrayEquals(new byte[] {0x0A, 0x0B}, mod.getXor()); } @@ -98,7 +98,7 @@ public void testGetStartPosition() { /** Test of setStartPosition method, of class ByteArrayXorModification. */ @Test public void testSetStartPosition() { - ByteArrayXorModification mod = new ByteArrayXorModification(); + ByteArrayXorModification mod = new ByteArrayXorModification(new byte[] {0x01, 0x02}, 0); mod.setStartPosition(5); assertEquals(5, mod.getStartPosition()); } diff --git a/src/test/java/de/rub/nds/modifiablevariable/bytearray/ModifiableByteArrayTest.java b/src/test/java/de/rub/nds/modifiablevariable/bytearray/ModifiableByteArrayTest.java index 095b877b..10a35776 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/bytearray/ModifiableByteArrayTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/bytearray/ModifiableByteArrayTest.java @@ -319,17 +319,17 @@ public void testDuplicateModification() { @Test public void testShuffle() { LOGGER.info("testShuffle"); - VariableModification modifier = new ByteArrayShuffleModification(new byte[] {0, 1}); + VariableModification modifier = new ByteArrayShuffleModification(new int[] {0, 1}); start.setModifications(modifier); byte[] result = {1, 0, 2, 3, 4, 5, 6}; assertArrayEquals(result, start.getValue()); - modifier = new ByteArrayShuffleModification(new byte[] {0, 1, 2, 3, 4, 5, 6}); + modifier = new ByteArrayShuffleModification(new int[] {0, 1, 2, 3, 4, 5, 6}); start.setModifications(modifier); result = new byte[] {1, 0, 3, 2, 5, 4, 6}; assertArrayEquals(result, start.getValue()); - modifier = new ByteArrayShuffleModification(new byte[] {0, 1, 2, 3, 4, 5, 6, 7}); + modifier = new ByteArrayShuffleModification(new int[] {0, 1, 2, 3, 4, 5, 6, 7}); start.setModifications(modifier); result = new byte[] {6, 0, 3, 2, 5, 4, 1}; assertArrayEquals(result, start.getValue()); diff --git a/src/test/java/de/rub/nds/modifiablevariable/integer/IntegerMultiplyModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/integer/IntegerMultiplyModificationTest.java index 04ca17d5..4afafb27 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/integer/IntegerMultiplyModificationTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/integer/IntegerMultiplyModificationTest.java @@ -114,20 +114,6 @@ public void testMultiplyMinValue() { assertEquals(expected, result); } - @Test - public void testDefaultConstructor() { - IntegerMultiplyModification modification = new IntegerMultiplyModification(); - - // Set factor after construction - modification.setFactor(3); - - modifiableInteger.setModifications(modification); - int expected = originalValue * 3; - int result = modifiableInteger.getValue(); - - assertEquals(expected, result); - } - @Test public void testGetFactor() { int factor = 5; diff --git a/src/test/java/de/rub/nds/modifiablevariable/integer/IntegerShiftModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/integer/IntegerShiftModificationTest.java index 1c08f584..11460faa 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/integer/IntegerShiftModificationTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/integer/IntegerShiftModificationTest.java @@ -91,7 +91,7 @@ public void testShiftLeftEqualsAndHashCode() { @Test public void testShiftLeftGetterAndSetter() { - IntegerShiftLeftModification modification = new IntegerShiftLeftModification(); + IntegerShiftLeftModification modification = new IntegerShiftLeftModification(5); int shift = 15; modification.setShift(shift); @@ -178,7 +178,7 @@ public void testShiftRightEqualsAndHashCode() { @Test public void testShiftRightGetterAndSetter() { - IntegerShiftRightModification modification = new IntegerShiftRightModification(); + IntegerShiftRightModification modification = new IntegerShiftRightModification(5); int shift = 15; modification.setShift(shift); diff --git a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongAddModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongAddModificationTest.java index 1b02c966..ff0ad317 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongAddModificationTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongAddModificationTest.java @@ -83,9 +83,9 @@ public void testToString() { @Test public void testConstructors() { - // Test default constructor - LongAddModification defaultConstructor = new LongAddModification(); - assertNotNull(defaultConstructor); + LongAddModification constructor = new LongAddModification(5L); + assertNotNull(constructor); + assertEquals(constructor.getSummand(), 5); // Test copy constructor LongAddModification copy = new LongAddModification(modification); diff --git a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongExplicitValueModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongExplicitValueModificationTest.java index 379faa34..b255a907 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongExplicitValueModificationTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongExplicitValueModificationTest.java @@ -87,8 +87,9 @@ public void testToString() { @Test public void testConstructors() { // Test default constructor - LongExplicitValueModification defaultConstructor = new LongExplicitValueModification(); - assertNotNull(defaultConstructor); + LongExplicitValueModification constructor = new LongExplicitValueModification(5L); + assertNotNull(constructor); + assertEquals(constructor.getExplicitValue(), 5); // Test copy constructor LongExplicitValueModification copy = new LongExplicitValueModification(modification); diff --git a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongMultiplyModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongMultiplyModificationTest.java index 9283deab..4c38ad26 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongMultiplyModificationTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongMultiplyModificationTest.java @@ -83,9 +83,9 @@ public void testToString() { @Test public void testConstructors() { - // Test default constructor - LongMultiplyModification defaultConstructor = new LongMultiplyModification(); - assertNotNull(defaultConstructor); + LongMultiplyModification constructor = new LongMultiplyModification(5L); + assertNotNull(constructor); + assertEquals(5L, constructor.getFactor()); // Test copy constructor LongMultiplyModification copy = new LongMultiplyModification(modification); diff --git a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongShiftLeftModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongShiftLeftModificationTest.java index 1f643f1e..5dbf5020 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongShiftLeftModificationTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongShiftLeftModificationTest.java @@ -81,9 +81,9 @@ public void testToString() { @Test public void testConstructors() { - // Test default constructor - LongShiftLeftModification defaultConstructor = new LongShiftLeftModification(); - assertNotNull(defaultConstructor); + LongShiftLeftModification constructor = new LongShiftLeftModification(5); + assertNotNull(constructor); + assertEquals(5, constructor.getShift()); // Test copy constructor LongShiftLeftModification copy = new LongShiftLeftModification(modification); diff --git a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongShiftRightModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongShiftRightModificationTest.java index 04fd1ebe..74c92a95 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongShiftRightModificationTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongShiftRightModificationTest.java @@ -83,9 +83,9 @@ public void testToString() { @Test public void testConstructors() { - // Test default constructor - LongShiftRightModification defaultConstructor = new LongShiftRightModification(); - assertNotNull(defaultConstructor); + LongShiftRightModification constructor = new LongShiftRightModification(5); + assertNotNull(constructor); + assertEquals(5, constructor.getShift()); // Test copy constructor LongShiftRightModification copy = new LongShiftRightModification(modification); diff --git a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongSubtractModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongSubtractModificationTest.java index 83254a03..ee6dbc99 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongSubtractModificationTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongSubtractModificationTest.java @@ -81,9 +81,9 @@ public void testToString() { @Test public void testConstructors() { - // Test default constructor - LongSubtractModification defaultConstructor = new LongSubtractModification(); - assertNotNull(defaultConstructor); + LongSubtractModification constructor = new LongSubtractModification(5L); + assertNotNull(constructor); + assertEquals(5, constructor.getSubtrahend()); // Test copy constructor LongSubtractModification copy = new LongSubtractModification(modification); diff --git a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongXorModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongXorModificationTest.java index 3a010bb4..f1a732f1 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/mlong/LongXorModificationTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/mlong/LongXorModificationTest.java @@ -83,9 +83,9 @@ public void testToString() { @Test public void testConstructors() { - // Test default constructor - LongXorModification defaultConstructor = new LongXorModification(); - assertNotNull(defaultConstructor); + LongXorModification constuctor = new LongXorModification(2L); + assertNotNull(constuctor); + assertEquals(2L, constuctor.getXor()); // Test copy constructor LongXorModification copy = new LongXorModification(modification); diff --git a/src/test/java/de/rub/nds/modifiablevariable/mlong/ModifiableLongTest.java b/src/test/java/de/rub/nds/modifiablevariable/mlong/ModifiableLongTest.java index 1e1d5a5f..a9050e8c 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/mlong/ModifiableLongTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/mlong/ModifiableLongTest.java @@ -13,13 +13,15 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import de.rub.nds.modifiablevariable.longint.LongAddModification; -import de.rub.nds.modifiablevariable.longint.ModifiableLong; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import de.rub.nds.modifiablevariable.longint.LongAddModification; +import de.rub.nds.modifiablevariable.longint.ModifiableLong; + public class ModifiableLongTest { private ModifiableLong long1; @@ -63,7 +65,7 @@ public void testIsOriginalValueModified() { // Null original value ModifiableLong nullLong = new ModifiableLong(); - assertFalse(nullLong.isOriginalValueModified()); + assertThrows(IllegalStateException.class, nullLong::isOriginalValueModified); } /** Test of getByteArray method, of class ModifiableLong. */ diff --git a/src/test/java/de/rub/nds/modifiablevariable/string/ModifiableStringTest.java b/src/test/java/de/rub/nds/modifiablevariable/string/ModifiableStringTest.java index 42fb626b..3b63c6f6 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/string/ModifiableStringTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/string/ModifiableStringTest.java @@ -59,7 +59,7 @@ public void testAssertions() { @Test public void testGetByteArray() { byte[] expected = "TestString".getBytes(java.nio.charset.StandardCharsets.ISO_8859_1); - byte[] actual = string.getByteArray(expected.length); + byte[] actual = string.getByteArray(); for (int i = 0; i < expected.length; i++) { assertEquals(expected[i], actual[i]); diff --git a/src/test/java/de/rub/nds/modifiablevariable/util/RandomHelperTest.java b/src/test/java/de/rub/nds/modifiablevariable/util/RandomHelperTest.java index 0e58fce1..638cd42f 100644 --- a/src/test/java/de/rub/nds/modifiablevariable/util/RandomHelperTest.java +++ b/src/test/java/de/rub/nds/modifiablevariable/util/RandomHelperTest.java @@ -93,9 +93,6 @@ public void testBadRandomImplementation() { // Test generateSeed byte[] generatedSeed = badRandom.generateSeed(5); assertEquals(5, generatedSeed.length); - - // setSeed with byte array should throw UnsupportedOperationException - assertThrows(UnsupportedOperationException.class, () -> badRandom.setSeed(new byte[1])); } @Test