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 Note: Subclasses must ensure proper copying of the respecitve assertEquals field.
+ *
+ * @param other The modifiable variable to copy
+ */
protected ModifiableVariable(ModifiableVariable 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 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 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 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 For each ModifiableVariable field:
+ *
+ * This method is useful for returning an object to a clean state before applying new
+ * modifications.
+ */
public void reset() {
List 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:
+ *
+ * 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 This method is the main entry point for applying modifications to values. It follows the
+ * Template Method pattern by:
+ *
+ * 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 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 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 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 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 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 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 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 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 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 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 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 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 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:
+ *
+ * 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 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 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 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 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
+ * 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 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:
+ *
+ * This class extends {@link ModifiableVariable} to provide runtime modification capabilities for
+ * byte array values. It supports various byte array-specific modifications such as:
+ *
+ * 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 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 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 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 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 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 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 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 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 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 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 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 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:
+ *
+ * The byte array formatting is controlled by two static configuration options:
+ *
+ * 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 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 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 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 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 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 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 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:
+ *
+ * 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 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 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 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 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 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 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 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 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 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 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.
+ *
+ * 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 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 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 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:
+ *
+ * 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 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:
+ *
+ * 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:
+ *
+ * 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:
+ *
+ * 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 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:
+ *
+ * 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 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 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 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 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 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:
+ *
+ * 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
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * @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
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * @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.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * @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.
+ *
+ *
+ *
+ *
+ * @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
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * @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.
+ *
+ *
+ * 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.
+ *
+ *
+ *
+ *
+ * @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.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * @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.
+ *
+ *
+ *
+ *
+ * @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.
+ *
+ *
+ *
+ */
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.
+ *
+ *
+ *
+ *
+ * {@code
+ * public class MyClass {
+ * @XmlElement
+ * @XmlJavaTypeAdapter(IllegalStringAdapter.class)
+ * private String data = "Line 1\nLine 2"; // Contains a newline that needs escaping
+ * }
+ * }
+ *
+ * {@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
+ * }
+ *
+ *
+ *
*
- * @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