modification) {
+ if (modification != null) {
+ if (modifications == null) {
+ modifications = new LinkedList<>();
+ }
+ modifications.add(modification);
+ }
+ }
+
+ /**
+ * Returns the first modification that was set for this modifiable variable, if one exists.
+ *
+ * Use {@code getModifications()} to get all modifications
+ */
public VariableModification getModification() {
- return modification;
+ if (modifications == null || modifications.isEmpty()) {
+ return null;
+ }
+ return modifications.getFirst();
+ }
+
+ /** Returns all modifications that are set for this modifiable variable */
+ public LinkedList> getModifications() {
+ return modifications;
}
public E getValue() {
if (Objects.equals(createRandomModification, Boolean.TRUE)) {
- createRandomModification();
+ setRandomModification();
createRandomModification = false;
}
- if (modification != null) {
- return modification.modify(getOriginalValue());
+ return getModifiedValue();
+ }
+
+ private E getModifiedValue() {
+ E resultValue = getOriginalValue();
+ if (modifications != null) {
+ for (VariableModification modification : modifications) {
+ resultValue = modification.modify(resultValue);
+ }
+ }
+ return resultValue;
+ }
+
+ /**
+ * Sets the original value to the value changed by the modification. The modification is then
+ * set to null, to reduce the modifiable variable to the original value.
+ *
+ * createRandomModification is ignored
+ */
+ public void reduceToOriginalValue(boolean evenWithNullOriginalValue) {
+ if (evenWithNullOriginalValue || getOriginalValue() != null) {
+ if (modifications != null) {
+ setOriginalValue(getModifiedValue());
+ modifications = null;
+ }
}
- return getOriginalValue();
}
public abstract E getOriginalValue();
public abstract void setOriginalValue(E originalValue);
- protected abstract void createRandomModification();
+ /** Set a single random modification, all previously set modifications are removed */
+ public abstract void setRandomModification();
+
+ public abstract ModifiableVariable createCopy();
public void createRandomModificationAtRuntime() {
createRandomModification = true;
@@ -195,13 +300,31 @@ public void createRandomModificationAtRuntime() {
public abstract boolean validateAssertions();
public boolean containsAssertion() {
- return (assertEquals != null);
+ return assertEquals != null;
}
public Boolean isCreateRandomModification() {
- if (createRandomModification == null) {
- return false;
+ return Objects.requireNonNullElse(createRandomModification, false);
+ }
+
+ public String innerToString() {
+ StringBuilder result = new StringBuilder();
+ if (modifications != null) {
+ result.append(", modifications=[")
+ .append(
+ modifications.stream()
+ .map(Object::toString)
+ .collect(Collectors.joining(", ")))
+ .append("]");
+ }
+
+ if (createRandomModification != null) {
+ result.append(", createRandomModification=").append(createRandomModification);
+ }
+ if (assertEquals != null) {
+ result.append(", assertEquals=").append(assertEquals);
}
- return createRandomModification;
+
+ return result.toString();
}
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableFactory.java b/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableFactory.java
index 19b9a22d..3c0d2f1a 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableFactory.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableFactory.java
@@ -12,11 +12,12 @@
import de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray;
import de.rub.nds.modifiablevariable.integer.ModifiableInteger;
import de.rub.nds.modifiablevariable.longint.ModifiableLong;
+import de.rub.nds.modifiablevariable.path.ModifiablePath;
import de.rub.nds.modifiablevariable.singlebyte.ModifiableByte;
import de.rub.nds.modifiablevariable.string.ModifiableString;
import java.math.BigInteger;
-public class ModifiableVariableFactory {
+public final class ModifiableVariableFactory {
public static ModifiableBigInteger createBigIntegerModifiableVariable() {
return new ModifiableBigInteger();
@@ -38,61 +39,297 @@ public static ModifiableLong createLongModifiableVariable() {
return new ModifiableLong();
}
+ public static ModifiableBoolean createBooleanModifiableVariable() {
+ return new ModifiableBoolean();
+ }
+
+ public static ModifiableString createStringModifiableVariable() {
+ return new ModifiableString();
+ }
+
+ public static ModifiablePath createPathModifiableVariable() {
+ return new ModifiablePath();
+ }
+
public static ModifiableBigInteger safelySetValue(ModifiableBigInteger mv, BigInteger value) {
if (mv == null) {
- mv = new ModifiableBigInteger();
+ return new ModifiableBigInteger(value);
}
mv.setOriginalValue(value);
return mv;
}
+ /**
+ * Returns only a ModifiableBigInteger with the value, if the given mv is null or the original
+ * value of the mv is null
+ */
+ public static ModifiableBigInteger softlySetValue(ModifiableBigInteger mv, BigInteger value) {
+ if (mv == null) {
+ return new ModifiableBigInteger(value);
+ } else if (mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
+ /**
+ * Returns only a ModifiableBigInteger with the value, if the given mv is null or the original
+ * value of the mv is null or alwaysSet is true
+ */
+ public static ModifiableBigInteger softlySetValue(
+ ModifiableBigInteger mv, BigInteger value, boolean alwaysSet) {
+ if (mv == null) {
+ return new ModifiableBigInteger(value);
+ } else if (alwaysSet || mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
public static ModifiableString safelySetValue(ModifiableString mv, String value) {
if (mv == null) {
- mv = new ModifiableString();
+ return new ModifiableString(value);
}
mv.setOriginalValue(value);
return mv;
}
+ /**
+ * Returns only a ModifiableString with the value, if the given mv is null or the original value
+ * of the mv is null
+ */
+ public static ModifiableString softlySetValue(ModifiableString mv, String value) {
+ if (mv == null) {
+ return new ModifiableString(value);
+ } else if (mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
+ /**
+ * Returns only a ModifiableString with the value, if the given mv is null or the original value
+ * of the mv is null or alwaysSet is true
+ */
+ public static ModifiableString softlySetValue(
+ ModifiableString mv, String value, boolean alwaysSet) {
+ if (mv == null) {
+ return new ModifiableString(value);
+ } else if (alwaysSet || mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
public static ModifiableInteger safelySetValue(ModifiableInteger mv, Integer value) {
if (mv == null) {
- mv = new ModifiableInteger();
+ return new ModifiableInteger(value);
}
mv.setOriginalValue(value);
return mv;
}
+ /**
+ * Returns only a ModifiableInteger with the value, if the given mv is null or the original
+ * value of the mv is null
+ */
+ public static ModifiableInteger softlySetValue(ModifiableInteger mv, Integer value) {
+ if (mv == null) {
+ return new ModifiableInteger(value);
+ } else if (mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
+ /**
+ * Returns only a ModifiableInteger with the value, if the given mv is null or the original
+ * value of the mv is null or alwaysSet is true
+ */
+ public static ModifiableInteger softlySetValue(
+ ModifiableInteger mv, Integer value, boolean alwaysSet) {
+ if (mv == null) {
+ return new ModifiableInteger(value);
+ } else if (alwaysSet || mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
public static ModifiableByte safelySetValue(ModifiableByte mv, Byte value) {
if (mv == null) {
- mv = new ModifiableByte();
+ return new ModifiableByte(value);
}
mv.setOriginalValue(value);
return mv;
}
+ /**
+ * Returns only a ModifiableByte with the value, if the given mv is null or the original value
+ * of the mv is null
+ */
+ public static ModifiableByte softlySetValue(ModifiableByte mv, Byte value) {
+ if (mv == null) {
+ return new ModifiableByte(value);
+ } else if (mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
+ /**
+ * Returns only a ModifiableByte with the value, if the given mv is null or the original value
+ * of the mv is null or alwaysSet is true
+ */
+ public static ModifiableByte softlySetValue(ModifiableByte mv, Byte value, boolean alwaysSet) {
+ if (mv == null) {
+ return new ModifiableByte(value);
+ } else if (alwaysSet || mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
public static ModifiableByteArray safelySetValue(ModifiableByteArray mv, byte[] value) {
if (mv == null) {
- mv = new ModifiableByteArray();
+ return new ModifiableByteArray(value);
}
mv.setOriginalValue(value);
return mv;
}
+ /**
+ * Returns only a ModifiableByteArray with the value, if the given mv is null or the original
+ * value of the mv is null
+ */
+ public static ModifiableByteArray softlySetValue(ModifiableByteArray mv, byte[] value) {
+ if (mv == null) {
+ return new ModifiableByteArray(value);
+ } else if (mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
+ /**
+ * Returns only a ModifiableByteArray with the value, if the given mv is null or the original
+ * value of the mv is null or alwaysSet is true
+ */
+ public static ModifiableByteArray softlySetValue(
+ ModifiableByteArray mv, byte[] value, boolean alwaysSet) {
+ if (mv == null) {
+ return new ModifiableByteArray(value);
+ } else if (alwaysSet || mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
public static ModifiableLong safelySetValue(ModifiableLong mv, Long value) {
if (mv == null) {
- mv = new ModifiableLong();
+ return new ModifiableLong(value);
}
mv.setOriginalValue(value);
return mv;
}
+ /**
+ * Returns only a ModifiableLong with the value, if the given mv is null or the original value
+ * of the mv is null
+ */
+ public static ModifiableLong softlySetValue(ModifiableLong mv, Long value) {
+ if (mv == null) {
+ return new ModifiableLong(value);
+ } else if (mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
+ /**
+ * Returns only a ModifiableLong with the value, if the given mv is null or the original value
+ * of the mv is null or alwaysSet is true
+ */
+ public static ModifiableLong softlySetValue(ModifiableLong mv, Long value, boolean alwaysSet) {
+ if (mv == null) {
+ return new ModifiableLong(value);
+ } else if (alwaysSet || mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
public static ModifiableBoolean safelySetValue(ModifiableBoolean mv, Boolean value) {
if (mv == null) {
- mv = new ModifiableBoolean();
+ return new ModifiableBoolean(value);
+ }
+ mv.setOriginalValue(value);
+ return mv;
+ }
+
+ /**
+ * Returns only a ModifiableBoolean with the value, if the given mv is null or the original
+ * value of the mv is null
+ */
+ public static ModifiableBoolean softlySetValue(ModifiableBoolean mv, Boolean value) {
+ if (mv == null) {
+ return new ModifiableBoolean(value);
+ } else if (mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
+ /**
+ * Returns only a ModifiableBoolean with the value, if the given mv is null or the original
+ * value of the mv is null or alwaysSet is true
+ */
+ public static ModifiableBoolean softlySetValue(
+ ModifiableBoolean mv, Boolean value, boolean alwaysSet) {
+ if (mv == null) {
+ return new ModifiableBoolean(value);
+ } else if (alwaysSet || mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
+ public static ModifiablePath safelySetValue(ModifiablePath mv, String value) {
+ if (mv == null) {
+ return new ModifiablePath(value);
}
mv.setOriginalValue(value);
return mv;
}
- private ModifiableVariableFactory() {}
+ /**
+ * Returns only a ModifiablePath with the value, if the given mv is null or the original value
+ * of the mv is null
+ */
+ public static ModifiablePath softlySetValue(ModifiablePath mv, String value) {
+ if (mv == null) {
+ return new ModifiablePath(value);
+ } else if (mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
+ /**
+ * Returns only a ModifiablePath with the value, if the given mv is null or the original value
+ * of the mv is null or alwaysSet is true
+ */
+ public static ModifiablePath softlySetValue(
+ ModifiablePath mv, String value, boolean alwaysSet) {
+ if (mv == null) {
+ return new ModifiablePath(value);
+ } else if (alwaysSet || mv.getOriginalValue() == null) {
+ mv.setOriginalValue(value);
+ }
+ return mv;
+ }
+
+ 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 137fc7b8..73bc4928 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableHolder.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableHolder.java
@@ -30,7 +30,7 @@ public abstract class ModifiableVariableHolder implements Serializable {
* @return List of all modifiableVariables declared in this class
*/
public List getAllModifiableVariableFields() {
- return ReflectionHelper.getFieldsUpTo(this.getClass(), null, ModifiableVariable.class);
+ return ReflectionHelper.getFieldsUpTo(getClass(), null, ModifiableVariable.class);
}
/**
@@ -70,12 +70,12 @@ public ModifiableVariableHolder getRandomModifiableVariableHolder(Random random)
public void reset() {
List fields = getAllModifiableVariableFields();
- for (Field f : fields) {
- f.setAccessible(true);
+ for (Field field : fields) {
+ field.setAccessible(true);
ModifiableVariable> mv = null;
try {
- mv = (ModifiableVariable>) f.get(this);
+ mv = (ModifiableVariable>) field.get(this);
} catch (IllegalArgumentException | IllegalAccessException ex) {
LOGGER.warn("Could not retrieve ModifiableVariables");
LOGGER.debug(ex);
@@ -85,7 +85,7 @@ public void reset() {
mv.setOriginalValue(null);
} else {
try {
- f.set(this, null);
+ field.set(this, null);
} catch (IllegalArgumentException | IllegalAccessException ex) {
LOGGER.warn("Could not strip ModifiableVariable without Modification");
}
@@ -95,17 +95,12 @@ public void reset() {
}
public String getExtendedString() {
- StringBuilder sb = new StringBuilder();
- sb.append(getClass().getSimpleName());
- sb.append("{\n");
- sb.append(getExtendedString(1));
- sb.append("}\n");
- return sb.toString();
+ return getClass().getSimpleName() + "{\n" + getExtendedString(1) + "}\n";
}
protected String getExtendedString(int depth) {
StringBuilder stringBuilder = new StringBuilder();
- List fields = ReflectionHelper.getFieldsUpTo(this.getClass(), null, null);
+ List fields = ReflectionHelper.getFieldsUpTo(getClass(), null, null);
for (Field field : fields) {
field.setAccessible(true);
// skip static
@@ -122,41 +117,31 @@ protected String getExtendedString(int depth) {
if (tempObject != null) {
if (tempObject instanceof byte[]) {
byte[] temp = (byte[]) tempObject;
- for (int i = 0; i < depth; i++) {
- stringBuilder.append("\t");
- }
+ stringBuilder.append("\t".repeat(Math.max(0, depth)));
stringBuilder.append(field.getName());
stringBuilder.append(": ");
stringBuilder.append(ArrayConverter.bytesToHexString(temp));
stringBuilder.append("\n");
}
if (tempObject instanceof ModifiableVariableHolder) {
- for (int i = 0; i < depth; i++) {
- stringBuilder.append("\t");
- }
+ stringBuilder.append("\t".repeat(Math.max(0, depth)));
stringBuilder.append(field.getName());
stringBuilder.append(":");
stringBuilder.append(tempObject.getClass().getSimpleName());
stringBuilder.append("{\n");
stringBuilder.append(
((ModifiableVariableHolder) tempObject).getExtendedString(depth + 1));
- for (int i = 0; i < depth; i++) {
- stringBuilder.append("\t");
- }
+ stringBuilder.append("\t".repeat(Math.max(0, depth)));
stringBuilder.append("}\n");
} else {
- for (int i = 0; i < depth; i++) {
- stringBuilder.append("\t");
- }
+ stringBuilder.append("\t".repeat(Math.max(0, depth)));
stringBuilder.append(field.getName());
stringBuilder.append(": ");
- stringBuilder.append(tempObject.toString());
+ stringBuilder.append(tempObject);
stringBuilder.append("\n");
}
} else {
- for (int i = 0; i < depth; i++) {
- stringBuilder.append("\t");
- }
+ stringBuilder.append("\t".repeat(Math.max(0, depth)));
stringBuilder.append(field.getName());
stringBuilder.append(": null\n");
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableProperty.java b/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableProperty.java
index e80a3d64..affcc4db 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableProperty.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/ModifiableVariableProperty.java
@@ -17,7 +17,7 @@
@Retention(RetentionPolicy.RUNTIME)
public @interface ModifiableVariableProperty {
- public enum Type {
+ enum Type {
LENGTH,
COUNT,
PADDING,
@@ -38,7 +38,7 @@ public enum Type {
BEHAVIOR_SWITCH
}
- public enum Format {
+ enum Format {
ASN1,
PKCS1,
NONE
diff --git a/src/main/java/de/rub/nds/modifiablevariable/ModificationFilter.java b/src/main/java/de/rub/nds/modifiablevariable/ModificationFilter.java
index f7967f1b..24816427 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/ModificationFilter.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/ModificationFilter.java
@@ -15,8 +15,18 @@
* data. For example, only the first data access returns a modified value. This can be achieved
* using a ModificationFilter object.
*/
-@XmlSeeAlso({AccessModificationFilter.class})
+@XmlSeeAlso(AccessModificationFilter.class)
public abstract class ModificationFilter {
+ protected ModificationFilter() {
+ super();
+ }
+
+ protected ModificationFilter(ModificationFilter other) {
+ super();
+ }
+
+ public abstract ModificationFilter createCopy();
+
public abstract boolean filterModification();
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/VariableModification.java b/src/main/java/de/rub/nds/modifiablevariable/VariableModification.java
index 04e81ef2..be4396b4 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/VariableModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/VariableModification.java
@@ -32,16 +32,24 @@ public abstract class VariableModification {
* ModificationFilter is responsible for validating if the modification can be executed.
*/
@XmlElements(
- value = {
- @XmlElement(
- type = AccessModificationFilter.class,
- name = "AccessModificationFilter")
- })
- private ModificationFilter modificationFilter = null;
+ @XmlElement(type = AccessModificationFilter.class, name = "AccessModificationFilter"))
+ private ModificationFilter modificationFilter;
+
+ protected VariableModification() {
+ super();
+ }
+
+ protected VariableModification(VariableModification other) {
+ super();
+ modificationFilter =
+ other.modificationFilter != null ? other.modificationFilter.createCopy() : null;
+ }
+
+ public abstract VariableModification createCopy();
public E modify(E input) {
E modifiedValue = modifyImplementationHook(input);
- if ((modificationFilter == null) || (modificationFilter.filterModification() == false)) {
+ if (modificationFilter == null || !modificationFilter.filterModification()) {
debug(modifiedValue);
return modifiedValue;
} else {
@@ -54,7 +62,7 @@ public E modify(E input) {
public abstract VariableModification getModifiedCopy();
/**
- * Debugging modified variables. Getting stack trace can be time consuming, thus we use
+ * Debugging modified variables. Getting stack trace can be time-consuming, thus we use
* isDebugEnabled() function
*
* @param value variable modification that is going to be debugged
@@ -78,7 +86,7 @@ protected void debug(E value) {
}
LOGGER.debug(
"Using {} in function:\n {}\n New value: {}",
- this.getClass().getSimpleName(),
+ getClass().getSimpleName(),
stack[index],
valueString);
}
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 012555ca..8e5e44d2 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerAddModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerAddModification.java
@@ -25,15 +25,28 @@ public class BigIntegerAddModification extends VariableModification
private BigInteger summand;
- public BigIntegerAddModification() {}
+ public BigIntegerAddModification() {
+ super();
+ }
+
+ public BigIntegerAddModification(BigInteger summand) {
+ super();
+ this.summand = summand;
+ }
+
+ public BigIntegerAddModification(BigIntegerAddModification other) {
+ super(other);
+ summand = other.summand;
+ }
- public BigIntegerAddModification(BigInteger bi) {
- this.summand = bi;
+ @Override
+ public BigIntegerAddModification createCopy() {
+ return new BigIntegerAddModification(this);
}
@Override
protected BigInteger modifyImplementationHook(BigInteger input) {
- return (input == null) ? summand : input.add(summand);
+ return input == null ? summand : input.add(summand);
}
public BigInteger getSummand() {
@@ -53,7 +66,7 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
int hash = 7;
- hash = 41 * hash + Objects.hashCode(this.summand);
+ hash = 31 * hash + summand.hashCode();
return hash;
}
@@ -68,10 +81,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final BigIntegerAddModification other = (BigIntegerAddModification) obj;
- if (!Objects.equals(this.summand, other.summand)) {
- return false;
- }
- return true;
+ BigIntegerAddModification other = (BigIntegerAddModification) obj;
+ return Objects.equals(summand, other.summand);
+ }
+
+ @Override
+ public String toString() {
+ return "BigIntegerAddModification{" + "summand=" + summand + '}';
}
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerAppendValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerAppendValueModification.java
new file mode 100644
index 00000000..0e7b70eb
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerAppendValueModification.java
@@ -0,0 +1,95 @@
+/*
+ * 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.biginteger;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.math.BigInteger;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"appendValue", "modificationFilter"})
+@XmlAccessorType(XmlAccessType.FIELD)
+public class BigIntegerAppendValueModification extends VariableModification {
+
+ private static final int MAX_APPEND_LENGTH = 8;
+
+ private BigInteger appendValue;
+
+ public BigIntegerAppendValueModification() {
+ super();
+ }
+
+ public BigIntegerAppendValueModification(BigInteger appendValue) {
+ super();
+ this.appendValue = appendValue;
+ }
+
+ public BigIntegerAppendValueModification(BigIntegerAppendValueModification other) {
+ super(other);
+ appendValue = other.appendValue;
+ }
+
+ @Override
+ public BigIntegerAppendValueModification createCopy() {
+ return new BigIntegerAppendValueModification(this);
+ }
+
+ @Override
+ protected BigInteger modifyImplementationHook(BigInteger input) {
+ if (input == null) {
+ input = BigInteger.ZERO;
+ }
+ return input.shiftLeft(appendValue.bitLength()).or(appendValue);
+ }
+
+ public BigInteger getAppendValue() {
+ return appendValue;
+ }
+
+ public void setAppendValue(BigInteger appendValue) {
+ this.appendValue = appendValue;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ return new BigIntegerAppendValueModification(
+ appendValue.add(new BigInteger(MAX_APPEND_LENGTH, new Random())));
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + appendValue.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ BigIntegerAppendValueModification other = (BigIntegerAppendValueModification) obj;
+ return Objects.equals(appendValue, other.appendValue);
+ }
+
+ @Override
+ public String toString() {
+ return "BigIntegerAppendValueModification{" + "appendValue=" + appendValue + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerExplicitValueFromFileModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerExplicitValueFromFileModification.java
new file mode 100644
index 00000000..3cfe18b1
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerExplicitValueFromFileModification.java
@@ -0,0 +1,91 @@
+/*
+ * 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.biginteger;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.math.BigInteger;
+import java.util.Objects;
+
+@XmlRootElement
+@XmlType(propOrder = "index")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class BigIntegerExplicitValueFromFileModification
+ extends BigIntegerExplicitValueModification {
+ private int index;
+
+ public BigIntegerExplicitValueFromFileModification() {
+ super();
+ }
+
+ public BigIntegerExplicitValueFromFileModification(int index, BigInteger explicitValue) {
+ super(explicitValue);
+ this.index = index;
+ }
+
+ public BigIntegerExplicitValueFromFileModification(
+ BigIntegerExplicitValueFromFileModification other) {
+ super(other);
+ index = other.index;
+ }
+
+ @Override
+ public BigIntegerExplicitValueFromFileModification createCopy() {
+ return new BigIntegerExplicitValueFromFileModification(this);
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ throw new UnsupportedOperationException(
+ "Cannot set modify Value of BigIntegerExplicitValueFromFileModification");
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + index;
+ hash = 31 * hash + explicitValue.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ BigIntegerExplicitValueFromFileModification other =
+ (BigIntegerExplicitValueFromFileModification) obj;
+ if (index != other.index) {
+ return false;
+ }
+ return Objects.equals(explicitValue, other.explicitValue);
+ }
+
+ @Override
+ public String toString() {
+ return "BigIntegerExplicitValueFromFileModification{"
+ + "index="
+ + index
+ + ", explicitValue="
+ + explicitValue
+ + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerExplicitValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerExplicitValueModification.java
index 8f59ad9d..3150a89b 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerExplicitValueModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerExplicitValueModification.java
@@ -23,16 +23,29 @@ public class BigIntegerExplicitValueModification extends VariableModification getModifiedCopy() {
@Override
public int hashCode() {
- int hash = 3;
- hash = 41 * hash + Objects.hashCode(this.explicitValue);
+ int hash = 7;
+ hash = 31 * hash + explicitValue.hashCode();
return hash;
}
@@ -74,10 +87,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final BigIntegerExplicitValueModification other = (BigIntegerExplicitValueModification) obj;
- if (!Objects.equals(this.explicitValue, other.explicitValue)) {
- return false;
- }
- return true;
+ BigIntegerExplicitValueModification other = (BigIntegerExplicitValueModification) obj;
+ return Objects.equals(explicitValue, other.explicitValue);
+ }
+
+ @Override
+ public String toString() {
+ return "BigIntegerExplicitValueModification{" + "explicitValue=" + explicitValue + '}';
}
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerInsertValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerInsertValueModification.java
new file mode 100644
index 00000000..007f9f12
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerInsertValueModification.java
@@ -0,0 +1,146 @@
+/*
+ * 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.biginteger;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.math.BigInteger;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"insertValue", "startPosition", "modificationFilter"})
+@XmlAccessorType(XmlAccessType.FIELD)
+public class BigIntegerInsertValueModification extends VariableModification {
+
+ private static final int MAX_INSERT_LENGTH = 8;
+ private static final int MAX_POSITION_MODIFIER = 32;
+
+ private BigInteger insertValue;
+ private int startPosition;
+
+ public BigIntegerInsertValueModification() {
+ super();
+ }
+
+ public BigIntegerInsertValueModification(BigInteger insertValue, int startPosition) {
+ super();
+ this.insertValue = insertValue;
+ this.startPosition = startPosition;
+ }
+
+ public BigIntegerInsertValueModification(BigIntegerInsertValueModification other) {
+ super(other);
+ insertValue = other.insertValue;
+ startPosition = other.startPosition;
+ }
+
+ @Override
+ public BigIntegerInsertValueModification createCopy() {
+ return new BigIntegerInsertValueModification(this);
+ }
+
+ @Override
+ protected BigInteger modifyImplementationHook(BigInteger input) {
+ if (input == null) {
+ input = BigInteger.ZERO;
+ }
+
+ int originalValueLength = input.bitLength();
+ int insertValueLength = insertValue.bitLength();
+
+ // Wrap around and also allow to insert at the end of the original value
+ int insertPosition = startPosition % (originalValueLength + 1);
+ if (startPosition < 0) {
+ insertPosition += originalValueLength;
+ }
+
+ BigInteger mask = BigInteger.valueOf((1L << insertPosition) - 1);
+
+ return input.shiftRight(insertPosition)
+ .shiftLeft(insertValueLength)
+ .or(insertValue)
+ .shiftLeft(insertPosition)
+ .or(mask.and(input));
+ }
+
+ public BigInteger getInsertValue() {
+ return insertValue;
+ }
+
+ public void setInsertValue(BigInteger insertValue) {
+ this.insertValue = insertValue;
+ }
+
+ public int getStartPosition() {
+ return startPosition;
+ }
+
+ public void setStartPosition(int startPosition) {
+ this.startPosition = startPosition;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+
+ if (r.nextBoolean()) {
+ return new BigIntegerInsertValueModification(
+ insertValue.add(new BigInteger(MAX_INSERT_LENGTH, r)), startPosition);
+ } else {
+ int modifier = r.nextInt(MAX_POSITION_MODIFIER);
+ if (r.nextBoolean()) {
+ modifier *= -1;
+ }
+ modifier = startPosition + modifier;
+ if (modifier <= 0) {
+ modifier = 1;
+ }
+ return new BigIntegerInsertValueModification(insertValue, modifier);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + insertValue.hashCode();
+ hash = 31 * hash + startPosition;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ BigIntegerInsertValueModification other = (BigIntegerInsertValueModification) obj;
+ if (startPosition != other.startPosition) {
+ return false;
+ }
+ return Objects.equals(insertValue, other.insertValue);
+ }
+
+ @Override
+ public String toString() {
+ return "BigIntegerInsertValueModification{"
+ + "insertValue="
+ + insertValue
+ + ", startPosition="
+ + startPosition
+ + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerInteractiveModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerInteractiveModification.java
index 0ec3fa18..61162991 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerInteractiveModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerInteractiveModification.java
@@ -16,23 +16,25 @@
import java.math.BigInteger;
@XmlRootElement
-@XmlType(propOrder = {"modificationFilter"})
+@XmlType(propOrder = "modificationFilter")
@XmlAccessorType(XmlAccessType.FIELD)
public class BigIntegerInteractiveModification extends VariableModification {
- @XmlTransient private InteractiveBigIntegerModification modification;
+ @XmlTransient private final InteractiveBigIntegerModification modification;
protected BigIntegerInteractiveModification() {
- this.modification = BigIntegerModificationFactory.getStandardInteractiveModification();
+ super();
+ modification = BigIntegerModificationFactory.getStandardInteractiveModification();
}
protected BigIntegerInteractiveModification(InteractiveBigIntegerModification modification) {
+ super();
this.modification = modification;
}
@Override
- protected BigInteger modifyImplementationHook(final BigInteger input) {
- return this.modification.modify(input);
+ protected BigInteger modifyImplementationHook(BigInteger input) {
+ return modification.modify(input);
}
public interface InteractiveBigIntegerModification {
@@ -45,4 +47,10 @@ public VariableModification getModifiedCopy() {
throw new UnsupportedOperationException(
"This method is not supported for interactive modifications");
}
+
+ @Override
+ public VariableModification createCopy() {
+ throw new UnsupportedOperationException(
+ "This method is not supported for interactive modifications");
+ }
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerModificationFactory.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerModificationFactory.java
index abb2c80e..57e3ba7a 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerModificationFactory.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerModificationFactory.java
@@ -10,84 +10,115 @@
import de.rub.nds.modifiablevariable.FileConfigurationException;
import de.rub.nds.modifiablevariable.VariableModification;
import de.rub.nds.modifiablevariable.bytearray.ByteArrayModificationFactory;
-import de.rub.nds.modifiablevariable.integer.IntegerModificationFactory;
+import de.rub.nds.modifiablevariable.longint.LongModificationFactory;
import de.rub.nds.modifiablevariable.util.RandomHelper;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Random;
-import java.util.Scanner;
+import java.util.*;
-public class BigIntegerModificationFactory {
+public final class BigIntegerModificationFactory {
- private static final int MODIFICATION_COUNT = 7;
+ private enum ModificationType {
+ ADD,
+ SUBTRACT,
+ MULTIPLY,
+ XOR,
+ EXPLICIT,
+ SHIFT_LEFT,
+ SHIFT_RIGHT,
+ EXPLICIT_FROM_FILE,
+ APPEND,
+ INSERT,
+ PREPEND
+ }
+
+ private static final int MODIFICATION_COUNT = ModificationType.values().length;
private static final int MAX_MODIFICATION_VALUE = 320000;
+ private static final int MAX_FILE_ENTRIES = 200;
+
private static final int MAX_MODIFICATION_SHIFT_VALUE = 50;
+ private static final int MAX_MODIFICATION_MULTIPLY_VALUE = 256;
+
+ private static final int MAX_MODIFICATION_INSERT_VALUE = 256;
+
+ private static final int MAX_MODIFICATION_INSERT_POSITION_VALUE = 50;
+
private static List> modificationsFromFile;
- public static BigIntegerAddModification add(final String summand) {
+ public static BigIntegerAddModification add(String summand) {
return add(new BigInteger(summand));
}
- public static BigIntegerAddModification add(final BigInteger summand) {
+ public static BigIntegerAddModification add(BigInteger summand) {
return new BigIntegerAddModification(summand);
}
- public static BigIntegerShiftLeftModification shiftLeft(final String shift) {
+ public static BigIntegerShiftLeftModification shiftLeft(String shift) {
return shiftLeft(Integer.parseInt(shift));
}
- public static BigIntegerShiftLeftModification shiftLeft(final Integer shift) {
+ public static BigIntegerShiftLeftModification shiftLeft(Integer shift) {
return new BigIntegerShiftLeftModification(shift);
}
- public static BigIntegerShiftRightModification shiftRight(final String shift) {
+ public static BigIntegerShiftRightModification shiftRight(String shift) {
return shiftRight(Integer.parseInt(shift));
}
- public static BigIntegerShiftRightModification shiftRight(final Integer shift) {
+ public static BigIntegerShiftRightModification shiftRight(Integer shift) {
return new BigIntegerShiftRightModification(shift);
}
- public static BigIntegerMultiplyModification multiply(final BigInteger factor) {
+ public static BigIntegerMultiplyModification multiply(BigInteger factor) {
return new BigIntegerMultiplyModification(factor);
}
- public static VariableModification sub(final String subtrahend) {
+ public static VariableModification sub(String subtrahend) {
return sub(new BigInteger(subtrahend));
}
- public static VariableModification sub(final BigInteger subtrahend) {
+ public static VariableModification sub(BigInteger subtrahend) {
return new BigIntegerSubtractModification(subtrahend);
}
- public static VariableModification xor(final String xor) {
+ public static VariableModification xor(String xor) {
return xor(new BigInteger(xor));
}
- public static VariableModification xor(final BigInteger xor) {
+ public static VariableModification xor(BigInteger xor) {
return new BigIntegerXorModification(xor);
}
- public static VariableModification explicitValue(final String value) {
+ public static VariableModification explicitValue(String value) {
return explicitValue(new BigInteger(value));
}
- public static VariableModification explicitValue(final BigInteger value) {
+ public static VariableModification explicitValue(BigInteger value) {
return new BigIntegerExplicitValueModification(value);
}
- public static VariableModification explicitValueFromFile(int value) {
+ public static VariableModification explicitValueFromFile(int pos) {
List> modifications = modificationsFromFile();
- int pos = value % modifications.size();
- return modifications.get(pos);
+ return modifications.get(pos % modifications.size());
+ }
+
+ public static VariableModification appendValue(BigInteger value) {
+ return new BigIntegerAppendValueModification(value);
+ }
+
+ public static VariableModification insertValue(
+ BigInteger value, int startPosition) {
+ return new BigIntegerInsertValueModification(value, startPosition);
+ }
+
+ public static VariableModification prependValue(BigInteger value) {
+ return new BigIntegerPrependValueModification(value);
}
/*
@@ -102,11 +133,8 @@ public static VariableModification explicitValueFromFile(int value)
public BigInteger modify(BigInteger oldVal) {
if (value == null) {
System.out.println("Enter new value for BigInt: ");
- Scanner scanner = new Scanner(System.in);
- try {
+ try (Scanner scanner = new Scanner(System.in)) {
value = scanner.nextBigInteger();
- } finally {
- scanner.close();
}
}
return value;
@@ -118,7 +146,7 @@ public static void setStandardInteractiveModification(
standardInteractiveModification = modification;
}
- protected static BigIntegerInteractiveModification.InteractiveBigIntegerModification
+ static BigIntegerInteractiveModification.InteractiveBigIntegerModification
getStandardInteractiveModification() {
return standardInteractiveModification;
}
@@ -130,16 +158,19 @@ public static VariableModification interactive() {
public static synchronized List> modificationsFromFile() {
try {
if (modificationsFromFile == null) {
- modificationsFromFile = new LinkedList<>();
+ modificationsFromFile = new ArrayList<>();
ClassLoader classLoader = ByteArrayModificationFactory.class.getClassLoader();
- InputStream is =
- classLoader.getResourceAsStream(IntegerModificationFactory.FILE_NAME);
+ InputStream is = classLoader.getResourceAsStream(LongModificationFactory.FILE_NAME);
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
+ int index = 0;
while ((line = br.readLine()) != null) {
String value = line.trim().split(" ")[0];
- if (!value.equals("")) {
- modificationsFromFile.add(explicitValue(value));
+ if (!value.isEmpty()) {
+ modificationsFromFile.add(
+ new BigIntegerExplicitValueFromFileModification(
+ index, new BigInteger(value)));
+ index++;
}
}
}
@@ -152,37 +183,43 @@ public static synchronized List> modificationsF
public static VariableModification createRandomModification() {
Random random = RandomHelper.getRandom();
- int r = random.nextInt(MODIFICATION_COUNT);
+ ModificationType randomType = ModificationType.values()[random.nextInt(MODIFICATION_COUNT)];
BigInteger modification = BigInteger.valueOf(random.nextInt(MAX_MODIFICATION_VALUE));
+ BigInteger insert_modification =
+ BigInteger.valueOf(random.nextInt(MAX_MODIFICATION_INSERT_VALUE));
int shiftModification = random.nextInt(MAX_MODIFICATION_SHIFT_VALUE);
- VariableModification vm = null;
- switch (r) {
- case 0:
- vm = new BigIntegerAddModification(modification);
- return vm;
- case 1:
- vm = new BigIntegerSubtractModification(modification);
- return vm;
- case 2:
- vm = new BigIntegerXorModification(modification);
- return vm;
- case 3:
- vm = new BigIntegerExplicitValueModification(modification);
- return vm;
- case 4:
- vm = new BigIntegerShiftLeftModification(shiftModification);
- return vm;
- case 5:
- vm = new BigIntegerShiftRightModification(shiftModification);
- return vm;
- case 6:
- vm = explicitValueFromFile(MAX_MODIFICATION_VALUE);
- return vm;
- default: // unreachable but included for checkstyle
- vm = explicitValueFromFile(MAX_MODIFICATION_VALUE);
- return vm;
+ switch (randomType) {
+ case ADD:
+ return new BigIntegerAddModification(modification);
+ case SUBTRACT:
+ return new BigIntegerSubtractModification(modification);
+ case MULTIPLY:
+ return new BigIntegerMultiplyModification(
+ BigInteger.valueOf(random.nextInt(MAX_MODIFICATION_MULTIPLY_VALUE)));
+ case XOR:
+ return new BigIntegerXorModification(modification);
+ case EXPLICIT:
+ return new BigIntegerExplicitValueModification(modification);
+ case SHIFT_LEFT:
+ return new BigIntegerShiftLeftModification(shiftModification);
+ case SHIFT_RIGHT:
+ return new BigIntegerShiftRightModification(shiftModification);
+ case EXPLICIT_FROM_FILE:
+ return explicitValueFromFile(MAX_FILE_ENTRIES);
+ case APPEND:
+ return new BigIntegerAppendValueModification(insert_modification);
+ case INSERT:
+ return new BigIntegerInsertValueModification(
+ insert_modification,
+ random.nextInt(MAX_MODIFICATION_INSERT_POSITION_VALUE));
+ case PREPEND:
+ return new BigIntegerPrependValueModification(insert_modification);
+ default:
+ throw new IllegalStateException("Unexpected modification type: " + randomType);
}
}
- private BigIntegerModificationFactory() {}
+ private BigIntegerModificationFactory() {
+ super();
+ }
}
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 3faeb0c6..93a732e5 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerMultiplyModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerMultiplyModification.java
@@ -25,18 +25,28 @@ public class BigIntegerMultiplyModification extends VariableModification getModifiedCopy() {
@Override
public int hashCode() {
- int hash = 5;
- hash = 61 * hash + Objects.hashCode(this.factor);
+ int hash = 7;
+ hash = 31 * hash + factor.hashCode();
return hash;
}
@@ -71,10 +81,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final BigIntegerMultiplyModification other = (BigIntegerMultiplyModification) obj;
- if (!Objects.equals(this.factor, other.factor)) {
- return false;
- }
- return true;
+ BigIntegerMultiplyModification other = (BigIntegerMultiplyModification) obj;
+ return Objects.equals(factor, other.factor);
+ }
+
+ @Override
+ public String toString() {
+ return "BigIntegerMultiplyModification{" + "factor=" + factor + '}';
}
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerPrependValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerPrependValueModification.java
new file mode 100644
index 00000000..d9e2fe1a
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerPrependValueModification.java
@@ -0,0 +1,95 @@
+/*
+ * 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.biginteger;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.math.BigInteger;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"prependValue", "modificationFilter"})
+@XmlAccessorType(XmlAccessType.FIELD)
+public class BigIntegerPrependValueModification extends VariableModification {
+
+ private static final int MAX_PREPEND_LENGTH = 8;
+
+ private BigInteger prependValue;
+
+ public BigIntegerPrependValueModification() {
+ super();
+ }
+
+ public BigIntegerPrependValueModification(BigInteger prependValue) {
+ super();
+ this.prependValue = prependValue;
+ }
+
+ public BigIntegerPrependValueModification(BigIntegerPrependValueModification other) {
+ super(other);
+ prependValue = other.prependValue;
+ }
+
+ @Override
+ public BigIntegerPrependValueModification createCopy() {
+ return new BigIntegerPrependValueModification(this);
+ }
+
+ @Override
+ protected BigInteger modifyImplementationHook(BigInteger input) {
+ if (input == null) {
+ input = BigInteger.ZERO;
+ }
+ return prependValue.shiftLeft(input.bitLength()).or(input);
+ }
+
+ public BigInteger getPrependValue() {
+ return prependValue;
+ }
+
+ public void setPrependValue(BigInteger prependValue) {
+ this.prependValue = prependValue;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ return new BigIntegerPrependValueModification(
+ prependValue.add(new BigInteger(MAX_PREPEND_LENGTH, new Random())));
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + prependValue.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ BigIntegerPrependValueModification other = (BigIntegerPrependValueModification) obj;
+ return Objects.equals(prependValue, other.prependValue);
+ }
+
+ @Override
+ public String toString() {
+ return "BigIntegerPrependValueModification{" + "prependValue=" + prependValue + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModification.java b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModification.java
index f07cddd7..77a9295f 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModification.java
@@ -24,12 +24,25 @@ public class BigIntegerShiftLeftModification extends VariableModification getModifiedCopy() {
@Override
public int hashCode() {
int hash = 7;
- hash = 97 * hash + this.shift;
+ hash = 31 * hash + shift;
return hash;
}
@@ -69,10 +82,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final BigIntegerShiftLeftModification other = (BigIntegerShiftLeftModification) obj;
- if (this.shift != other.shift) {
- return false;
- }
- return true;
+ BigIntegerShiftLeftModification other = (BigIntegerShiftLeftModification) obj;
+ return shift == other.shift;
+ }
+
+ @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 78443aa5..0d142373 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftRightModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftRightModification.java
@@ -24,12 +24,25 @@ public class BigIntegerShiftRightModification extends VariableModification getModifiedCopy() {
@Override
public int hashCode() {
int hash = 7;
- hash = 97 * hash + this.shift;
+ hash = 31 * hash + shift;
return hash;
}
@@ -69,10 +82,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final BigIntegerShiftRightModification other = (BigIntegerShiftRightModification) obj;
- if (this.shift != other.shift) {
- return false;
- }
- return true;
+ BigIntegerShiftRightModification other = (BigIntegerShiftRightModification) obj;
+ return shift == other.shift;
+ }
+
+ @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 11fa6703..f07e4fb0 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerSubtractModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerSubtractModification.java
@@ -25,10 +25,23 @@ public class BigIntegerSubtractModification extends VariableModification getModifiedCopy() {
@Override
public int hashCode() {
- int hash = 5;
- hash = 61 * hash + Objects.hashCode(this.subtrahend);
+ int hash = 7;
+ hash = 31 * hash + subtrahend.hashCode();
return hash;
}
@@ -71,10 +84,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final BigIntegerSubtractModification other = (BigIntegerSubtractModification) obj;
- if (!Objects.equals(this.subtrahend, other.subtrahend)) {
- return false;
- }
- return true;
+ BigIntegerSubtractModification other = (BigIntegerSubtractModification) obj;
+ return Objects.equals(subtrahend, other.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 064f6f85..c3d67759 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerXorModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerXorModification.java
@@ -25,10 +25,23 @@ public class BigIntegerXorModification extends VariableModification
private BigInteger xor;
- public BigIntegerXorModification() {}
+ public BigIntegerXorModification() {
+ super();
+ }
+
+ public BigIntegerXorModification(BigInteger xor) {
+ super();
+ this.xor = xor;
+ }
+
+ public BigIntegerXorModification(BigIntegerXorModification other) {
+ super(other);
+ xor = other.xor;
+ }
- public BigIntegerXorModification(BigInteger bi) {
- this.xor = bi;
+ @Override
+ public BigIntegerXorModification createCopy() {
+ return new BigIntegerXorModification(this);
}
@Override
@@ -55,7 +68,7 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
int hash = 7;
- hash = 97 * hash + Objects.hashCode(this.xor);
+ hash = 31 * hash + xor.hashCode();
return hash;
}
@@ -70,10 +83,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final BigIntegerXorModification other = (BigIntegerXorModification) obj;
- if (!Objects.equals(this.xor, other.xor)) {
- return false;
- }
- return true;
+ BigIntegerXorModification other = (BigIntegerXorModification) obj;
+ return Objects.equals(xor, other.xor);
+ }
+
+ @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 c9ab1e89..0788cdcf 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/biginteger/ModifiableBigInteger.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/biginteger/ModifiableBigInteger.java
@@ -21,8 +21,27 @@ public class ModifiableBigInteger extends ModifiableVariable {
private BigInteger originalValue;
+ public ModifiableBigInteger() {
+ super();
+ }
+
+ public ModifiableBigInteger(BigInteger originalValue) {
+ super();
+ this.originalValue = originalValue;
+ }
+
+ public ModifiableBigInteger(ModifiableBigInteger other) {
+ super(other);
+ originalValue = other.originalValue;
+ }
+
+ @Override
+ public ModifiableBigInteger createCopy() {
+ return new ModifiableBigInteger(this);
+ }
+
@Override
- protected void createRandomModification() {
+ public void setRandomModification() {
VariableModification vm =
BigIntegerModificationFactory.createRandomModification();
setModification(vm);
@@ -38,7 +57,7 @@ public void setAssertEquals(BigInteger assertEquals) {
@Override
public boolean isOriginalValueModified() {
- return getOriginalValue() != null && (getOriginalValue().compareTo(getValue()) != 0);
+ return originalValue != null && originalValue.compareTo(getValue()) != 0;
}
public byte[] getByteArray() {
@@ -52,9 +71,7 @@ public byte[] getByteArray(int size) {
@Override
public boolean validateAssertions() {
if (assertEquals != null) {
- if (assertEquals.compareTo(getValue()) != 0) {
- return false;
- }
+ return assertEquals.compareTo(getValue()) == 0;
}
return true;
}
@@ -71,19 +88,19 @@ public void setOriginalValue(BigInteger originalValue) {
@Override
public String toString() {
- return "ModifiableBigInteger{" + "originalValue=" + originalValue + '}';
+ return "ModifiableBigInteger{" + "originalValue=" + originalValue + innerToString() + '}';
}
@Override
- public boolean equals(Object o) {
- if (this == o) {
+ public boolean equals(Object obj) {
+ if (this == obj) {
return true;
}
- if (!(o instanceof ModifiableBigInteger)) {
+ if (!(obj instanceof ModifiableBigInteger)) {
return false;
}
- ModifiableBigInteger that = (ModifiableBigInteger) o;
+ ModifiableBigInteger that = (ModifiableBigInteger) obj;
return getValue() != null ? getValue().equals(that.getValue()) : that.getValue() == null;
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanExplicitValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanExplicitValueModification.java
index d253c44e..123d95f4 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanExplicitValueModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanExplicitValueModification.java
@@ -17,14 +17,27 @@ public class BooleanExplicitValueModification extends VariableModification getModifiedCopy() {
@Override
public int hashCode() {
int hash = 7;
- hash = 29 * hash + (this.explicitValue ? 1 : 0);
+ hash = 31 * hash + (explicitValue ? 1231 : 1237);
return hash;
}
@@ -59,11 +72,8 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final BooleanExplicitValueModification other = (BooleanExplicitValueModification) obj;
- if (this.explicitValue != other.explicitValue) {
- return false;
- }
- return true;
+ BooleanExplicitValueModification other = (BooleanExplicitValueModification) obj;
+ return explicitValue == other.explicitValue;
}
@Override
diff --git a/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanModificationFactory.java b/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanModificationFactory.java
index 0a3c2a9e..653d6ddb 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanModificationFactory.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanModificationFactory.java
@@ -11,21 +11,32 @@
import de.rub.nds.modifiablevariable.util.RandomHelper;
import java.util.Random;
-public class BooleanModificationFactory {
+public final class BooleanModificationFactory {
- private static final int MODIFICATION_COUNT = 3;
+ private BooleanModificationFactory() {
+ super();
+ }
+
+ private enum ModificationType {
+ EXPLICIT_TRUE,
+ EXPLICIT_FALSE,
+ TOGGLE
+ }
+
+ private static final int MODIFICATION_COUNT = ModificationType.values().length;
public static VariableModification createRandomModification() {
Random random = RandomHelper.getRandom();
- switch (random.nextInt(MODIFICATION_COUNT)) {
- case 0:
+ ModificationType randomType = ModificationType.values()[random.nextInt(MODIFICATION_COUNT)];
+ switch (randomType) {
+ case EXPLICIT_TRUE:
return new BooleanExplicitValueModification(true);
- case 1:
+ case EXPLICIT_FALSE:
return new BooleanExplicitValueModification(false);
- case 2:
+ case TOGGLE:
return new BooleanToggleModification();
default:
- return null;
+ throw new IllegalStateException("Unexpected modification type: " + randomType);
}
}
@@ -33,7 +44,7 @@ public static VariableModification toggle() {
return new BooleanToggleModification();
}
- public static VariableModification explicitValue(final boolean explicitValue) {
+ public static VariableModification explicitValue(boolean explicitValue) {
return new BooleanExplicitValueModification(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 aee21384..34ad7608 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanToggleModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/bool/BooleanToggleModification.java
@@ -12,10 +12,21 @@
import jakarta.xml.bind.annotation.XmlType;
@XmlRootElement
-@XmlType(propOrder = {"modificationFilter"})
+@XmlType(propOrder = "modificationFilter")
public class BooleanToggleModification extends VariableModification {
- public BooleanToggleModification() {}
+ public BooleanToggleModification() {
+ super();
+ }
+
+ public BooleanToggleModification(BooleanToggleModification other) {
+ super(other);
+ }
+
+ @Override
+ public BooleanToggleModification createCopy() {
+ return new BooleanToggleModification(this);
+ }
@Override
protected Boolean modifyImplementationHook(Boolean input) {
@@ -32,8 +43,7 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
- int hash = 7;
- return hash;
+ return 7;
}
@Override
@@ -44,10 +54,7 @@ public boolean equals(Object obj) {
if (obj == null) {
return false;
}
- if (getClass() != obj.getClass()) {
- return false;
- }
- return true;
+ return getClass() == obj.getClass();
}
@Override
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 9dc3fc21..b6c2e97c 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/bool/ModifiableBoolean.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/bool/ModifiableBoolean.java
@@ -19,12 +19,25 @@ public class ModifiableBoolean extends ModifiableVariable {
private Boolean originalValue;
- public ModifiableBoolean() {}
+ public ModifiableBoolean() {
+ super();
+ }
public ModifiableBoolean(Boolean originalValue) {
+ super();
this.originalValue = originalValue;
}
+ public ModifiableBoolean(ModifiableBoolean other) {
+ super(other);
+ originalValue = other.originalValue;
+ }
+
+ @Override
+ public ModifiableBoolean createCopy() {
+ return new ModifiableBoolean(this);
+ }
+
@Override
public Boolean getOriginalValue() {
return originalValue;
@@ -36,41 +49,39 @@ public void setOriginalValue(Boolean originalValue) {
}
@Override
- protected void createRandomModification() {
+ public void setRandomModification() {
VariableModification vm = BooleanModificationFactory.createRandomModification();
setModification(vm);
}
@Override
public boolean isOriginalValueModified() {
- return getOriginalValue() != null && (getOriginalValue().compareTo(getValue()) != 0);
+ return originalValue != null && originalValue.compareTo(getValue()) != 0;
}
@Override
public boolean validateAssertions() {
if (assertEquals != null) {
- if (assertEquals.compareTo(getValue()) != 0) {
- return false;
- }
+ return assertEquals.compareTo(getValue()) == 0;
}
return true;
}
@Override
public String toString() {
- return "ModifiableBoolean{" + "originalValue=" + originalValue + '}';
+ return "ModifiableBoolean{" + "originalValue=" + originalValue + innerToString() + '}';
}
@Override
- public boolean equals(Object o) {
- if (this == o) {
+ public boolean equals(Object obj) {
+ if (this == obj) {
return true;
}
- if (!(o instanceof ModifiableBoolean)) {
+ if (!(obj instanceof ModifiableBoolean)) {
return false;
}
- ModifiableBoolean that = (ModifiableBoolean) o;
+ ModifiableBoolean that = (ModifiableBoolean) obj;
return getValue() != null ? getValue().equals(that.getValue()) : that.getValue() == null;
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayAppendValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayAppendValueModification.java
new file mode 100644
index 00000000..78eb3d2e
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayAppendValueModification.java
@@ -0,0 +1,105 @@
+/*
+ * 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.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.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import java.util.Arrays;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"bytesToAppend", "modificationFilter"})
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ByteArrayAppendValueModification extends VariableModification {
+
+ private static final int MAX_EXPLICIT_VALUE = 256;
+
+ @XmlJavaTypeAdapter(UnformattedByteArrayAdapter.class)
+ private byte[] bytesToAppend;
+
+ public ByteArrayAppendValueModification() {
+ super();
+ }
+
+ public ByteArrayAppendValueModification(byte[] bytesToAppend) {
+ super();
+ this.bytesToAppend = bytesToAppend;
+ }
+
+ public ByteArrayAppendValueModification(ByteArrayAppendValueModification other) {
+ super(other);
+ bytesToAppend = other.bytesToAppend != null ? other.bytesToAppend.clone() : null;
+ }
+
+ @Override
+ public ByteArrayAppendValueModification createCopy() {
+ return new ByteArrayAppendValueModification(this);
+ }
+
+ @Override
+ protected byte[] modifyImplementationHook(byte[] input) {
+ if (input == null) {
+ input = new byte[0];
+ }
+
+ return ArrayConverter.concatenate(input, bytesToAppend);
+ }
+
+ public byte[] getBytesToAppend() {
+ return bytesToAppend;
+ }
+
+ public void setBytesToAppend(byte[] bytesToAppend) {
+ this.bytesToAppend = bytesToAppend;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+
+ int index = r.nextInt(bytesToAppend.length);
+ byte[] newValue = Arrays.copyOf(bytesToAppend, bytesToAppend.length);
+ newValue[index] = (byte) r.nextInt(MAX_EXPLICIT_VALUE);
+ return new ByteArrayAppendValueModification(newValue);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + Arrays.hashCode(bytesToAppend);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ByteArrayAppendValueModification other = (ByteArrayAppendValueModification) obj;
+ return Arrays.equals(bytesToAppend, other.bytesToAppend);
+ }
+
+ @Override
+ public String toString() {
+ return "ByteArrayInsertModification{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 c2e96dae..88b25d5f 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayDeleteModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayDeleteModification.java
@@ -7,8 +7,6 @@
*/
package de.rub.nds.modifiablevariable.bytearray;
-import static de.rub.nds.modifiablevariable.util.ArrayConverter.bytesToHexString;
-
import de.rub.nds.modifiablevariable.VariableModification;
import de.rub.nds.modifiablevariable.util.ArrayConverter;
import jakarta.xml.bind.annotation.XmlAccessType;
@@ -29,44 +27,52 @@ public class ByteArrayDeleteModification extends VariableModification {
private int startPosition;
- public ByteArrayDeleteModification() {}
+ public ByteArrayDeleteModification() {
+ super();
+ }
public ByteArrayDeleteModification(int startPosition, int count) {
+ super();
this.startPosition = startPosition;
this.count = count;
}
+ public ByteArrayDeleteModification(ByteArrayDeleteModification other) {
+ super(other);
+ count = other.count;
+ startPosition = other.startPosition;
+ }
+
+ @Override
+ public ByteArrayDeleteModification createCopy() {
+ return new ByteArrayDeleteModification(this);
+ }
+
@Override
protected byte[] modifyImplementationHook(byte[] input) {
if (input == null) {
input = new byte[0];
}
- int start = startPosition;
- if (start < 0) {
- start += input.length;
- if (start < 0) {
- LOGGER.debug(
- "Trying to delete from too negative Startposition. start = "
- + (start - input.length));
- return input;
- }
- }
- final int endPosition = start + count;
- if ((endPosition) > input.length) {
- LOGGER.debug(
- String.format(
- "Bytes %d..%d cannot be deleted from {%s} of length %d",
- start, endPosition, bytesToHexString(input), input.length));
+ if (input.length == 0) {
return input;
}
- if (count <= 0) {
- LOGGER.debug("You must delete at least one byte. count = " + count);
- return input;
+
+ // Wrap around and also allow to delete at the end of the original value
+ int deleteStartPosition = startPosition % input.length;
+ if (startPosition < 0) {
+ deleteStartPosition += input.length - 1;
+ }
+
+ // If the end position overflows, it is fixed at the end of the byte array
+ int deleteEndPosition = deleteStartPosition + Math.max(0, count);
+ if (deleteEndPosition > input.length) {
+ deleteEndPosition = input.length;
}
- byte[] ret1 = Arrays.copyOf(input, start);
+
+ byte[] ret1 = Arrays.copyOf(input, deleteStartPosition);
byte[] ret2 = null;
- if ((endPosition) < input.length) {
- ret2 = Arrays.copyOfRange(input, endPosition, input.length);
+ if (deleteEndPosition < input.length) {
+ ret2 = Arrays.copyOfRange(input, deleteEndPosition, input.length);
}
return ArrayConverter.concatenate(ret1, ret2);
}
@@ -112,8 +118,8 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
int hash = 7;
- hash = 89 * hash + this.count;
- hash = 89 * hash + this.startPosition;
+ hash = 31 * hash + count;
+ hash = 31 * hash + startPosition;
return hash;
}
@@ -128,14 +134,11 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final ByteArrayDeleteModification other = (ByteArrayDeleteModification) obj;
- if (this.count != other.count) {
- return false;
- }
- if (this.startPosition != other.startPosition) {
+ ByteArrayDeleteModification other = (ByteArrayDeleteModification) obj;
+ if (count != other.count) {
return false;
}
- return true;
+ return startPosition == other.startPosition;
}
@Override
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 697837d2..b919fccf 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayDuplicateModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayDuplicateModification.java
@@ -15,11 +15,22 @@
import jakarta.xml.bind.annotation.XmlType;
@XmlRootElement
-@XmlType(propOrder = {"modificationFilter"})
+@XmlType(propOrder = "modificationFilter")
@XmlAccessorType(XmlAccessType.FIELD)
public class ByteArrayDuplicateModification extends VariableModification {
- public ByteArrayDuplicateModification() {}
+ public ByteArrayDuplicateModification() {
+ super();
+ }
+
+ public ByteArrayDuplicateModification(ByteArrayDuplicateModification other) {
+ super(other);
+ }
+
+ @Override
+ public ByteArrayDuplicateModification createCopy() {
+ return new ByteArrayDuplicateModification(this);
+ }
@Override
protected byte[] modifyImplementationHook(byte[] input) {
@@ -36,8 +47,7 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
- int hash = 7;
- return hash;
+ return 7;
}
@Override
@@ -48,10 +58,7 @@ public boolean equals(Object obj) {
if (obj == null) {
return false;
}
- if (getClass() != obj.getClass()) {
- return false;
- }
- return true;
+ return getClass() == obj.getClass();
}
@Override
diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayExplicitValueFromFileModification.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayExplicitValueFromFileModification.java
new file mode 100644
index 00000000..f303e922
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayExplicitValueFromFileModification.java
@@ -0,0 +1,90 @@
+/*
+ * 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.bytearray;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import de.rub.nds.modifiablevariable.util.ArrayConverter;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Arrays;
+
+@XmlRootElement
+@XmlType(propOrder = "index")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ByteArrayExplicitValueFromFileModification extends ByteArrayExplicitValueModification {
+ private int index;
+
+ public ByteArrayExplicitValueFromFileModification() {
+ super();
+ }
+
+ public ByteArrayExplicitValueFromFileModification(int index, byte[] explicitValue) {
+ super(explicitValue);
+ this.index = index;
+ }
+
+ public ByteArrayExplicitValueFromFileModification(
+ ByteArrayExplicitValueFromFileModification other) {
+ super(other);
+ index = other.index;
+ }
+
+ @Override
+ public ByteArrayExplicitValueFromFileModification createCopy() {
+ return new ByteArrayExplicitValueFromFileModification(this);
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ throw new UnsupportedOperationException(
+ "Cannot set modify Value of ByteArrayExplicitValueFromFileModification");
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + index;
+ hash = 31 * hash + Arrays.hashCode(explicitValue);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ByteArrayExplicitValueFromFileModification other =
+ (ByteArrayExplicitValueFromFileModification) obj;
+ if (index != other.index) {
+ return false;
+ }
+ return Arrays.equals(explicitValue, other.explicitValue);
+ }
+
+ @Override
+ public String toString() {
+ return "ByteArrayExplicitValueFromFileModification{"
+ + "index="
+ + index
+ + ", explicitValue="
+ + ArrayConverter.bytesToHexString(explicitValue)
+ + '}';
+ }
+}
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 85c5d8e5..83fca1b1 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayExplicitValueModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayExplicitValueModification.java
@@ -26,16 +26,29 @@ public class ByteArrayExplicitValueModification extends VariableModification getModifiedCopy() {
@Override
public int hashCode() {
- int hash = 5;
- hash = 53 * hash + Arrays.hashCode(this.explicitValue);
+ int hash = 7;
+ hash = 31 * hash + Arrays.hashCode(explicitValue);
return hash;
}
@@ -85,10 +98,7 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final ByteArrayExplicitValueModification other = (ByteArrayExplicitValueModification) obj;
- if (!Arrays.equals(this.explicitValue, other.explicitValue)) {
- return false;
- }
- return true;
+ ByteArrayExplicitValueModification other = (ByteArrayExplicitValueModification) obj;
+ return Arrays.equals(explicitValue, other.explicitValue);
}
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayInsertModification.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayInsertValueModification.java
similarity index 66%
rename from src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayInsertModification.java
rename to src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayInsertValueModification.java
index 660d6e0c..59579e1d 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayInsertModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayInsertValueModification.java
@@ -21,52 +21,54 @@
@XmlRootElement
@XmlType(propOrder = {"bytesToInsert", "startPosition", "modificationFilter"})
@XmlAccessorType(XmlAccessType.FIELD)
-public class ByteArrayInsertModification extends VariableModification {
+public class ByteArrayInsertValueModification extends VariableModification {
private static final int MAX_EXPLICIT_VALUE = 256;
- private static final int MAX_INSERT_MODIFIER = 32;
+ private static final int MAX_POSITION_MODIFIER = 32;
@XmlJavaTypeAdapter(UnformattedByteArrayAdapter.class)
private byte[] bytesToInsert;
private int startPosition;
- public ByteArrayInsertModification() {}
+ public ByteArrayInsertValueModification() {
+ super();
+ }
- public ByteArrayInsertModification(byte[] bytesToInsert, int startPosition) {
+ public ByteArrayInsertValueModification(byte[] bytesToInsert, int startPosition) {
+ super();
this.bytesToInsert = bytesToInsert;
this.startPosition = startPosition;
}
+ public ByteArrayInsertValueModification(ByteArrayInsertValueModification other) {
+ super(other);
+ bytesToInsert = other.bytesToInsert != null ? other.bytesToInsert.clone() : null;
+ startPosition = other.startPosition;
+ }
+
+ @Override
+ public ByteArrayInsertValueModification createCopy() {
+ return new ByteArrayInsertValueModification(this);
+ }
+
@Override
protected byte[] modifyImplementationHook(byte[] input) {
if (input == null) {
input = new byte[0];
}
- int start = startPosition;
- if (start < 0) {
- start += input.length;
- if (start < 0) {
- LOGGER.debug(
- "Trying to insert from too negative Startposition. start = "
- + startPosition);
- return input;
- }
- }
- if (startPosition > input.length) {
- LOGGER.debug(
- "Trying to insert behind the Array. ArraySize:"
- + input.length
- + " Insert Position:"
- + startPosition);
- return input;
+ // Wrap around and also allow to insert at the end of the original value
+ int insertPosition = startPosition % (input.length + 1);
+ if (startPosition < 0) {
+ insertPosition += input.length;
}
- byte[] ret1 = Arrays.copyOf(input, start);
+
+ byte[] ret1 = Arrays.copyOf(input, insertPosition);
byte[] ret3 = null;
- if ((start) < input.length) {
- ret3 = Arrays.copyOfRange(input, start, input.length);
+ if (insertPosition < input.length) {
+ ret3 = Arrays.copyOfRange(input, insertPosition, input.length);
}
return ArrayConverter.concatenate(ret1, bytesToInsert, ret3);
}
@@ -95,10 +97,10 @@ public VariableModification getModifiedCopy() {
int index = r.nextInt(bytesToInsert.length);
byte[] newValue = Arrays.copyOf(bytesToInsert, bytesToInsert.length);
newValue[index] = (byte) r.nextInt(MAX_EXPLICIT_VALUE);
- return new ByteArrayInsertModification(newValue, startPosition);
+ return new ByteArrayInsertValueModification(newValue, startPosition);
} else {
byte[] newValue = Arrays.copyOf(bytesToInsert, bytesToInsert.length);
- int modifier = r.nextInt(MAX_INSERT_MODIFIER);
+ int modifier = r.nextInt(MAX_POSITION_MODIFIER);
if (r.nextBoolean()) {
modifier *= -1;
}
@@ -106,15 +108,15 @@ public VariableModification getModifiedCopy() {
if (modifier <= 0) {
modifier = 1;
}
- return new ByteArrayInsertModification(newValue, modifier);
+ return new ByteArrayInsertValueModification(newValue, modifier);
}
}
@Override
public int hashCode() {
int hash = 7;
- hash = 59 * hash + Arrays.hashCode(this.bytesToInsert);
- hash = 59 * hash + this.startPosition;
+ hash = 31 * hash + Arrays.hashCode(bytesToInsert);
+ hash = 31 * hash + startPosition;
return hash;
}
@@ -129,14 +131,11 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final ByteArrayInsertModification other = (ByteArrayInsertModification) obj;
- if (this.startPosition != other.startPosition) {
- return false;
- }
- if (!Arrays.equals(this.bytesToInsert, other.bytesToInsert)) {
+ ByteArrayInsertValueModification other = (ByteArrayInsertValueModification) obj;
+ if (startPosition != other.startPosition) {
return false;
}
- return true;
+ return Arrays.equals(bytesToInsert, other.bytesToInsert);
}
@Override
diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayModificationFactory.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayModificationFactory.java
index ce26299d..ee603cff 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayModificationFactory.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayModificationFactory.java
@@ -15,31 +15,29 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.util.LinkedList;
+import java.util.ArrayList;
import java.util.List;
import java.util.Random;
-public class ByteArrayModificationFactory {
-
- private static final int BYTE_ARRAY_SHUFFLE_MODIFICATION = 6;
-
- private static final int BYTE_ARRAY_EXPLICIT_VALUE_MODIFICATION_FROM_FILE = 5;
-
- private static final int BYTE_ARRAY_DUPLICATE_MODIFICATION = 4;
-
- private static final int BYTE_ARRAY_EXPLICIT_VALUE_MODIFICATION = 3;
-
- private static final int BYTE_ARRAY_DELETE_MODIFICATION = 2;
-
- private static final int BYTE_ARRAY_INSERT_MODIFICATION = 1;
-
- private static final int BYTE_ARRAY_XOR_MODIFICATION = 0;
+public final class ByteArrayModificationFactory {
+
+ private enum ModificationType {
+ XOR,
+ APPEND,
+ INSERT,
+ PREPEND,
+ DELETE,
+ EXPLICIT,
+ DUPLICATE,
+ EXPLICIT_FROM_FILE,
+ SHUFFLE
+ }
- private static final int MODIFICATION_COUNT = 7;
+ private static final int MODIFICATION_COUNT = ModificationType.values().length;
- private static final int MAX_CONFIG_PARAMETER = 200;
+ private static final int MAX_BYTE_ARRAY_LENGTH = 200;
- private static final int EXPLICIT_VALUE_RANDOM = 1000;
+ private static final int MAX_FILE_ENTRIES = 1000;
private static final int MODIFIED_ARRAY_LENGTH_ESTIMATION = 50;
@@ -52,20 +50,28 @@ public class ByteArrayModificationFactory {
* @param startPosition negative numbers mean that the position is taken from the end
* @return variable modification
*/
- public static VariableModification xor(final byte[] xor, final int startPosition) {
+ public static VariableModification xor(byte[] xor, int startPosition) {
return new ByteArrayXorModification(xor, startPosition);
}
/**
* *
*
- * @param bytesToInsert bytes to xor
+ * @param bytesToInsert bytes to insert
* @param startPosition negative numbers mean that the position is taken from the end
* @return variable modification
*/
- public static VariableModification insert(
- final byte[] bytesToInsert, final int startPosition) {
- return new ByteArrayInsertModification(bytesToInsert, startPosition);
+ public static VariableModification insertValue(
+ byte[] bytesToInsert, int startPosition) {
+ return new ByteArrayInsertValueModification(bytesToInsert, startPosition);
+ }
+
+ public static VariableModification appendValue(byte[] bytesToAppend) {
+ return new ByteArrayAppendValueModification(bytesToAppend);
+ }
+
+ public static VariableModification prependValue(byte[] bytesToPrepend) {
+ return new ByteArrayPrependValueModification(bytesToPrepend);
}
/**
@@ -75,7 +81,7 @@ public static VariableModification insert(
* @param count number of bytes to be deleted
* @return variable modification
*/
- public static VariableModification delete(final int startPosition, final int count) {
+ public static VariableModification delete(int startPosition, int count) {
return new ByteArrayDeleteModification(startPosition, count);
}
@@ -88,14 +94,13 @@ public static VariableModification duplicate() {
return new ByteArrayDuplicateModification();
}
- public static VariableModification explicitValue(final byte[] explicitValue) {
+ public static VariableModification explicitValue(byte[] explicitValue) {
return new ByteArrayExplicitValueModification(explicitValue);
}
public static VariableModification explicitValueFromFile(int value) {
List> modifications = modificationsFromFile();
- int pos = value % modifications.size();
- return modifications.get(pos);
+ return modifications.get(value % modifications.size());
}
/**
@@ -104,22 +109,25 @@ public static VariableModification explicitValueFromFile(int value) {
* @param shuffle positions that define shuffling
* @return shuffling variable modification
*/
- public static VariableModification shuffle(final byte[] shuffle) {
+ public static VariableModification shuffle(byte[] shuffle) {
return new ByteArrayShuffleModification(shuffle);
}
public static synchronized List> modificationsFromFile() {
try {
if (modificationsFromFile == null) {
- modificationsFromFile = new LinkedList<>();
+ modificationsFromFile = new ArrayList<>();
ClassLoader classLoader = ByteArrayModificationFactory.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream(FILE_NAME);
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
+ int index = 0;
while ((line = br.readLine()) != null) {
line = line.replaceAll("\\s+", "");
byte[] value = ArrayConverter.hexStringToByteArray(line);
- modificationsFromFile.add(explicitValue(value));
+ modificationsFromFile.add(
+ new ByteArrayExplicitValueFromFileModification(index, value));
+ index++;
}
}
return modificationsFromFile;
@@ -131,69 +139,62 @@ public static synchronized List> modificationsFromF
public static VariableModification createRandomModification(byte[] originalValue) {
Random random = RandomHelper.getRandom();
- int r = random.nextInt(MODIFICATION_COUNT);
- VariableModification vm = null;
+ ModificationType randomType = ModificationType.values()[random.nextInt(MODIFICATION_COUNT)];
int modifiedArrayLength;
+ int modificationArrayLength;
+ int startPosition;
if (originalValue == null) {
modifiedArrayLength = MODIFIED_ARRAY_LENGTH_ESTIMATION;
} else {
modifiedArrayLength = originalValue.length;
if (originalValue.length == 0 || originalValue.length == 1) {
- r = BYTE_ARRAY_EXPLICIT_VALUE_MODIFICATION;
+ randomType = ModificationType.EXPLICIT;
}
}
- switch (r) {
- case BYTE_ARRAY_XOR_MODIFICATION:
- int modificationArrayLength = random.nextInt(modifiedArrayLength);
- if (modificationArrayLength == 0) {
- modificationArrayLength++;
- }
+ modificationArrayLength = random.nextInt(MAX_BYTE_ARRAY_LENGTH - 1) + 1;
+ switch (randomType) {
+ case XOR:
byte[] xor = new byte[modificationArrayLength];
random.nextBytes(xor);
- int startPosition = random.nextInt(modifiedArrayLength - modificationArrayLength);
- vm = new ByteArrayXorModification(xor, startPosition);
- return vm;
- case BYTE_ARRAY_INSERT_MODIFICATION:
- modificationArrayLength = random.nextInt(MAX_CONFIG_PARAMETER);
- if (modificationArrayLength == 0) {
- modificationArrayLength++;
- }
+ startPosition = random.nextInt(modifiedArrayLength - modificationArrayLength);
+ return new ByteArrayXorModification(xor, startPosition);
+ case APPEND:
+ byte[] bytesToAppend = new byte[modificationArrayLength];
+ random.nextBytes(bytesToAppend);
+ return new ByteArrayAppendValueModification(bytesToAppend);
+ case INSERT:
byte[] bytesToInsert = new byte[modificationArrayLength];
random.nextBytes(bytesToInsert);
- int insertPosition = random.nextInt(modifiedArrayLength);
- vm = new ByteArrayInsertModification(bytesToInsert, insertPosition);
- return vm;
- case BYTE_ARRAY_DELETE_MODIFICATION:
+ return new ByteArrayInsertValueModification(
+ bytesToInsert, random.nextInt(modifiedArrayLength));
+ case PREPEND:
+ byte[] bytesToPrepend = new byte[modificationArrayLength];
+ random.nextBytes(bytesToPrepend);
+ return new ByteArrayPrependValueModification(bytesToPrepend);
+ case DELETE:
startPosition = random.nextInt(modifiedArrayLength - 1);
int count = random.nextInt(modifiedArrayLength - startPosition);
count++;
- vm = new ByteArrayDeleteModification(startPosition, count);
- return vm;
- case BYTE_ARRAY_EXPLICIT_VALUE_MODIFICATION:
- modificationArrayLength = random.nextInt(MAX_CONFIG_PARAMETER);
- if (modificationArrayLength == 0) {
- modificationArrayLength++;
- }
+ return new ByteArrayDeleteModification(startPosition, count);
+ case EXPLICIT:
byte[] explicitValue = new byte[modificationArrayLength];
random.nextBytes(explicitValue);
- vm = new ByteArrayExplicitValueModification(explicitValue);
- return vm;
- case BYTE_ARRAY_DUPLICATE_MODIFICATION:
- vm = new ByteArrayDuplicateModification();
- return vm;
- case BYTE_ARRAY_EXPLICIT_VALUE_MODIFICATION_FROM_FILE:
- vm = explicitValueFromFile(random.nextInt(EXPLICIT_VALUE_RANDOM));
- return vm;
- case BYTE_ARRAY_SHUFFLE_MODIFICATION:
- int shuffleSize = random.nextInt(MAX_CONFIG_PARAMETER);
+ return new ByteArrayExplicitValueModification(explicitValue);
+ case DUPLICATE:
+ return new ByteArrayDuplicateModification();
+ case EXPLICIT_FROM_FILE:
+ return explicitValueFromFile(random.nextInt(MAX_FILE_ENTRIES));
+ case SHUFFLE:
+ int shuffleSize = random.nextInt(MAX_BYTE_ARRAY_LENGTH);
byte[] shuffle = new byte[shuffleSize];
random.nextBytes(shuffle);
- vm = shuffle(shuffle);
- return vm;
+ return new ByteArrayShuffleModification(shuffle);
default:
- return vm;
+ throw new IllegalStateException("Unexpected modification type: " + randomType);
}
}
- private ByteArrayModificationFactory() {}
+ private ByteArrayModificationFactory() {
+ super();
+ }
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayPrependValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayPrependValueModification.java
new file mode 100644
index 00000000..7399d6ec
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayPrependValueModification.java
@@ -0,0 +1,105 @@
+/*
+ * 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.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.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import java.util.Arrays;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"bytesToPrepend", "modificationFilter"})
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ByteArrayPrependValueModification extends VariableModification {
+
+ private static final int MAX_EXPLICIT_VALUE = 256;
+
+ @XmlJavaTypeAdapter(UnformattedByteArrayAdapter.class)
+ private byte[] bytesToPrepend;
+
+ public ByteArrayPrependValueModification() {
+ super();
+ }
+
+ public ByteArrayPrependValueModification(byte[] bytesToPrepend) {
+ super();
+ this.bytesToPrepend = bytesToPrepend;
+ }
+
+ public ByteArrayPrependValueModification(ByteArrayPrependValueModification other) {
+ super(other);
+ bytesToPrepend = other.bytesToPrepend != null ? other.bytesToPrepend.clone() : null;
+ }
+
+ @Override
+ public ByteArrayPrependValueModification createCopy() {
+ return new ByteArrayPrependValueModification(this);
+ }
+
+ @Override
+ protected byte[] modifyImplementationHook(byte[] input) {
+ if (input == null) {
+ input = new byte[0];
+ }
+
+ return ArrayConverter.concatenate(bytesToPrepend, input);
+ }
+
+ public byte[] getBytesToPrepend() {
+ return bytesToPrepend;
+ }
+
+ public void setBytesToPrepend(byte[] bytesToPrepend) {
+ this.bytesToPrepend = bytesToPrepend;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+
+ int index = r.nextInt(bytesToPrepend.length);
+ byte[] newValue = Arrays.copyOf(bytesToPrepend, bytesToPrepend.length);
+ newValue[index] = (byte) r.nextInt(MAX_EXPLICIT_VALUE);
+ return new ByteArrayPrependValueModification(newValue);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + Arrays.hashCode(bytesToPrepend);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ByteArrayPrependValueModification other = (ByteArrayPrependValueModification) obj;
+ return Arrays.equals(bytesToPrepend, other.bytesToPrepend);
+ }
+
+ @Override
+ public String toString() {
+ return "ByteArrayPrependValueModification{bytesToPrepend="
+ + ArrayConverter.bytesToHexString(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 379a7354..47990150 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayShuffleModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayShuffleModification.java
@@ -32,20 +32,42 @@ public class ByteArrayShuffleModification extends VariableModification {
@XmlJavaTypeAdapter(UnformattedByteArrayAdapter.class)
private byte[] shuffle;
- public ByteArrayShuffleModification() {}
+ public ByteArrayShuffleModification() {
+ super();
+ }
public ByteArrayShuffleModification(byte[] shuffle) {
+ super();
this.shuffle = shuffle;
}
+ public ByteArrayShuffleModification(ByteArrayShuffleModification other) {
+ super(other);
+ shuffle = other.shuffle != null ? other.shuffle.clone() : null;
+ }
+
+ @Override
+ public ByteArrayShuffleModification createCopy() {
+ return new ByteArrayShuffleModification(this);
+ }
+
@Override
- protected byte[] modifyImplementationHook(final byte[] input) {
+ protected byte[] modifyImplementationHook(byte[] input) {
if (input == null) {
- return input;
+ return null;
}
byte[] result = input.clone();
int size = input.length;
- if (size != 0) {
+ 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;
@@ -71,13 +93,13 @@ public VariableModification getModifiedCopy() {
int index = r.nextInt(shuffle.length);
byte[] newValue = Arrays.copyOf(shuffle, shuffle.length);
newValue[index] = (byte) r.nextInt(MAX_MODIFIER_VALUE);
- return new ByteArrayShuffleModification(shuffle);
+ return new ByteArrayShuffleModification(newValue);
}
@Override
public int hashCode() {
- int hash = 5;
- hash = 71 * hash + Arrays.hashCode(this.shuffle);
+ int hash = 7;
+ hash = 31 * hash + Arrays.hashCode(shuffle);
return hash;
}
@@ -92,11 +114,8 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final ByteArrayShuffleModification other = (ByteArrayShuffleModification) obj;
- if (!Arrays.equals(this.shuffle, other.shuffle)) {
- return false;
- }
- return true;
+ ByteArrayShuffleModification other = (ByteArrayShuffleModification) obj;
+ return Arrays.equals(shuffle, other.shuffle);
}
@Override
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 9845db53..3471b3ea 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayXorModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ByteArrayXorModification.java
@@ -32,38 +32,53 @@ public class ByteArrayXorModification extends VariableModification {
private int startPosition;
- public ByteArrayXorModification() {}
+ public ByteArrayXorModification() {
+ super();
+ }
public ByteArrayXorModification(byte[] xor, int startPosition) {
+ super();
this.xor = xor;
this.startPosition = startPosition;
}
+ public ByteArrayXorModification(ByteArrayXorModification other) {
+ super(other);
+ xor = other.xor != null ? other.xor.clone() : null;
+ startPosition = other.startPosition;
+ }
+
+ @Override
+ public ByteArrayXorModification createCopy() {
+ return new ByteArrayXorModification(this);
+ }
+
@Override
protected byte[] modifyImplementationHook(byte[] input) {
if (input == null) {
input = new byte[0];
}
+ if (input.length == 0) {
+ return input;
+ }
byte[] result = input.clone();
- int start = startPosition;
- if (start < 0) {
- start += input.length;
+
+ // Wrap around and also allow to xor at the end of the original value
+ int xorPosition = startPosition % input.length;
+ if (startPosition < 0) {
+ xorPosition += input.length - 1;
}
- final int end = start + xor.length;
- if (end > result.length) {
- // result = new byte[end];
- // System.arraycopy(input, 0, result, 0, input.length);
- LOGGER.debug(
- "Input {{}} of length {} cannot be xor-ed with {{}} of length {} with start position {}",
- input,
- input.length,
- xor,
- xor.length,
- startPosition);
- return input;
+ int endPosition = xorPosition + xor.length;
+ if (endPosition > result.length) {
+ // Fix the end position to the length of the original value
+ // This may not match the expected behavior of a user
+ // But for fuzzing purpose, that's fine
+ // Todo: Add an option that expands the byte array instead
+ endPosition = result.length;
}
- for (int i = 0; i < xor.length; ++i) {
- result[start + i] = (byte) (input[start + i] ^ xor[i]);
+
+ for (int i = 0; i < endPosition - xorPosition; ++i) {
+ result[xorPosition + i] = (byte) (input[xorPosition + i] ^ xor[i]);
}
return result;
}
@@ -109,8 +124,8 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
int hash = 7;
- hash = 97 * hash + Arrays.hashCode(this.xor);
- hash = 97 * hash + this.startPosition;
+ hash = 31 * hash + Arrays.hashCode(xor);
+ hash = 31 * hash + startPosition;
return hash;
}
@@ -125,14 +140,11 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final ByteArrayXorModification other = (ByteArrayXorModification) obj;
- if (this.startPosition != other.startPosition) {
- return false;
- }
- if (!Arrays.equals(this.xor, other.xor)) {
+ ByteArrayXorModification other = (ByteArrayXorModification) obj;
+ if (startPosition != other.startPosition) {
return false;
}
- return true;
+ return Arrays.equals(xor, other.xor);
}
@Override
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 a0d46cb4..9601e69e 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/bytearray/ModifiableByteArray.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/bytearray/ModifiableByteArray.java
@@ -21,12 +21,30 @@
@XmlAccessorType(XmlAccessType.PROPERTY)
public class ModifiableByteArray extends ModifiableVariable {
- public ModifiableByteArray() {}
-
private byte[] originalValue;
+ public ModifiableByteArray() {
+ super();
+ }
+
+ public ModifiableByteArray(byte[] originalValue) {
+ super();
+ this.originalValue = originalValue;
+ }
+
+ public ModifiableByteArray(ModifiableByteArray other) {
+ super(other);
+ originalValue = other.originalValue != null ? other.originalValue.clone() : null;
+ assertEquals = other.assertEquals != null ? other.assertEquals.clone() : null;
+ }
+
+ @Override
+ public ModifiableByteArray createCopy() {
+ return new ModifiableByteArray(this);
+ }
+
@Override
- protected void createRandomModification() {
+ public void setRandomModification() {
VariableModification vm =
ByteArrayModificationFactory.createRandomModification(originalValue);
setModification(vm);
@@ -69,30 +87,15 @@ public boolean validateAssertions() {
}
@Override
- public String toString() {
- StringBuilder result = new StringBuilder();
- if (this.isOriginalValueModified()) {
- result.append("Actual byte value is: ");
- result.append(ArrayConverter.bytesToHexString(this));
- result.append("\nOriginal value was: ");
- result.append(ArrayConverter.bytesToHexString(this.getOriginalValue()));
- } else {
- result.append("Original byte value is: ");
- result.append(ArrayConverter.bytesToHexString(this.getOriginalValue()));
- }
- return result.toString();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
+ public boolean equals(Object obj) {
+ if (this == obj) {
return true;
}
- if (!(o instanceof ModifiableByteArray)) {
+ if (!(obj instanceof ModifiableByteArray)) {
return false;
}
- ModifiableByteArray that = (ModifiableByteArray) o;
+ ModifiableByteArray that = (ModifiableByteArray) obj;
return Arrays.equals(getValue(), that.getValue());
}
@@ -103,4 +106,13 @@ public int hashCode() {
result = 31 * result + Arrays.hashCode(getValue());
return result;
}
+
+ @Override
+ public String toString() {
+ return "ModifiableByteArray{"
+ + "originalValue="
+ + ArrayConverter.bytesToHexString(originalValue)
+ + innerToString()
+ + '}';
+ }
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/filter/AccessModificationFilter.java b/src/main/java/de/rub/nds/modifiablevariable/filter/AccessModificationFilter.java
index 02daf06f..cbf940ac 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/filter/AccessModificationFilter.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/filter/AccessModificationFilter.java
@@ -29,14 +29,27 @@ public class AccessModificationFilter extends ModificationFilter {
private int[] accessNumbers;
public AccessModificationFilter() {
+ super();
accessCounter = 1;
}
- public AccessModificationFilter(final int[] accessNumbers) {
+ public AccessModificationFilter(int[] accessNumbers) {
+ super();
accessCounter = 1;
this.accessNumbers = accessNumbers;
}
+ public AccessModificationFilter(AccessModificationFilter other) {
+ super(other);
+ accessCounter = other.accessCounter;
+ accessNumbers = other.accessNumbers != null ? other.accessNumbers.clone() : null;
+ }
+
+ @Override
+ public AccessModificationFilter createCopy() {
+ return new AccessModificationFilter(this);
+ }
+
@Override
public boolean filterModification() {
boolean filter = contains(accessNumbers, accessCounter);
@@ -44,7 +57,7 @@ public boolean filterModification() {
return filter;
}
- private boolean contains(int[] numbers, int number) {
+ private static boolean contains(int[] numbers, int number) {
for (int i : numbers) {
if (i == number) {
return true;
diff --git a/src/main/java/de/rub/nds/modifiablevariable/filter/ModificationFilterFactory.java b/src/main/java/de/rub/nds/modifiablevariable/filter/ModificationFilterFactory.java
index db70b67f..66a46b03 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/filter/ModificationFilterFactory.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/filter/ModificationFilterFactory.java
@@ -7,11 +7,13 @@
*/
package de.rub.nds.modifiablevariable.filter;
-public class ModificationFilterFactory {
+public final class ModificationFilterFactory {
- public static AccessModificationFilter access(final int[] accessNumbers) {
+ public static AccessModificationFilter access(int[] accessNumbers) {
return new AccessModificationFilter(accessNumbers);
}
- private ModificationFilterFactory() {}
+ private ModificationFilterFactory() {
+ super();
+ }
}
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 eb466c99..d0e24a60 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerAddModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerAddModification.java
@@ -21,15 +21,28 @@ public class IntegerAddModification extends VariableModification {
private Integer summand;
- public IntegerAddModification() {}
+ public IntegerAddModification() {
+ super();
+ }
+
+ public IntegerAddModification(Integer summand) {
+ super();
+ this.summand = summand;
+ }
+
+ public IntegerAddModification(IntegerAddModification other) {
+ super(other);
+ summand = other.summand;
+ }
- public IntegerAddModification(Integer bi) {
- this.summand = bi;
+ @Override
+ public IntegerAddModification createCopy() {
+ return new IntegerAddModification(this);
}
@Override
protected Integer modifyImplementationHook(Integer input) {
- return (input == null) ? summand : input + summand;
+ return input == null ? summand : input + summand;
}
public Integer getSummand() {
@@ -47,8 +60,8 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
- int hash = 3;
- hash = 23 * hash + Objects.hashCode(this.summand);
+ int hash = 7;
+ hash = 31 * hash + summand;
return hash;
}
@@ -63,10 +76,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final IntegerAddModification other = (IntegerAddModification) obj;
- if (!Objects.equals(this.summand, other.summand)) {
- return false;
- }
- return true;
+ IntegerAddModification other = (IntegerAddModification) obj;
+ return Objects.equals(summand, other.summand);
+ }
+
+ @Override
+ public String toString() {
+ return "IntegerAddModification{" + "summand=" + summand + '}';
}
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerAppendValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerAppendValueModification.java
new file mode 100644
index 00000000..1f4729ab
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerAppendValueModification.java
@@ -0,0 +1,91 @@
+/*
+ * 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.integer;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"appendValue", "modificationFilter"})
+public class IntegerAppendValueModification extends VariableModification {
+
+ private static final int MAX_VALUE_MODIFIER = 256;
+
+ private Integer appendValue;
+
+ public IntegerAppendValueModification() {
+ super();
+ }
+
+ public IntegerAppendValueModification(Integer appendValue) {
+ super();
+ this.appendValue = appendValue;
+ }
+
+ public IntegerAppendValueModification(IntegerAppendValueModification other) {
+ super(other);
+ appendValue = other.appendValue;
+ }
+
+ @Override
+ public IntegerAppendValueModification createCopy() {
+ return new IntegerAppendValueModification(this);
+ }
+
+ @Override
+ protected Integer modifyImplementationHook(Integer input) {
+ if (input == null) {
+ input = 0;
+ }
+ return input << Integer.SIZE - Integer.numberOfLeadingZeros(appendValue) | appendValue;
+ }
+
+ public Integer getAppendValue() {
+ return appendValue;
+ }
+
+ public void setAppendValue(Integer appendValue) {
+ this.appendValue = appendValue;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ return new IntegerAppendValueModification(
+ appendValue + new Random().nextInt(MAX_VALUE_MODIFIER));
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + appendValue;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ IntegerAppendValueModification other = (IntegerAppendValueModification) obj;
+ return Objects.equals(appendValue, other.appendValue);
+ }
+
+ @Override
+ public String toString() {
+ return "IntegerAppendValueModification{" + "appendValue=" + appendValue + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerExplicitValueFromFileModification.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerExplicitValueFromFileModification.java
new file mode 100644
index 00000000..f8affaed
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerExplicitValueFromFileModification.java
@@ -0,0 +1,89 @@
+/*
+ * 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.integer;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+
+@XmlRootElement
+@XmlType(propOrder = "index")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class IntegerExplicitValueFromFileModification extends IntegerExplicitValueModification {
+ private int index;
+
+ public IntegerExplicitValueFromFileModification() {
+ super();
+ }
+
+ public IntegerExplicitValueFromFileModification(int index, Integer explicitValue) {
+ super(explicitValue);
+ this.index = index;
+ }
+
+ public IntegerExplicitValueFromFileModification(
+ IntegerExplicitValueFromFileModification other) {
+ super(other);
+ index = other.index;
+ }
+
+ @Override
+ public IntegerExplicitValueFromFileModification createCopy() {
+ return new IntegerExplicitValueFromFileModification(this);
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ throw new UnsupportedOperationException(
+ "Cannot set modify Value of IntegerExplicitValueFromFileModification");
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + index;
+ hash = 31 * hash + explicitValue.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ IntegerExplicitValueFromFileModification other =
+ (IntegerExplicitValueFromFileModification) obj;
+ if (index != other.index) {
+ return false;
+ }
+ return Objects.equals(explicitValue, other.explicitValue);
+ }
+
+ @Override
+ public String toString() {
+ return "IntegerExplicitValueFromFileModification{"
+ + "index="
+ + index
+ + ", explicitValue="
+ + explicitValue
+ + '}';
+ }
+}
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 5b5e4db7..10d5e6f1 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerExplicitValueModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerExplicitValueModification.java
@@ -19,16 +19,29 @@ public class IntegerExplicitValueModification extends VariableModification getModifiedCopy() {
@Override
public int hashCode() {
int hash = 7;
- hash = 53 * hash + Objects.hashCode(this.explicitValue);
+ hash = 31 * hash + explicitValue;
return hash;
}
@@ -70,10 +83,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final IntegerExplicitValueModification other = (IntegerExplicitValueModification) obj;
- if (!Objects.equals(this.explicitValue, other.explicitValue)) {
- return false;
- }
- return true;
+ IntegerExplicitValueModification other = (IntegerExplicitValueModification) obj;
+ return Objects.equals(explicitValue, other.explicitValue);
+ }
+
+ @Override
+ public String toString() {
+ return "IntegerExplicitValueModification{" + "explicitValue=" + explicitValue + '}';
}
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerInsertValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerInsertValueModification.java
new file mode 100644
index 00000000..2473144b
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerInsertValueModification.java
@@ -0,0 +1,140 @@
+/*
+ * 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.integer;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"insertValue", "startPosition", "modificationFilter"})
+public class IntegerInsertValueModification extends VariableModification {
+
+ private static final int MAX_VALUE_MODIFIER = 256;
+
+ private static final int MAX_POSITION_MODIFIER = 32;
+
+ private Integer insertValue;
+
+ private int startPosition;
+
+ public IntegerInsertValueModification() {
+ super();
+ }
+
+ public IntegerInsertValueModification(Integer insertValue, int startPosition) {
+ super();
+ this.insertValue = insertValue;
+ this.startPosition = startPosition;
+ }
+
+ public IntegerInsertValueModification(IntegerInsertValueModification other) {
+ super(other);
+ insertValue = other.insertValue;
+ startPosition = other.startPosition;
+ }
+
+ @Override
+ public IntegerInsertValueModification createCopy() {
+ return new IntegerInsertValueModification(this);
+ }
+
+ @Override
+ protected Integer modifyImplementationHook(Integer input) {
+ if (input == null) {
+ input = 0;
+ }
+
+ int insertValueLength = Integer.SIZE - Integer.numberOfLeadingZeros(insertValue);
+
+ // Wrap around integer size
+ int insertPosition = startPosition % Integer.SIZE;
+ if (startPosition < 0) {
+ insertPosition += Integer.SIZE - 1;
+ }
+
+ int mask = (1 << insertPosition) - 1;
+
+ return (input >> insertPosition << insertValueLength | insertValue) << insertPosition
+ | mask & input;
+ }
+
+ public Integer getInsertValue() {
+ return insertValue;
+ }
+
+ public void setInsertValue(Integer insertValue) {
+ this.insertValue = insertValue;
+ }
+
+ public int getStartPosition() {
+ return startPosition;
+ }
+
+ public void setStartPosition(int startPosition) {
+ this.startPosition = startPosition;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+
+ if (r.nextBoolean()) {
+ return new IntegerInsertValueModification(
+ insertValue + r.nextInt(MAX_VALUE_MODIFIER), startPosition);
+ } else {
+ int modifier = r.nextInt(MAX_POSITION_MODIFIER);
+ if (r.nextBoolean()) {
+ modifier *= -1;
+ }
+ modifier = startPosition + modifier;
+ if (modifier <= 0) {
+ modifier = 1;
+ }
+ return new IntegerInsertValueModification(insertValue, modifier);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + insertValue;
+ hash = 31 * hash + startPosition;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ IntegerInsertValueModification other = (IntegerInsertValueModification) obj;
+ if (startPosition != other.startPosition) {
+ return false;
+ }
+ return Objects.equals(insertValue, other.insertValue);
+ }
+
+ @Override
+ public String toString() {
+ return "IntegerInsertValueModification{"
+ + "insertValue="
+ + insertValue
+ + ", startPosition="
+ + startPosition
+ + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerModificationFactory.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerModificationFactory.java
index 824f9f87..9acd71eb 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerModificationFactory.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerModificationFactory.java
@@ -14,87 +14,133 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.util.LinkedList;
+import java.util.ArrayList;
import java.util.List;
import java.util.Random;
-public class IntegerModificationFactory {
+public final class IntegerModificationFactory {
+
+ private enum ModificationType {
+ ADD,
+ SUBTRACT,
+ MULTIPLY,
+ XOR,
+ SWAP_ENDIAN,
+ EXPLICIT,
+ SHIFT_LEFT,
+ SHIFT_RIGHT,
+ EXPLICIT_FROM_FILE,
+ APPEND,
+ INSERT,
+ PREPEND
+ }
- private static final int MODIFICATION_COUNT = 7;
+ private static final int MODIFICATION_COUNT = ModificationType.values().length;
private static final int MAX_MODIFICATION_VALUE = 32000;
+ private static final int MAX_FILE_ENTRIES = 200;
+
private static final int MAX_MODIFICATION_SHIFT_VALUE = 20;
+ private static final int MAX_MODIFICATION_MULTIPLY_VALUE = 256;
+
+ private static final int MAX_MODIFICATION_INSERT_VALUE = 256;
+
+ private static final int MAX_MODIFICATION_INSERT_POSITION_VALUE = 32;
+
private static List> modificationsFromFile;
public static final String FILE_NAME = "de/rub/nds/modifiablevariable/explicit/integer.vec";
- public static IntegerAddModification add(final String summand) {
+ public static IntegerAddModification add(String summand) {
return add(Integer.parseInt(summand));
}
- public static IntegerAddModification add(final Integer summand) {
+ public static IntegerAddModification add(Integer summand) {
return new IntegerAddModification(summand);
}
- public static IntegerShiftLeftModification shiftLeft(final String shift) {
+ public static IntegerShiftLeftModification shiftLeft(String shift) {
return shiftLeft(Integer.parseInt(shift));
}
- public static IntegerShiftLeftModification shiftLeft(final Integer shift) {
+ public static IntegerShiftLeftModification shiftLeft(Integer shift) {
return new IntegerShiftLeftModification(shift);
}
- public static IntegerShiftRightModification shiftRight(final String shift) {
+ public static IntegerShiftRightModification shiftRight(String shift) {
return shiftRight(Integer.parseInt(shift));
}
- public static IntegerShiftRightModification shiftRight(final Integer shift) {
+ public static IntegerShiftRightModification shiftRight(Integer shift) {
return new IntegerShiftRightModification(shift);
}
- public static VariableModification sub(final String subtrahend) {
+ public static VariableModification sub(String subtrahend) {
return sub(Integer.parseInt(subtrahend));
}
- public static VariableModification sub(final Integer subtrahend) {
+ public static VariableModification sub(Integer subtrahend) {
return new IntegerSubtractModification(subtrahend);
}
- public static VariableModification xor(final String xor) {
+ public static VariableModification xor(String xor) {
return xor(Integer.parseInt(xor));
}
- public static VariableModification xor(final Integer xor) {
+ public static VariableModification xor(Integer xor) {
return new IntegerXorModification(xor);
}
- public static VariableModification explicitValue(final String value) {
+ public static VariableModification swapEndian() {
+ return new IntegerSwapEndianModification();
+ }
+
+ public static VariableModification explicitValue(String value) {
return explicitValue(Integer.parseInt(value));
}
- public static VariableModification explicitValue(final Integer value) {
+ public static VariableModification explicitValue(Integer value) {
return new IntegerExplicitValueModification(value);
}
- public static VariableModification explicitValueFromFile(int value) {
+ public static VariableModification explicitValueFromFile(int pos) {
List> modifications = modificationsFromFile();
- int pos = value % modifications.size();
- return modifications.get(pos);
+ return modifications.get(pos % modifications.size());
+ }
+
+ public static VariableModification appendValue(Integer value) {
+ return new IntegerAppendValueModification(value);
+ }
+
+ public static VariableModification insertValue(Integer value, int position) {
+ return new IntegerInsertValueModification(value, position);
+ }
+
+ public static VariableModification prependValue(Integer value) {
+ return new IntegerPrependValueModification(value);
+ }
+
+ public static VariableModification multiply(Integer value) {
+ return new IntegerMultiplyModification(value);
}
public static synchronized List> modificationsFromFile() {
try {
if (modificationsFromFile == null) {
- modificationsFromFile = new LinkedList<>();
+ modificationsFromFile = new ArrayList<>();
ClassLoader classLoader = IntegerModificationFactory.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream(FILE_NAME);
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
+ int index = 0;
while ((line = br.readLine()) != null) {
String value = line.trim().split(" ")[0];
- modificationsFromFile.add(explicitValue(value));
+ modificationsFromFile.add(
+ new IntegerExplicitValueFromFileModification(
+ index, Integer.parseInt(value)));
+ index++;
}
}
return modificationsFromFile;
@@ -106,36 +152,44 @@ public static synchronized List> modificationsFrom
public static VariableModification createRandomModification() {
Random random = RandomHelper.getRandom();
- int r = random.nextInt(MODIFICATION_COUNT);
+ ModificationType randomType = ModificationType.values()[random.nextInt(MODIFICATION_COUNT)];
int modification = random.nextInt(MAX_MODIFICATION_VALUE);
+ int insert_modification = random.nextInt(MAX_MODIFICATION_INSERT_VALUE);
int shiftModification = random.nextInt(MAX_MODIFICATION_SHIFT_VALUE);
- VariableModification vm = null;
- switch (r) {
- case 0:
- vm = new IntegerAddModification(modification);
- return vm;
- case 1:
- vm = new IntegerSubtractModification(modification);
- return vm;
- case 2:
- vm = new IntegerXorModification(modification);
- return vm;
- case 3:
- vm = new IntegerExplicitValueModification(modification);
- return vm;
- case 4:
- vm = new IntegerShiftLeftModification(shiftModification);
- return vm;
- case 5:
- vm = new IntegerShiftRightModification(shiftModification);
- return vm;
- case 6:
- vm = explicitValueFromFile(random.nextInt(MAX_MODIFICATION_VALUE));
- return vm;
+ switch (randomType) {
+ case ADD:
+ return new IntegerAddModification(modification);
+ case SUBTRACT:
+ return new IntegerSubtractModification(modification);
+ case MULTIPLY:
+ return new IntegerSubtractModification(
+ random.nextInt(MAX_MODIFICATION_MULTIPLY_VALUE));
+ case XOR:
+ return new IntegerXorModification(modification);
+ case SWAP_ENDIAN:
+ return new IntegerSwapEndianModification();
+ case EXPLICIT:
+ return new IntegerExplicitValueModification(modification);
+ case SHIFT_LEFT:
+ return new IntegerShiftLeftModification(shiftModification);
+ case SHIFT_RIGHT:
+ return new IntegerShiftRightModification(shiftModification);
+ case EXPLICIT_FROM_FILE:
+ return explicitValueFromFile(random.nextInt(MAX_FILE_ENTRIES));
+ case APPEND:
+ return new IntegerAppendValueModification(insert_modification);
+ case INSERT:
+ return new IntegerInsertValueModification(
+ insert_modification,
+ random.nextInt(MAX_MODIFICATION_INSERT_POSITION_VALUE));
+ case PREPEND:
+ return new IntegerPrependValueModification(insert_modification);
default:
- return vm;
+ throw new IllegalStateException("Unexpected modification type: " + randomType);
}
}
- private IntegerModificationFactory() {}
+ private IntegerModificationFactory() {
+ super();
+ }
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerMultiplyModification.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerMultiplyModification.java
new file mode 100644
index 00000000..0f441bba
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerMultiplyModification.java
@@ -0,0 +1,89 @@
+/*
+ * 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.integer;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"factor", "modificationFilter"})
+public class IntegerMultiplyModification extends VariableModification {
+
+ private static final int MAX_FACTOR_MODIFIER = 256;
+
+ private Integer factor;
+
+ public IntegerMultiplyModification() {
+ super();
+ }
+
+ public IntegerMultiplyModification(Integer factor) {
+ super();
+ this.factor = factor;
+ }
+
+ public IntegerMultiplyModification(IntegerMultiplyModification other) {
+ super(other);
+ factor = other.factor;
+ }
+
+ @Override
+ public IntegerMultiplyModification createCopy() {
+ return new IntegerMultiplyModification(this);
+ }
+
+ @Override
+ protected Integer modifyImplementationHook(Integer input) {
+ return input == null ? 0 : input * factor;
+ }
+
+ public Integer getFactor() {
+ return factor;
+ }
+
+ public void setFactor(Integer factor) {
+ this.factor = factor;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+
+ return new IntegerMultiplyModification(factor + r.nextInt(MAX_FACTOR_MODIFIER));
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + factor;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ IntegerMultiplyModification other = (IntegerMultiplyModification) obj;
+ return Objects.equals(factor, other.factor);
+ }
+
+ @Override
+ public String toString() {
+ return "IntegerMultiplyModification{" + "factor=" + factor + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerPrependValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerPrependValueModification.java
new file mode 100644
index 00000000..ddbf3676
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerPrependValueModification.java
@@ -0,0 +1,92 @@
+/*
+ * 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.integer;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"prependValue", "modificationFilter"})
+public class IntegerPrependValueModification extends VariableModification {
+
+ private static final int MAX_VALUE_MODIFIER = 256;
+
+ private Integer prependValue;
+
+ public IntegerPrependValueModification() {
+ super();
+ }
+
+ public IntegerPrependValueModification(Integer prependValue) {
+ super();
+ this.prependValue = prependValue;
+ }
+
+ public IntegerPrependValueModification(IntegerPrependValueModification other) {
+ super(other);
+ prependValue = other.prependValue;
+ }
+
+ @Override
+ public IntegerPrependValueModification createCopy() {
+ return new IntegerPrependValueModification(this);
+ }
+
+ @Override
+ protected Integer modifyImplementationHook(Integer input) {
+ if (input == null) {
+ input = 0;
+ }
+
+ return prependValue << Integer.SIZE - Integer.numberOfLeadingZeros(input) | input;
+ }
+
+ public Integer getPrependValue() {
+ return prependValue;
+ }
+
+ public void setPrependValue(Integer prependValue) {
+ this.prependValue = prependValue;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ return new IntegerPrependValueModification(
+ prependValue + new Random().nextInt(MAX_VALUE_MODIFIER));
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + prependValue;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ IntegerPrependValueModification other = (IntegerPrependValueModification) obj;
+ return Objects.equals(prependValue, other.prependValue);
+ }
+
+ @Override
+ public String toString() {
+ return "IntegerPrependValueModification{" + "prependValue=" + prependValue + '}';
+ }
+}
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 3647542c..7c6aced5 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerShiftLeftModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerShiftLeftModification.java
@@ -20,15 +20,28 @@ public class IntegerShiftLeftModification extends VariableModification
private int shift;
- public IntegerShiftLeftModification() {}
+ public IntegerShiftLeftModification() {
+ super();
+ }
public IntegerShiftLeftModification(int shift) {
+ super();
this.shift = shift;
}
+ public IntegerShiftLeftModification(IntegerShiftLeftModification other) {
+ super(other);
+ shift = other.shift;
+ }
+
+ @Override
+ public IntegerShiftLeftModification createCopy() {
+ return new IntegerShiftLeftModification(this);
+ }
+
@Override
protected Integer modifyImplementationHook(Integer input) {
- return (input == null) ? 0 : input << shift;
+ return input == null ? 0 : input << shift % MAX_SHIFT_MODIFIER;
}
public int getShift() {
@@ -59,7 +72,7 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
int hash = 7;
- hash = 73 * hash + this.shift;
+ hash = 31 * hash + shift;
return hash;
}
@@ -74,10 +87,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final IntegerShiftLeftModification other = (IntegerShiftLeftModification) obj;
- if (this.shift != other.shift) {
- return false;
- }
- return true;
+ IntegerShiftLeftModification other = (IntegerShiftLeftModification) obj;
+ return shift == other.shift;
+ }
+
+ @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 f0cfb2e6..bb25bd2b 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerShiftRightModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerShiftRightModification.java
@@ -20,15 +20,28 @@ public class IntegerShiftRightModification extends VariableModification
private int shift;
- public IntegerShiftRightModification() {}
+ public IntegerShiftRightModification() {
+ super();
+ }
public IntegerShiftRightModification(int shift) {
+ super();
this.shift = shift;
}
+ public IntegerShiftRightModification(IntegerShiftRightModification other) {
+ super(other);
+ shift = other.shift;
+ }
+
+ @Override
+ public IntegerShiftRightModification createCopy() {
+ return new IntegerShiftRightModification(this);
+ }
+
@Override
- protected Integer modifyImplementationHook(final Integer input) {
- return (input == null) ? 0 : input >> shift;
+ protected Integer modifyImplementationHook(Integer input) {
+ return input == null ? 0 : input >> shift % MAX_SHIFT_MODIFIER;
}
public int getShift() {
@@ -58,8 +71,8 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
- int hash = 5;
- hash = 59 * hash + this.shift;
+ int hash = 7;
+ hash = 31 * hash + shift;
return hash;
}
@@ -74,10 +87,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final IntegerShiftRightModification other = (IntegerShiftRightModification) obj;
- if (this.shift != other.shift) {
- return false;
- }
- return true;
+ IntegerShiftRightModification other = (IntegerShiftRightModification) obj;
+ return shift == other.shift;
+ }
+
+ @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 12c43435..3586d55c 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerSubtractModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerSubtractModification.java
@@ -21,15 +21,28 @@ public class IntegerSubtractModification extends VariableModification {
private Integer subtrahend;
- public IntegerSubtractModification() {}
+ public IntegerSubtractModification() {
+ super();
+ }
+
+ public IntegerSubtractModification(Integer subtrahend) {
+ super();
+ this.subtrahend = subtrahend;
+ }
+
+ public IntegerSubtractModification(IntegerSubtractModification other) {
+ super(other);
+ subtrahend = other.subtrahend;
+ }
- public IntegerSubtractModification(Integer bi) {
- this.subtrahend = bi;
+ @Override
+ public IntegerSubtractModification createCopy() {
+ return new IntegerSubtractModification(this);
}
@Override
- protected Integer modifyImplementationHook(final Integer input) {
- return (input == null) ? -subtrahend : input - subtrahend;
+ protected Integer modifyImplementationHook(Integer input) {
+ return input == null ? -subtrahend : input - subtrahend;
}
public Integer getSubtrahend() {
@@ -49,7 +62,7 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
int hash = 7;
- hash = 23 * hash + Objects.hashCode(this.subtrahend);
+ hash = 31 * hash + subtrahend;
return hash;
}
@@ -64,10 +77,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final IntegerSubtractModification other = (IntegerSubtractModification) obj;
- if (!Objects.equals(this.subtrahend, other.subtrahend)) {
- return false;
- }
- return true;
+ IntegerSubtractModification other = (IntegerSubtractModification) obj;
+ return Objects.equals(subtrahend, other.subtrahend);
+ }
+
+ @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
new file mode 100644
index 00000000..601b9abd
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerSwapEndianModification.java
@@ -0,0 +1,64 @@
+/*
+ * 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.integer;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+
+@XmlRootElement
+@XmlType(propOrder = "modificationFilter")
+public class IntegerSwapEndianModification extends VariableModification {
+
+ public IntegerSwapEndianModification() {
+ super();
+ }
+
+ public IntegerSwapEndianModification(IntegerSwapEndianModification other) {
+ super(other);
+ }
+
+ @Override
+ public IntegerSwapEndianModification createCopy() {
+ return new IntegerSwapEndianModification(this);
+ }
+
+ @Override
+ protected Integer modifyImplementationHook(Integer input) {
+ if (input == null) {
+ return null;
+ }
+ return Integer.reverseBytes(input);
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ return new IntegerSwapEndianModification();
+ }
+
+ @Override
+ public int hashCode() {
+ return 7;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ return getClass() == obj.getClass();
+ }
+
+ @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 b91a6e1f..d33f6fc3 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerXorModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/IntegerXorModification.java
@@ -21,15 +21,28 @@ public class IntegerXorModification extends VariableModification {
private Integer xor;
- public IntegerXorModification() {}
+ public IntegerXorModification() {
+ super();
+ }
+
+ public IntegerXorModification(Integer xor) {
+ super();
+ this.xor = xor;
+ }
+
+ public IntegerXorModification(IntegerXorModification other) {
+ super(other);
+ xor = other.xor;
+ }
- public IntegerXorModification(Integer bi) {
- this.xor = bi;
+ @Override
+ public IntegerXorModification createCopy() {
+ return new IntegerXorModification(this);
}
@Override
- protected Integer modifyImplementationHook(final Integer input) {
- return (input == null) ? xor : input ^ xor;
+ protected Integer modifyImplementationHook(Integer input) {
+ return input == null ? xor : input ^ xor;
}
public Integer getXor() {
@@ -44,16 +57,16 @@ public void setXor(Integer xor) {
public VariableModification getModifiedCopy() {
Random r = new Random();
if (r.nextBoolean()) {
- return new IntegerSubtractModification(xor + new Random().nextInt(MAX_VALUE_MODIFIER));
+ return new IntegerXorModification(xor + new Random().nextInt(MAX_VALUE_MODIFIER));
} else {
- return new IntegerSubtractModification(xor - new Random().nextInt(MAX_VALUE_MODIFIER));
+ return new IntegerXorModification(xor - new Random().nextInt(MAX_VALUE_MODIFIER));
}
}
@Override
public int hashCode() {
- int hash = 3;
- hash = 97 * hash + Objects.hashCode(this.xor);
+ int hash = 7;
+ hash = 31 * hash + xor;
return hash;
}
@@ -68,10 +81,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final IntegerXorModification other = (IntegerXorModification) obj;
- if (!Objects.equals(this.xor, other.xor)) {
- return false;
- }
- return true;
+ IntegerXorModification other = (IntegerXorModification) obj;
+ return Objects.equals(xor, other.xor);
+ }
+
+ @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 e3daeb21..d9612ec3 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/integer/ModifiableInteger.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/integer/ModifiableInteger.java
@@ -20,8 +20,27 @@ public class ModifiableInteger extends ModifiableVariable {
private Integer originalValue;
+ public ModifiableInteger() {
+ super();
+ }
+
+ public ModifiableInteger(Integer originalValue) {
+ super();
+ this.originalValue = originalValue;
+ }
+
+ public ModifiableInteger(ModifiableInteger other) {
+ super(other);
+ originalValue = other.originalValue;
+ }
+
+ @Override
+ public ModifiableInteger createCopy() {
+ return new ModifiableInteger(this);
+ }
+
@Override
- protected void createRandomModification() {
+ public void setRandomModification() {
VariableModification vm = IntegerModificationFactory.createRandomModification();
setModification(vm);
}
@@ -66,19 +85,19 @@ public void setOriginalValue(Integer originalValue) {
@Override
public String toString() {
- return "ModifiableInteger{" + "originalValue=" + originalValue + '}';
+ return "ModifiableInteger{" + "originalValue=" + originalValue + innerToString() + '}';
}
@Override
- public boolean equals(Object o) {
- if (this == o) {
+ public boolean equals(Object obj) {
+ if (this == obj) {
return true;
}
- if (!(o instanceof ModifiableInteger)) {
+ if (!(obj instanceof ModifiableInteger)) {
return false;
}
- ModifiableInteger that = (ModifiableInteger) o;
+ ModifiableInteger that = (ModifiableInteger) obj;
return getValue() != null ? getValue().equals(that.getValue()) : that.getValue() == null;
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/length/ModifiableLengthField.java b/src/main/java/de/rub/nds/modifiablevariable/length/ModifiableLengthField.java
index f54b99e4..0afcfe2d 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/length/ModifiableLengthField.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/length/ModifiableLengthField.java
@@ -20,9 +20,20 @@ public class ModifiableLengthField extends ModifiableInteger {
private final ModifiableByteArray ref;
public ModifiableLengthField(ModifiableByteArray ref) {
+ super();
this.ref = ref;
}
+ public ModifiableLengthField(ModifiableLengthField other) {
+ super(other);
+ ref = other.ref;
+ }
+
+ @Override
+ public ModifiableLengthField createCopy() {
+ return new ModifiableLengthField(this);
+ }
+
@Override
public Integer getOriginalValue() {
return ref.getValue().length;
@@ -36,19 +47,19 @@ public void setOriginalValue(Integer originalValue) {
@Override
public String toString() {
- return "ModifiableLengthField{" + "ref=" + ref + "} " + super.toString();
+ return "ModifiableLengthField{" + "ref=" + ref + super.toString() + "} ";
}
@Override
- public boolean equals(Object o) {
- if (this == o) {
+ public boolean equals(Object obj) {
+ if (this == obj) {
return true;
}
- if (!(o instanceof ModifiableLengthField)) {
+ if (!(obj instanceof ModifiableLengthField)) {
return false;
}
- ModifiableLengthField that = (ModifiableLengthField) o;
+ ModifiableLengthField that = (ModifiableLengthField) obj;
return ref != null ? getValue().equals(that.getValue()) : that.getValue() == null;
}
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 36475e7b..e35a58e9 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/logging/ExtendedPatternLayout.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/logging/ExtendedPatternLayout.java
@@ -39,7 +39,7 @@
category = "Core",
elementType = "layout",
printObject = true)
-public class ExtendedPatternLayout extends AbstractStringLayout {
+public final class ExtendedPatternLayout extends AbstractStringLayout {
public static final String DEFAULT_CONVERSION_PATTERN = "%m%n";
public static final String TTCC_CONVERSION_PATTERN = "%r [%t] %p %c %notEmpty{%x }- %m%n";
public static final String SIMPLE_CONVERSION_PATTERN = "%d [%t] %p %c - %m%n";
@@ -80,9 +80,9 @@ private ExtendedPatternLayout(
.setNoConsoleNoAnsi(noConsoleNoAnsi)
.setPattern(footerPattern)
.build());
- this.conversionPattern = eventPattern;
+ conversionPattern = eventPattern;
this.patternSelector = patternSelector;
- this.eventSerializer =
+ eventSerializer =
newSerializerBuilder()
.setConfiguration(config)
.setReplace(replace)
@@ -101,8 +101,8 @@ public static ExtendedPatternLayout.SerializerBuilder newSerializerBuilder() {
@Override
public boolean requiresLocation() {
- return this.eventSerializer instanceof LocationAware
- && ((LocationAware) this.eventSerializer).requiresLocation();
+ return eventSerializer instanceof LocationAware
+ && ((LocationAware) eventSerializer).requiresLocation();
}
/**
@@ -129,7 +129,7 @@ public static AbstractStringLayout.Serializer createSerializer(
}
public String getConversionPattern() {
- return this.conversionPattern;
+ return conversionPattern;
}
@Override
@@ -137,32 +137,32 @@ public Map getContentFormat() {
Map result = new HashMap<>();
result.put("structured", "false");
result.put("formatType", "conversion");
- result.put("format", this.conversionPattern);
+ result.put("format", conversionPattern);
return result;
}
@Override
public String toSerializable(LogEvent event) {
- return this.eventSerializer.toSerializable(event);
+ return eventSerializer.toSerializable(event);
}
public void serialize(LogEvent event, StringBuilder stringBuilder) {
- this.eventSerializer.toSerializable(event, stringBuilder);
+ eventSerializer.toSerializable(event, stringBuilder);
}
@Override
public void encode(LogEvent event, ByteBufferDestination destination) {
- if (this.eventSerializer == null) {
+ if (eventSerializer == null) {
super.encode(event, destination);
} else {
- StringBuilder text = this.toText(this.eventSerializer, event, getStringBuilder());
- Encoder encoder = this.getStringBuilderEncoder();
+ StringBuilder text = toText(eventSerializer, event, getStringBuilder());
+ Encoder encoder = getStringBuilderEncoder();
encoder.encode(text, destination);
trimToMaxSize(text);
}
}
- private StringBuilder toText(
+ private static StringBuilder toText(
AbstractStringLayout.Serializer2 serializer,
LogEvent event,
StringBuilder destination) {
@@ -171,7 +171,7 @@ private StringBuilder toText(
public static PatternParser createPatternParser(Configuration config) {
if (config == null) {
- return new PatternParser(config, "Converter", LogEventPatternConverter.class);
+ return new PatternParser(null, "Converter", LogEventPatternConverter.class);
} else {
PatternParser parser = config.getComponent("Converter");
if (parser == null) {
@@ -186,9 +186,7 @@ public static PatternParser createPatternParser(Configuration config) {
@Override
public String toString() {
- return this.patternSelector == null
- ? this.conversionPattern
- : this.patternSelector.toString();
+ return patternSelector == null ? conversionPattern : patternSelector.toString();
}
/**
@@ -234,10 +232,10 @@ public static ExtendedPatternLayout.Builder newBuilder() {
}
public AbstractStringLayout.Serializer getEventSerializer() {
- return this.eventSerializer;
+ return eventSerializer;
}
- public static class Builder
+ public static final class Builder
implements org.apache.logging.log4j.core.util.Builder {
@PluginBuilderAttribute private String pattern;
@@ -263,13 +261,14 @@ public static class Builder
private static boolean prettyPrinting;
private Builder() {
- this.pattern = "%m%n";
- this.charset = Charset.defaultCharset();
- this.alwaysWriteExceptions = true;
- this.disableAnsi = !this.useAnsiEscapeCodes();
+ super();
+ pattern = "%m%n";
+ charset = Charset.defaultCharset();
+ alwaysWriteExceptions = true;
+ disableAnsi = !useAnsiEscapeCodes();
}
- private boolean useAnsiEscapeCodes() {
+ private static boolean useAnsiEscapeCodes() {
PropertiesUtil propertiesUtil = PropertiesUtil.getProperties();
boolean isPlatformSupportsAnsi = !propertiesUtil.isOsWindows();
boolean isJansiRequested = !propertiesUtil.getBooleanProperty("log4j.skipJansi", true);
@@ -333,78 +332,79 @@ public ExtendedPatternLayout.Builder withFooter(String footer) {
@Override
public ExtendedPatternLayout build() {
- if (this.configuration == null) {
- this.configuration = new DefaultConfiguration();
+ if (configuration == null) {
+ configuration = new DefaultConfiguration();
}
return new ExtendedPatternLayout(
- this.configuration,
- this.regexReplacement,
- this.pattern,
- this.patternSelector,
- this.charset,
- this.alwaysWriteExceptions,
- this.disableAnsi,
- this.noConsoleNoAnsi,
- this.header,
- this.footer);
+ configuration,
+ regexReplacement,
+ pattern,
+ patternSelector,
+ charset,
+ alwaysWriteExceptions,
+ disableAnsi,
+ noConsoleNoAnsi,
+ header,
+ footer);
}
}
- private static class PatternSelectorSerializer
+ private static final class PatternSelectorSerializer
implements AbstractStringLayout.Serializer, LocationAware {
private final PatternSelector patternSelector;
private final RegexReplacement replace;
private PatternSelectorSerializer(
PatternSelector patternSelector, RegexReplacement replace) {
+ super();
this.patternSelector = patternSelector;
this.replace = replace;
}
@Override
public String toSerializable(LogEvent event) {
- StringBuilder sb = AbstractStringLayout.getStringBuilder();
+ StringBuilder sb = getStringBuilder();
String var3;
try {
- var3 = this.toSerializable(event, sb).toString();
+ var3 = toSerializable(event, sb).toString();
} finally {
- AbstractStringLayout.trimToMaxSize(sb);
+ trimToMaxSize(sb);
}
return var3;
}
@Override
- public StringBuilder toSerializable(LogEvent event, StringBuilder buffer) {
- PatternFormatter[] formatters = this.patternSelector.getFormatters(event);
- Arrays.stream(formatters).forEachOrdered(formatter -> formatter.format(event, buffer));
-
- if (this.replace != null) {
- String str = buffer.toString();
- str = this.replace.format(str);
- buffer.setLength(0);
- buffer.append(str);
+ public StringBuilder toSerializable(LogEvent event, StringBuilder builder) {
+ PatternFormatter[] formatters = patternSelector.getFormatters(event);
+ Arrays.stream(formatters).forEachOrdered(formatter -> formatter.format(event, builder));
+
+ if (replace != null) {
+ String str = builder.toString();
+ str = replace.format(str);
+ builder.setLength(0);
+ builder.append(str);
}
- return buffer;
+ return builder;
}
@Override
public boolean requiresLocation() {
- return this.patternSelector instanceof LocationAware
- && ((LocationAware) this.patternSelector).requiresLocation();
+ return patternSelector instanceof LocationAware
+ && ((LocationAware) patternSelector).requiresLocation();
}
@Override
public String toString() {
return super.toString()
- .concat("[patternSelector=")
- .concat(this.patternSelector.toString())
- .concat(", replace=")
- .concat(this.replace.toString())
- .concat("]");
+ + "[patternSelector="
+ + patternSelector.toString()
+ + ", replace="
+ + replace.toString()
+ + "]";
}
}
@@ -421,28 +421,27 @@ public static class SerializerBuilder
@Override
public AbstractStringLayout.Serializer build() {
- if (Strings.isEmpty(this.pattern) && Strings.isEmpty(this.defaultPattern)) {
+ if (Strings.isEmpty(pattern) && Strings.isEmpty(defaultPattern)) {
return null;
- } else if (this.patternSelector == null) {
+ } else if (patternSelector == null) {
try {
- PatternParser parser =
- ExtendedPatternLayout.createPatternParser(this.configuration);
+ PatternParser parser = createPatternParser(configuration);
List list =
parser.parse(
- this.pattern == null ? this.defaultPattern : this.pattern,
- this.alwaysWriteExceptions,
- this.disableAnsi,
- this.noConsoleNoAnsi);
+ pattern == null ? defaultPattern : pattern,
+ alwaysWriteExceptions,
+ disableAnsi,
+ noConsoleNoAnsi);
PatternFormatter[] formatters = list.toArray(new PatternFormatter[0]);
return new ExtendedPatternLayout.ExtendedPatternLayoutSerializer(
- formatters, this.replace);
+ formatters, replace);
} catch (RuntimeException var4) {
throw new IllegalArgumentException(
- "Cannot parse pattern '" + this.pattern + "'", var4);
+ "Cannot parse pattern '" + pattern + "'", var4);
}
} else {
return new ExtendedPatternLayout.PatternSelectorSerializer(
- this.patternSelector, this.replace);
+ patternSelector, replace);
}
}
@@ -490,39 +489,40 @@ public ExtendedPatternLayout.SerializerBuilder setNoConsoleNoAnsi(boolean noCons
}
}
- private static class ExtendedPatternLayoutSerializer
+ private static final class ExtendedPatternLayoutSerializer
implements AbstractStringLayout.Serializer, LocationAware {
private final PatternFormatter[] formatters;
private final RegexReplacement replace;
private ExtendedPatternLayoutSerializer(
PatternFormatter[] formatters, RegexReplacement replace) {
+ super();
this.formatters = formatters;
this.replace = replace;
}
@Override
public String toSerializable(LogEvent event) {
- StringBuilder sb = AbstractStringLayout.getStringBuilder();
+ StringBuilder sb = getStringBuilder();
String var3;
try {
- var3 = this.toSerializable(event, sb).toString();
+ var3 = toSerializable(event, sb).toString();
} finally {
- AbstractStringLayout.trimToMaxSize(sb);
+ trimToMaxSize(sb);
}
return var3;
}
@Override
- public StringBuilder toSerializable(LogEvent event, StringBuilder buffer) {
- Arrays.stream(formatters).forEachOrdered(formatter -> formatter.format(event, buffer));
-
- if (this.replace != null) {
- String str = buffer.toString();
- str = this.replace.format(str);
- buffer.setLength(0);
- buffer.append(str);
+ public StringBuilder toSerializable(LogEvent event, StringBuilder builder) {
+ Arrays.stream(formatters).forEachOrdered(formatter -> formatter.format(event, builder));
+
+ if (replace != null) {
+ String str = builder.toString();
+ str = replace.format(str);
+ builder.setLength(0);
+ builder.append(str);
}
// Added section to parse ByteArrays to the correct output format.
@@ -538,9 +538,9 @@ public StringBuilder toSerializable(LogEvent event, StringBuilder buffer) {
// calculated
// by the ArrayConverter.
if (param != null && bArrayClass.equals(param.getClass())) {
- buffer.replace(
- buffer.indexOf(Arrays.toString((byte[]) param)),
- buffer.indexOf(Arrays.toString((byte[]) param))
+ builder.replace(
+ builder.indexOf(Arrays.toString((byte[]) param)),
+ builder.indexOf(Arrays.toString((byte[]) param))
+ Arrays.toString((byte[]) param).length(),
ArrayConverter.bytesToHexString(
(byte[]) param,
@@ -549,21 +549,21 @@ public StringBuilder toSerializable(LogEvent event, StringBuilder buffer) {
}
}
}
- return buffer;
+ return builder;
}
public boolean requiresLocation() {
- return Arrays.stream(this.formatters).anyMatch(PatternFormatter::requiresLocation);
+ return Arrays.stream(formatters).anyMatch(PatternFormatter::requiresLocation);
}
@Override
public String toString() {
return super.toString()
- .concat("[formatters=")
- .concat(Arrays.toString(this.formatters))
- .concat(", replace=")
- .concat(this.replace.toString())
- .concat("]");
+ + "[formatters="
+ + Arrays.toString(formatters)
+ + ", replace="
+ + replace.toString()
+ + "]";
}
}
}
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 6f89d677..a42604f4 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/longint/LongAddModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongAddModification.java
@@ -21,15 +21,28 @@ public class LongAddModification extends VariableModification {
private Long summand;
- public LongAddModification() {}
+ public LongAddModification() {
+ super();
+ }
+
+ public LongAddModification(Long summand) {
+ super();
+ this.summand = summand;
+ }
+
+ public LongAddModification(LongAddModification other) {
+ super(other);
+ summand = other.summand;
+ }
- public LongAddModification(Long bi) {
- this.summand = bi;
+ @Override
+ public LongAddModification createCopy() {
+ return new LongAddModification(this);
}
@Override
- protected Long modifyImplementationHook(final Long input) {
- return (input == null) ? summand : input + summand;
+ protected Long modifyImplementationHook(Long input) {
+ return input == null ? summand : input + summand;
}
public Long getSummand() {
@@ -48,7 +61,7 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
int hash = 7;
- hash = 43 * hash + Objects.hashCode(this.summand);
+ hash = 31 * hash + summand.hashCode();
return hash;
}
@@ -63,10 +76,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final LongAddModification other = (LongAddModification) obj;
- if (!Objects.equals(this.summand, other.summand)) {
- return false;
- }
- return true;
+ LongAddModification other = (LongAddModification) obj;
+ return Objects.equals(summand, other.summand);
+ }
+
+ @Override
+ public String toString() {
+ return "LongAddModification{" + "summand=" + summand + '}';
}
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongAppendValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongAppendValueModification.java
new file mode 100644
index 00000000..b6f05442
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongAppendValueModification.java
@@ -0,0 +1,91 @@
+/*
+ * 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.longint;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"appendValue", "modificationFilter"})
+public class LongAppendValueModification extends VariableModification {
+
+ private static final int MAX_VALUE_MODIFIER = 256;
+
+ private Long appendValue;
+
+ public LongAppendValueModification() {
+ super();
+ }
+
+ public LongAppendValueModification(Long appendValue) {
+ super();
+ this.appendValue = appendValue;
+ }
+
+ public LongAppendValueModification(LongAppendValueModification other) {
+ super(other);
+ appendValue = other.appendValue;
+ }
+
+ @Override
+ public LongAppendValueModification createCopy() {
+ return new LongAppendValueModification(this);
+ }
+
+ @Override
+ protected Long modifyImplementationHook(Long input) {
+ if (input == null) {
+ input = 0L;
+ }
+ return input << Long.SIZE - Long.numberOfLeadingZeros(appendValue) | appendValue;
+ }
+
+ public Long getAppendValue() {
+ return appendValue;
+ }
+
+ public void setAppendValue(Long appendValue) {
+ this.appendValue = appendValue;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ return new LongAppendValueModification(
+ appendValue + new Random().nextInt(MAX_VALUE_MODIFIER));
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + appendValue.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LongAppendValueModification other = (LongAppendValueModification) obj;
+ return Objects.equals(appendValue, other.appendValue);
+ }
+
+ @Override
+ public String toString() {
+ return "LongAppendValueModification{" + "appendValue=" + appendValue + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongExplicitValueFromFileModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongExplicitValueFromFileModification.java
new file mode 100644
index 00000000..9635702d
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongExplicitValueFromFileModification.java
@@ -0,0 +1,87 @@
+/*
+ * 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.longint;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+
+@XmlRootElement
+@XmlType(propOrder = "index")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class LongExplicitValueFromFileModification extends LongExplicitValueModification {
+ private int index;
+
+ public LongExplicitValueFromFileModification() {
+ super();
+ }
+
+ public LongExplicitValueFromFileModification(int index, Long explicitValue) {
+ super(explicitValue);
+ this.index = index;
+ }
+
+ public LongExplicitValueFromFileModification(LongExplicitValueFromFileModification other) {
+ super(other);
+ index = other.index;
+ }
+
+ @Override
+ public LongExplicitValueFromFileModification createCopy() {
+ return new LongExplicitValueFromFileModification(this);
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ throw new UnsupportedOperationException(
+ "Cannot set modify Value of LongExplicitValueFromFileModification");
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + index;
+ hash = 31 * hash + explicitValue.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LongExplicitValueFromFileModification other = (LongExplicitValueFromFileModification) obj;
+ if (index != other.index) {
+ return false;
+ }
+ return Objects.equals(explicitValue, other.explicitValue);
+ }
+
+ @Override
+ public String toString() {
+ return "LongExplicitValueFromFileModification{"
+ + "index="
+ + index
+ + ", explicitValue="
+ + explicitValue
+ + '}';
+ }
+}
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 d8136779..a52d08ed 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/longint/LongExplicitValueModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongExplicitValueModification.java
@@ -19,16 +19,29 @@ public class LongExplicitValueModification extends VariableModification {
private static final int MAX_EXPLICIT_MODIFIER = 256;
- private Long explicitValue;
+ protected Long explicitValue;
- public LongExplicitValueModification() {}
+ public LongExplicitValueModification() {
+ super();
+ }
+
+ public LongExplicitValueModification(Long explicitValue) {
+ super();
+ this.explicitValue = explicitValue;
+ }
+
+ public LongExplicitValueModification(LongExplicitValueModification other) {
+ super(other);
+ explicitValue = other.explicitValue;
+ }
- public LongExplicitValueModification(Long bi) {
- this.explicitValue = bi;
+ @Override
+ public LongExplicitValueModification createCopy() {
+ return new LongExplicitValueModification(this);
}
@Override
- protected Long modifyImplementationHook(final Long input) {
+ protected Long modifyImplementationHook(Long input) {
return explicitValue;
}
@@ -54,8 +67,8 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
- int hash = 3;
- hash = 43 * hash + Objects.hashCode(this.explicitValue);
+ int hash = 7;
+ hash = 31 * hash + explicitValue.hashCode();
return hash;
}
@@ -70,10 +83,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final LongExplicitValueModification other = (LongExplicitValueModification) obj;
- if (!Objects.equals(this.explicitValue, other.explicitValue)) {
- return false;
- }
- return true;
+ LongExplicitValueModification other = (LongExplicitValueModification) obj;
+ return Objects.equals(explicitValue, other.explicitValue);
+ }
+
+ @Override
+ public String toString() {
+ return "LongExplicitValueModification{" + "explicitValue=" + explicitValue + '}';
}
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongInsertValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongInsertValueModification.java
new file mode 100644
index 00000000..3eb30715
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongInsertValueModification.java
@@ -0,0 +1,138 @@
+/*
+ * 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.longint;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"insertValue", "startPosition", "modificationFilter"})
+public class LongInsertValueModification extends VariableModification {
+
+ private static final int MAX_VALUE_MODIFIER = 256;
+ private static final int MAX_POSITION_MODIFIER = 32;
+
+ private Long insertValue;
+ private int startPosition;
+
+ public LongInsertValueModification() {
+ super();
+ }
+
+ public LongInsertValueModification(Long insertValue, int startPosition) {
+ super();
+ this.insertValue = insertValue;
+ this.startPosition = startPosition;
+ }
+
+ public LongInsertValueModification(LongInsertValueModification other) {
+ super(other);
+ insertValue = other.insertValue;
+ startPosition = other.startPosition;
+ }
+
+ @Override
+ public LongInsertValueModification createCopy() {
+ return new LongInsertValueModification(this);
+ }
+
+ @Override
+ protected Long modifyImplementationHook(Long input) {
+ if (input == null) {
+ input = 0L;
+ }
+
+ int insertValueLength = Long.SIZE - Long.numberOfLeadingZeros(insertValue);
+
+ // Wrap around long size
+ int insertPosition = startPosition % Long.SIZE;
+ if (startPosition < 0) {
+ insertPosition += Long.SIZE - 1;
+ }
+
+ long mask = (1L << insertPosition) - 1;
+
+ return (input >> insertPosition << insertValueLength | insertValue) << insertPosition
+ | mask & input;
+ }
+
+ public Long getInsertValue() {
+ return insertValue;
+ }
+
+ public void setInsertValue(Long insertValue) {
+ this.insertValue = insertValue;
+ }
+
+ public int getStartPosition() {
+ return startPosition;
+ }
+
+ public void setStartPosition(int startPosition) {
+ this.startPosition = startPosition;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+
+ if (r.nextBoolean()) {
+ return new LongInsertValueModification(
+ insertValue + r.nextInt(MAX_VALUE_MODIFIER), startPosition);
+ } else {
+ int modifier = r.nextInt(MAX_POSITION_MODIFIER);
+ if (r.nextBoolean()) {
+ modifier *= -1;
+ }
+ modifier = startPosition + modifier;
+ if (modifier <= 0) {
+ modifier = 1;
+ }
+ return new LongInsertValueModification(insertValue, modifier);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + insertValue.hashCode();
+ hash = 31 * hash + startPosition;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LongInsertValueModification other = (LongInsertValueModification) obj;
+ if (startPosition != other.startPosition) {
+ return false;
+ }
+ return Objects.equals(insertValue, other.insertValue);
+ }
+
+ @Override
+ public String toString() {
+ return "LongInsertValueModification{"
+ + "insertValue="
+ + insertValue
+ + ", startPosition="
+ + startPosition
+ + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongModificationFactory.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongModificationFactory.java
index bbfd4f09..546db557 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/longint/LongModificationFactory.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongModificationFactory.java
@@ -15,68 +15,125 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.util.LinkedList;
+import java.util.ArrayList;
import java.util.List;
import java.util.Random;
-public class LongModificationFactory {
+public final class LongModificationFactory {
+
+ private enum ModificationType {
+ ADD,
+ SUBTRACT,
+ MULTIPLY,
+ XOR,
+ SWAP_ENDIAN,
+ EXPLICIT,
+ SHIFT_LEFT,
+ SHIFT_RIGHT,
+ EXPLICIT_FROM_FILE,
+ APPEND,
+ INSERT,
+ PREPEND
+ }
- private static final int MODIFICATION_COUNT = 5;
+ private static final int MODIFICATION_COUNT = ModificationType.values().length;
private static final int MAX_MODIFICATION_VALUE = 32000;
+ private static final int MAX_FILE_ENTRIES = 200;
+
+ private static final int MAX_MODIFICATION_SHIFT_VALUE = 40;
+
+ private static final int MAX_MODIFICATION_MULTIPLY_VALUE = 256;
+
+ private static final int MAX_MODIFICATION_INSERT_VALUE = 256;
+
+ private static final int MAX_MODIFICATION_INSERT_POSITION_VALUE = 64;
+
private static List> modificationsFromFile;
- public static LongAddModification add(final String summand) {
+ public static final String FILE_NAME = "de/rub/nds/modifiablevariable/explicit/long.vec";
+
+ public static LongAddModification add(String summand) {
return add(Long.parseLong(summand));
}
- public static LongAddModification add(final Long summand) {
+ public static LongAddModification add(Long summand) {
return new LongAddModification(summand);
}
- public static VariableModification sub(final String subtrahend) {
+ public static VariableModification sub(String subtrahend) {
return sub(Long.parseLong(subtrahend));
}
- public static VariableModification sub(final Long subtrahend) {
+ public static VariableModification sub(Long subtrahend) {
return new LongSubtractModification(subtrahend);
}
- public static VariableModification xor(final String xor) {
+ public static VariableModification xor(String xor) {
return xor(Long.parseLong(xor));
}
- public static VariableModification xor(final Long xor) {
+ public static VariableModification xor(Long xor) {
return new LongXorModification(xor);
}
- public static VariableModification explicitValue(final String value) {
+ public static VariableModification swapEndian() {
+ return new LongSwapEndianModification();
+ }
+
+ public static VariableModification explicitValue(String value) {
return explicitValue(Long.parseLong(value));
}
- public static VariableModification explicitValue(final Long value) {
+ public static VariableModification explicitValue(Long value) {
return new LongExplicitValueModification(value);
}
- public static VariableModification explicitValueFromFile(int value) {
+ public static VariableModification explicitValueFromFile(int pos) {
List> modifications = modificationsFromFile();
- int pos = value % modifications.size();
- return modifications.get(pos);
+ return modifications.get(pos % modifications.size());
+ }
+
+ public static VariableModification appendValue(Long value) {
+ return new LongAppendValueModification(value);
+ }
+
+ public static VariableModification insertValue(Long value, int position) {
+ return new LongInsertValueModification(value, position);
+ }
+
+ public static VariableModification prependValue(Long value) {
+ return new LongPrependValueModification(value);
+ }
+
+ public static VariableModification multiply(Long factor) {
+ return new LongMultiplyModification(factor);
+ }
+
+ public static VariableModification shiftLeft(int shift) {
+ return new LongShiftLeftModification(shift);
+ }
+
+ public static VariableModification shiftRight(int shift) {
+ return new LongShiftRightModification(shift);
}
public static synchronized List> modificationsFromFile() {
try {
if (modificationsFromFile == null) {
- modificationsFromFile = new LinkedList<>();
+ modificationsFromFile = new ArrayList<>();
ClassLoader classLoader = IntegerModificationFactory.class.getClassLoader();
- InputStream is =
- classLoader.getResourceAsStream(IntegerModificationFactory.FILE_NAME);
+ InputStream is = classLoader.getResourceAsStream(FILE_NAME);
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
+ int index = 0;
while ((line = br.readLine()) != null) {
String value = line.trim().split(" ")[0];
- modificationsFromFile.add(explicitValue(value));
+ modificationsFromFile.add(
+ new LongExplicitValueFromFileModification(
+ index, Long.parseLong(value)));
+ index++;
}
}
return modificationsFromFile;
@@ -88,29 +145,44 @@ public static synchronized List> modificationsFromFil
public static VariableModification createRandomModification() {
Random random = RandomHelper.getRandom();
- int r = random.nextInt(MODIFICATION_COUNT);
+ ModificationType randomType = ModificationType.values()[random.nextInt(MODIFICATION_COUNT)];
long modification = random.nextInt(MAX_MODIFICATION_VALUE);
- VariableModification vm = null;
- switch (r) {
- case 0:
- vm = new LongAddModification(modification);
- return vm;
- case 1:
- vm = new LongSubtractModification(modification);
- return vm;
- case 2:
- vm = new LongXorModification(modification);
- return vm;
- case 3:
- vm = new LongExplicitValueModification(modification);
- return vm;
- case 4:
- vm = explicitValueFromFile(random.nextInt(MAX_MODIFICATION_VALUE));
- return vm;
+ long insert_modification = random.nextInt(MAX_MODIFICATION_INSERT_VALUE);
+ int shiftModification = random.nextInt(MAX_MODIFICATION_SHIFT_VALUE);
+ switch (randomType) {
+ case ADD:
+ return new LongAddModification(modification);
+ case SUBTRACT:
+ return new LongSubtractModification(modification);
+ case MULTIPLY:
+ return new LongMultiplyModification(
+ (long) random.nextInt(MAX_MODIFICATION_MULTIPLY_VALUE));
+ case XOR:
+ return new LongXorModification(modification);
+ case SWAP_ENDIAN:
+ return new LongSwapEndianModification();
+ case EXPLICIT:
+ return new LongExplicitValueModification(modification);
+ case SHIFT_LEFT:
+ return new LongShiftLeftModification(shiftModification);
+ case SHIFT_RIGHT:
+ return new LongShiftRightModification(shiftModification);
+ case EXPLICIT_FROM_FILE:
+ return explicitValueFromFile(random.nextInt(MAX_FILE_ENTRIES));
+ case APPEND:
+ return new LongAppendValueModification(insert_modification);
+ case INSERT:
+ return new LongInsertValueModification(
+ insert_modification,
+ random.nextInt(MAX_MODIFICATION_INSERT_POSITION_VALUE));
+ case PREPEND:
+ return new LongPrependValueModification(insert_modification);
default:
- return vm;
+ throw new IllegalStateException("Unexpected modification type: " + randomType);
}
}
- private LongModificationFactory() {}
+ private LongModificationFactory() {
+ super();
+ }
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongMultiplyModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongMultiplyModification.java
new file mode 100644
index 00000000..180f96b3
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongMultiplyModification.java
@@ -0,0 +1,87 @@
+/*
+ * 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.longint;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"factor", "modificationFilter"})
+public class LongMultiplyModification extends VariableModification {
+
+ private static final int MAX_FACTOR_MODIFIER = 256;
+
+ private Long factor;
+
+ public LongMultiplyModification() {
+ super();
+ }
+
+ public LongMultiplyModification(Long factor) {
+ super();
+ this.factor = factor;
+ }
+
+ public LongMultiplyModification(LongMultiplyModification other) {
+ super(other);
+ factor = other.factor;
+ }
+
+ @Override
+ public LongMultiplyModification createCopy() {
+ return new LongMultiplyModification(this);
+ }
+
+ @Override
+ protected Long modifyImplementationHook(Long input) {
+ return input == null ? 0L : input * factor;
+ }
+
+ public Long getFactor() {
+ return factor;
+ }
+
+ public void setFactor(Long factor) {
+ this.factor = factor;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ return new LongMultiplyModification(factor + new Random().nextInt(MAX_FACTOR_MODIFIER));
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + factor.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LongMultiplyModification other = (LongMultiplyModification) obj;
+ return Objects.equals(factor, other.factor);
+ }
+
+ @Override
+ public String toString() {
+ return "LongMultiplyModification{" + "factor=" + factor + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongPrependValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongPrependValueModification.java
new file mode 100644
index 00000000..484d710c
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongPrependValueModification.java
@@ -0,0 +1,91 @@
+/*
+ * 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.longint;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"prependValue", "modificationFilter"})
+public class LongPrependValueModification extends VariableModification {
+
+ private static final int MAX_VALUE_MODIFIER = 256;
+
+ private Long prependValue;
+
+ public LongPrependValueModification() {
+ super();
+ }
+
+ public LongPrependValueModification(Long prependValue) {
+ super();
+ this.prependValue = prependValue;
+ }
+
+ public LongPrependValueModification(LongPrependValueModification other) {
+ super(other);
+ prependValue = other.prependValue;
+ }
+
+ @Override
+ public LongPrependValueModification createCopy() {
+ return new LongPrependValueModification(this);
+ }
+
+ @Override
+ protected Long modifyImplementationHook(Long input) {
+ if (input == null) {
+ input = 0L;
+ }
+ return prependValue << Long.SIZE - Long.numberOfLeadingZeros(input) | input;
+ }
+
+ public Long getPrependValue() {
+ return prependValue;
+ }
+
+ public void setPrependValue(Long prependValue) {
+ this.prependValue = prependValue;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ return new LongPrependValueModification(
+ prependValue + new Random().nextInt(MAX_VALUE_MODIFIER));
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + prependValue.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LongPrependValueModification other = (LongPrependValueModification) obj;
+ return Objects.equals(prependValue, other.prependValue);
+ }
+
+ @Override
+ public String toString() {
+ return "LongPrependValueModification{" + "prependValue=" + prependValue + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/longint/LongShiftLeftModification.java b/src/main/java/de/rub/nds/modifiablevariable/longint/LongShiftLeftModification.java
new file mode 100644
index 00000000..2d479360
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongShiftLeftModification.java
@@ -0,0 +1,100 @@
+/*
+ * 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.longint;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"shift", "modificationFilter"})
+public class LongShiftLeftModification extends VariableModification {
+
+ private static final int MAX_SHIFT_MODIFIER = 64;
+
+ private int shift;
+
+ public LongShiftLeftModification() {
+ super();
+ }
+
+ public LongShiftLeftModification(int shift) {
+ super();
+ this.shift = shift;
+ }
+
+ public LongShiftLeftModification(LongShiftLeftModification other) {
+ super(other);
+ shift = other.shift;
+ }
+
+ @Override
+ public LongShiftLeftModification createCopy() {
+ return new LongShiftLeftModification(this);
+ }
+
+ @Override
+ protected Long modifyImplementationHook(Long input) {
+ return input == null ? 0L : input << shift % MAX_SHIFT_MODIFIER;
+ }
+
+ public int getShift() {
+ return shift;
+ }
+
+ public void setShift(int shift) {
+ this.shift = shift;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+ int newShift;
+ if (r.nextBoolean()) {
+ newShift = shift + r.nextInt(MAX_SHIFT_MODIFIER);
+ } else {
+ newShift = shift - r.nextInt(MAX_SHIFT_MODIFIER);
+ }
+ if (newShift < 0) {
+ newShift = MAX_SHIFT_MODIFIER - 1;
+ } else if (newShift > MAX_SHIFT_MODIFIER - 1) {
+ newShift = 0;
+ }
+
+ return new LongShiftLeftModification(newShift);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + shift;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LongShiftLeftModification other = (LongShiftLeftModification) obj;
+ return Objects.equals(shift, other.shift);
+ }
+
+ @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
new file mode 100644
index 00000000..0f8b2cfe
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongShiftRightModification.java
@@ -0,0 +1,100 @@
+/*
+ * 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.longint;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"shift", "modificationFilter"})
+public class LongShiftRightModification extends VariableModification {
+
+ private static final int MAX_SHIFT_MODIFIER = 64;
+
+ private int shift;
+
+ public LongShiftRightModification() {
+ super();
+ }
+
+ public LongShiftRightModification(int shift) {
+ super();
+ this.shift = shift;
+ }
+
+ public LongShiftRightModification(LongShiftRightModification other) {
+ super(other);
+ shift = other.shift;
+ }
+
+ @Override
+ public LongShiftRightModification createCopy() {
+ return new LongShiftRightModification(this);
+ }
+
+ @Override
+ protected Long modifyImplementationHook(Long input) {
+ return input == null ? 0L : input >> shift % MAX_SHIFT_MODIFIER;
+ }
+
+ public int getShift() {
+ return shift;
+ }
+
+ public void setShift(int shift) {
+ this.shift = shift;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+ int newShift;
+ if (r.nextBoolean()) {
+ newShift = shift + r.nextInt(MAX_SHIFT_MODIFIER);
+ } else {
+ newShift = shift - r.nextInt(MAX_SHIFT_MODIFIER);
+ }
+ if (newShift < 0) {
+ newShift = MAX_SHIFT_MODIFIER - 1;
+ } else if (newShift > MAX_SHIFT_MODIFIER - 1) {
+ newShift = 0;
+ }
+
+ return new LongShiftRightModification(newShift);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + shift;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LongShiftRightModification other = (LongShiftRightModification) obj;
+ return Objects.equals(shift, other.shift);
+ }
+
+ @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 ba2f488d..2f04ac48 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/longint/LongSubtractModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongSubtractModification.java
@@ -21,15 +21,28 @@ public class LongSubtractModification extends VariableModification {
private Long subtrahend;
- public LongSubtractModification() {}
+ public LongSubtractModification() {
+ super();
+ }
+
+ public LongSubtractModification(Long subtrahend) {
+ super();
+ this.subtrahend = subtrahend;
+ }
+
+ public LongSubtractModification(LongSubtractModification other) {
+ super(other);
+ subtrahend = other.subtrahend;
+ }
- public LongSubtractModification(Long bi) {
- this.subtrahend = bi;
+ @Override
+ public LongSubtractModification createCopy() {
+ return new LongSubtractModification(this);
}
@Override
- protected Long modifyImplementationHook(final Long input) {
- return (input == null) ? -subtrahend : input - subtrahend;
+ protected Long modifyImplementationHook(Long input) {
+ return input == null ? -subtrahend : input - subtrahend;
}
public Long getSubtrahend() {
@@ -49,7 +62,7 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
int hash = 7;
- hash = 97 * hash + Objects.hashCode(this.subtrahend);
+ hash = 31 * hash + subtrahend.hashCode();
return hash;
}
@@ -64,10 +77,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final LongSubtractModification other = (LongSubtractModification) obj;
- if (!Objects.equals(this.subtrahend, other.subtrahend)) {
- return false;
- }
- return true;
+ LongSubtractModification other = (LongSubtractModification) obj;
+ return Objects.equals(subtrahend, other.subtrahend);
+ }
+
+ @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
new file mode 100644
index 00000000..980b4b8e
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongSwapEndianModification.java
@@ -0,0 +1,64 @@
+/*
+ * 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.longint;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+
+@XmlRootElement
+@XmlType(propOrder = "modificationFilter")
+public class LongSwapEndianModification extends VariableModification {
+
+ public LongSwapEndianModification() {
+ super();
+ }
+
+ public LongSwapEndianModification(LongSwapEndianModification other) {
+ super(other);
+ }
+
+ @Override
+ public LongSwapEndianModification createCopy() {
+ return new LongSwapEndianModification(this);
+ }
+
+ @Override
+ protected Long modifyImplementationHook(Long input) {
+ if (input == null) {
+ return null;
+ }
+ return Long.reverseBytes(input);
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ return new LongSwapEndianModification();
+ }
+
+ @Override
+ public int hashCode() {
+ return 7;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ return getClass() == obj.getClass();
+ }
+
+ @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 c9755784..9407bed8 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/longint/LongXorModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/LongXorModification.java
@@ -21,15 +21,28 @@ public class LongXorModification extends VariableModification {
private Long xor;
- public LongXorModification() {}
+ public LongXorModification() {
+ super();
+ }
+
+ public LongXorModification(Long xor) {
+ super();
+ this.xor = xor;
+ }
+
+ public LongXorModification(LongXorModification other) {
+ super(other);
+ xor = other.xor;
+ }
- public LongXorModification(Long bi) {
- this.xor = bi;
+ @Override
+ public LongXorModification createCopy() {
+ return new LongXorModification(this);
}
@Override
- protected Long modifyImplementationHook(final Long input) {
- return (input == null) ? xor : input ^ xor;
+ protected Long modifyImplementationHook(Long input) {
+ return input == null ? xor : input ^ xor;
}
public Long getXor() {
@@ -44,16 +57,16 @@ public void setXor(Long xor) {
public VariableModification getModifiedCopy() {
Random r = new Random();
if (r.nextBoolean()) {
- return new LongXorModification(xor + new Random().nextInt(MAX_XOR_MODIFIER));
+ return new LongXorModification(xor + r.nextInt(MAX_XOR_MODIFIER));
} else {
- return new LongXorModification(xor - new Random().nextInt(MAX_XOR_MODIFIER));
+ return new LongXorModification(xor - r.nextInt(MAX_XOR_MODIFIER));
}
}
@Override
public int hashCode() {
- int hash = 3;
- hash = 59 * hash + Objects.hashCode(this.xor);
+ int hash = 7;
+ hash = 31 * hash + xor.hashCode();
return hash;
}
@@ -68,10 +81,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final LongXorModification other = (LongXorModification) obj;
- if (!Objects.equals(this.xor, other.xor)) {
- return false;
- }
- return true;
+ LongXorModification other = (LongXorModification) obj;
+ return Objects.equals(xor, other.xor);
+ }
+
+ @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 5e75ea3f..44c233a4 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/longint/ModifiableLong.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/longint/ModifiableLong.java
@@ -20,8 +20,27 @@ public class ModifiableLong extends ModifiableVariable {
private Long originalValue;
+ public ModifiableLong() {
+ super();
+ }
+
+ public ModifiableLong(Long originalValue) {
+ super();
+ this.originalValue = originalValue;
+ }
+
+ public ModifiableLong(ModifiableLong other) {
+ super(other);
+ originalValue = other.originalValue;
+ }
+
+ @Override
+ public ModifiableLong createCopy() {
+ return new ModifiableLong(this);
+ }
+
@Override
- protected void createRandomModification() {
+ public void setRandomModification() {
VariableModification vm = LongModificationFactory.createRandomModification();
setModification(vm);
}
@@ -66,19 +85,19 @@ public void setOriginalValue(Long originalValue) {
@Override
public String toString() {
- return "ModifiableLong{" + "originalValue=" + originalValue + '}';
+ return "ModifiableLong{" + "originalValue=" + originalValue + innerToString() + '}';
}
@Override
- public boolean equals(Object o) {
- if (this == o) {
+ public boolean equals(Object obj) {
+ if (this == obj) {
return true;
}
- if (!(o instanceof ModifiableLong)) {
+ if (!(obj instanceof ModifiableLong)) {
return false;
}
- ModifiableLong that = (ModifiableLong) o;
+ ModifiableLong that = (ModifiableLong) obj;
return getValue() != null ? getValue().equals(that.getValue()) : that.getValue() == null;
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/path/ModifiablePath.java b/src/main/java/de/rub/nds/modifiablevariable/path/ModifiablePath.java
new file mode 100644
index 00000000..b3566ea1
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/path/ModifiablePath.java
@@ -0,0 +1,68 @@
+/*
+ * 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.path;
+
+import static de.rub.nds.modifiablevariable.util.StringUtil.backslashEscapeString;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import de.rub.nds.modifiablevariable.string.ModifiableString;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ModifiablePath extends ModifiableString {
+
+ public ModifiablePath() {
+ super();
+ }
+
+ public ModifiablePath(String originalValue) {
+ super(originalValue);
+ }
+
+ public ModifiablePath(ModifiablePath other) {
+ super(other);
+ }
+
+ @Override
+ public ModifiablePath createCopy() {
+ return new ModifiablePath(this);
+ }
+
+ @Override
+ public void setRandomModification() {
+ VariableModification vm = PathModificationFactory.createRandomModification(null);
+ setModification(vm);
+ }
+
+ @Override
+ public String toString() {
+ return "ModifiablePath{"
+ + "originalValue='"
+ + backslashEscapeString(originalValue)
+ + '\''
+ + innerToString()
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof ModifiablePath)) {
+ return false;
+ }
+
+ ModifiablePath that = (ModifiablePath) obj;
+
+ return getValue() != null ? getValue().equals(that.getValue()) : that.getValue() == null;
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/path/PathAppendValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/path/PathAppendValueModification.java
new file mode 100644
index 00000000..1a806de9
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/path/PathAppendValueModification.java
@@ -0,0 +1,108 @@
+/*
+ * 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.path;
+
+import static de.rub.nds.modifiablevariable.util.StringUtil.backslashEscapeString;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import de.rub.nds.modifiablevariable.util.IllegalStringAdapter;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import java.util.Objects;
+import java.util.Random;
+
+/** Modification that appends a path parts to the original value. */
+@XmlRootElement
+@XmlType(propOrder = {"appendValue", "modificationFilter"})
+public class PathAppendValueModification extends VariableModification {
+
+ private static final int MAX_EXPLICIT_VALUE = 256;
+
+ @XmlJavaTypeAdapter(IllegalStringAdapter.class)
+ private String appendValue;
+
+ public PathAppendValueModification() {
+ super();
+ }
+
+ public PathAppendValueModification(String appendValue) {
+ super();
+ this.appendValue = appendValue;
+ }
+
+ public PathAppendValueModification(PathAppendValueModification other) {
+ super(other);
+ appendValue = other.appendValue;
+ }
+
+ @Override
+ public PathAppendValueModification createCopy() {
+ return new PathAppendValueModification(this);
+ }
+
+ @Override
+ protected String modifyImplementationHook(String input) {
+ if (input == null) {
+ return null;
+ }
+ if (input.endsWith("/")) {
+ return input + appendValue + "/";
+ }
+ return input + "/" + appendValue;
+ }
+
+ public String getAppendValue() {
+ return appendValue;
+ }
+
+ public void setAppendValue(String appendValue) {
+ this.appendValue = appendValue;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+ int index = r.nextInt(appendValue.length());
+ char randomChar = (char) r.nextInt(MAX_EXPLICIT_VALUE);
+ StringBuilder modifiedString = new StringBuilder(appendValue);
+ modifiedString.setCharAt(index, randomChar);
+ return new PathAppendValueModification(modifiedString.toString());
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + appendValue.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ PathAppendValueModification other = (PathAppendValueModification) obj;
+ return Objects.equals(appendValue, other.appendValue);
+ }
+
+ @Override
+ public String toString() {
+ return "PathAppendValueModification{"
+ + "appendValue='"
+ + backslashEscapeString(appendValue)
+ + '\''
+ + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/path/PathDeleteModification.java b/src/main/java/de/rub/nds/modifiablevariable/path/PathDeleteModification.java
new file mode 100644
index 00000000..3de7c144
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/path/PathDeleteModification.java
@@ -0,0 +1,161 @@
+/*
+ * 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.path;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import de.rub.nds.modifiablevariable.util.ArrayConverter;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.Random;
+
+/** Modification that deletes path parts from the original value. */
+@XmlRootElement
+@XmlType(propOrder = {"count", "startPosition", "modificationFilter"})
+public class PathDeleteModification extends VariableModification {
+
+ private static final int MAX_MODIFIER_LENGTH = 32;
+
+ private int count;
+
+ private int startPosition;
+
+ public PathDeleteModification() {
+ super();
+ }
+
+ public PathDeleteModification(int startPosition, int count) {
+ super();
+ this.count = count;
+ this.startPosition = startPosition;
+ }
+
+ public PathDeleteModification(PathDeleteModification other) {
+ super(other);
+ count = other.count;
+ startPosition = other.startPosition;
+ }
+
+ @Override
+ public PathDeleteModification createCopy() {
+ return new PathDeleteModification(this);
+ }
+
+ @Override
+ protected String modifyImplementationHook(String input) {
+ if (input == null) {
+ return null;
+ }
+ if (input.isEmpty()) {
+ return input;
+ }
+ String[] pathParts = input.split("/");
+ boolean leadingSlash = pathParts[0].isEmpty();
+
+ // Wrap around and also allow to delete at the end of the original value
+ int deleteStartPosition =
+ PathUtil.getPathPartPosition(startPosition, leadingSlash, pathParts);
+ // If the end position overflows, it is fixed at the end of the path
+ int deleteEndPosition = deleteStartPosition + count;
+ if (deleteEndPosition > pathParts.length) {
+ deleteEndPosition = pathParts.length;
+ }
+
+ String[] partsBefore = Arrays.copyOf(pathParts, deleteStartPosition);
+ String[] partsAfter = null;
+ if (deleteEndPosition < pathParts.length) {
+ partsAfter = Arrays.copyOfRange(pathParts, deleteEndPosition, pathParts.length);
+ }
+ String[] resultParts = ArrayConverter.concatenate(partsBefore, partsAfter);
+
+ if (input.endsWith("/") && resultParts.length > 0) {
+ resultParts[resultParts.length - 1] += "/";
+ }
+ return String.join("/", resultParts);
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ }
+
+ public int getStartPosition() {
+ return startPosition;
+ }
+
+ public void setStartPosition(int startPosition) {
+ this.startPosition = startPosition;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+
+ if (r.nextBoolean()) {
+ int modifier = r.nextInt(MAX_MODIFIER_LENGTH);
+ if (r.nextBoolean()) {
+ modifier *= -1;
+ }
+ modifier = count + modifier;
+ if (modifier <= 0) {
+ modifier = 1;
+ }
+ return new PathDeleteModification(modifier, startPosition);
+ } else {
+ int modifier = r.nextInt(MAX_MODIFIER_LENGTH);
+ if (r.nextBoolean()) {
+ modifier *= -1;
+ }
+ modifier = startPosition + modifier;
+ if (modifier <= 0) {
+ modifier = 1;
+ }
+ return new PathDeleteModification(count, modifier);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + count;
+ hash = 31 * hash + startPosition;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ PathDeleteModification other = (PathDeleteModification) obj;
+ if (startPosition != other.startPosition) {
+ return false;
+ }
+ return Objects.equals(count, other.count);
+ }
+
+ @Override
+ public String toString() {
+ return "PathDeleteModification{"
+ + "count="
+ + count
+ + ", startPosition="
+ + startPosition
+ + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/path/PathExplicitValueFromFileModification.java b/src/main/java/de/rub/nds/modifiablevariable/path/PathExplicitValueFromFileModification.java
new file mode 100644
index 00000000..7d78424e
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/path/PathExplicitValueFromFileModification.java
@@ -0,0 +1,89 @@
+/*
+ * 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.path;
+
+import static de.rub.nds.modifiablevariable.util.StringUtil.backslashEscapeString;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+
+@XmlRootElement
+@XmlType(propOrder = "index")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class PathExplicitValueFromFileModification extends PathExplicitValueModification {
+ private int index;
+
+ public PathExplicitValueFromFileModification() {
+ super();
+ }
+
+ public PathExplicitValueFromFileModification(int index, String explicitValue) {
+ super(explicitValue);
+ this.index = index;
+ }
+
+ public PathExplicitValueFromFileModification(PathExplicitValueFromFileModification other) {
+ super(other);
+ index = other.index;
+ }
+
+ @Override
+ public PathExplicitValueFromFileModification createCopy() {
+ return new PathExplicitValueFromFileModification(this);
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ throw new UnsupportedOperationException(
+ "Cannot set modify Value of PathExplicitValueFromFileModification");
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + index;
+ hash = 31 * hash + explicitValue.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ PathExplicitValueFromFileModification other = (PathExplicitValueFromFileModification) obj;
+ if (index != other.index) {
+ return false;
+ }
+ return Objects.equals(explicitValue, other.explicitValue);
+ }
+
+ @Override
+ public String toString() {
+ return "PathExplicitValueFromFileModification{"
+ + "index="
+ + index
+ + ", explicitValue="
+ + backslashEscapeString(explicitValue)
+ + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/path/PathExplicitValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/path/PathExplicitValueModification.java
new file mode 100644
index 00000000..d5ea0b6c
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/path/PathExplicitValueModification.java
@@ -0,0 +1,104 @@
+/*
+ * 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.path;
+
+import static de.rub.nds.modifiablevariable.util.StringUtil.backslashEscapeString;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import de.rub.nds.modifiablevariable.util.IllegalStringAdapter;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import java.util.Objects;
+import java.util.Random;
+
+@XmlRootElement
+@XmlType(propOrder = {"explicitValue", "modificationFilter"})
+public class PathExplicitValueModification extends VariableModification {
+
+ private static final int MAX_EXPLICIT_VALUE = 256;
+
+ @XmlJavaTypeAdapter(IllegalStringAdapter.class)
+ protected String explicitValue;
+
+ public PathExplicitValueModification() {
+ super();
+ }
+
+ public PathExplicitValueModification(String explicitValue) {
+ super();
+ this.explicitValue = explicitValue;
+ }
+
+ public PathExplicitValueModification(PathExplicitValueModification other) {
+ super(other);
+ explicitValue = other.explicitValue;
+ }
+
+ @Override
+ public PathExplicitValueModification createCopy() {
+ return new PathExplicitValueModification(this);
+ }
+
+ @Override
+ protected String modifyImplementationHook(String input) {
+ return explicitValue;
+ }
+
+ public String getExplicitValue() {
+ return explicitValue;
+ }
+
+ public void setExplicitValue(String explicitValue) {
+ this.explicitValue = explicitValue;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ if (explicitValue.isEmpty()) {
+ return this;
+ }
+ Random r = new Random();
+ int index = r.nextInt(explicitValue.length());
+ char randomChar = (char) r.nextInt(MAX_EXPLICIT_VALUE);
+ StringBuilder modifiedString = new StringBuilder(explicitValue);
+ modifiedString.setCharAt(index, randomChar);
+ return new PathExplicitValueModification(modifiedString.toString());
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + explicitValue.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ PathExplicitValueModification other = (PathExplicitValueModification) obj;
+ return Objects.equals(explicitValue, other.explicitValue);
+ }
+
+ @Override
+ public String toString() {
+ return "PathExplicitValueModification{"
+ + "explicitValue='"
+ + backslashEscapeString(explicitValue)
+ + '\''
+ + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/path/PathInsertDirectorySeparatorModification.java b/src/main/java/de/rub/nds/modifiablevariable/path/PathInsertDirectorySeparatorModification.java
new file mode 100644
index 00000000..0dfa225d
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/path/PathInsertDirectorySeparatorModification.java
@@ -0,0 +1,147 @@
+/*
+ * 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.path;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import de.rub.nds.modifiablevariable.util.IllegalStringAdapter;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import java.util.Objects;
+import java.util.Random;
+
+/** Modification that inserts directory separators as path parts to the original value. */
+@XmlRootElement
+@XmlType(propOrder = {"insertValue", "count", "startPosition", "modificationFilter"})
+public class PathInsertDirectorySeparatorModification extends VariableModification {
+
+ private static final int MAX_INSERT_MODIFIER = 32;
+
+ @XmlJavaTypeAdapter(IllegalStringAdapter.class)
+ private String insertValue;
+
+ private int count;
+ private int startPosition;
+
+ public PathInsertDirectorySeparatorModification() {
+ super();
+ }
+
+ public PathInsertDirectorySeparatorModification(int count, int startPosition) {
+ super();
+ this.count = count;
+ this.startPosition = startPosition;
+ updateInsertValue();
+ }
+
+ public PathInsertDirectorySeparatorModification(
+ PathInsertDirectorySeparatorModification other) {
+ super(other);
+ insertValue = other.insertValue;
+ count = other.count;
+ startPosition = other.startPosition;
+ }
+
+ @Override
+ public PathInsertDirectorySeparatorModification createCopy() {
+ return new PathInsertDirectorySeparatorModification(this);
+ }
+
+ private void updateInsertValue() {
+ insertValue = "/".repeat(Math.max(0, count));
+ }
+
+ @Override
+ protected String modifyImplementationHook(String input) {
+ return PathUtil.insertValueAsPathPart(input, insertValue, startPosition);
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ updateInsertValue();
+ }
+
+ public int getStartPosition() {
+ return startPosition;
+ }
+
+ public void setStartPosition(int startPosition) {
+ this.startPosition = startPosition;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+
+ if (r.nextBoolean()) {
+ int modifier = r.nextInt(MAX_INSERT_MODIFIER);
+ if (r.nextBoolean()) {
+ modifier *= -1;
+ }
+ modifier = count + modifier;
+ if (modifier <= 0) {
+ modifier = 1;
+ }
+ return new PathInsertDirectorySeparatorModification(modifier, startPosition);
+ } else {
+ int modifier = r.nextInt(MAX_INSERT_MODIFIER);
+ if (r.nextBoolean()) {
+ modifier *= -1;
+ }
+ modifier = startPosition + modifier;
+ if (modifier <= 0) {
+ modifier = 1;
+ }
+ return new PathInsertDirectorySeparatorModification(count, modifier);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + count;
+ hash = 31 * hash + startPosition;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ PathInsertDirectorySeparatorModification other =
+ (PathInsertDirectorySeparatorModification) obj;
+ if (startPosition != other.startPosition) {
+ return false;
+ }
+ return Objects.equals(count, other.count);
+ }
+
+ @Override
+ public String toString() {
+ return "PathInsertDirectorySeparatorModification{"
+ + "insertValue='"
+ + insertValue
+ + '\''
+ + ", count="
+ + count
+ + ", startPosition="
+ + startPosition
+ + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/path/PathInsertDirectoryTraversalModification.java b/src/main/java/de/rub/nds/modifiablevariable/path/PathInsertDirectoryTraversalModification.java
new file mode 100644
index 00000000..1e22284c
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/path/PathInsertDirectoryTraversalModification.java
@@ -0,0 +1,158 @@
+/*
+ * 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.path;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import de.rub.nds.modifiablevariable.util.IllegalStringAdapter;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import java.util.Objects;
+import java.util.Random;
+
+/** Modification that directory traversal path parts the original value. */
+@XmlRootElement
+@XmlType(propOrder = {"insertValue", "count", "startPosition", "modificationFilter"})
+public class PathInsertDirectoryTraversalModification extends VariableModification {
+
+ private static final int MAX_INSERT_MODIFIER = 32;
+
+ @XmlJavaTypeAdapter(IllegalStringAdapter.class)
+ private String insertValue;
+
+ private int count;
+ private int startPosition;
+
+ public PathInsertDirectoryTraversalModification() {
+ super();
+ }
+
+ public PathInsertDirectoryTraversalModification(int count, int startPosition) {
+ super();
+ this.count = count;
+ this.startPosition = startPosition;
+ updateInsertValue();
+ }
+
+ public PathInsertDirectoryTraversalModification(
+ PathInsertDirectoryTraversalModification other) {
+ super(other);
+ insertValue = other.insertValue;
+ count = other.count;
+ startPosition = other.startPosition;
+ }
+
+ @Override
+ public PathInsertDirectoryTraversalModification createCopy() {
+ return new PathInsertDirectoryTraversalModification(this);
+ }
+
+ private void updateInsertValue() {
+ if (count <= 0) {
+ insertValue = "";
+ return;
+ }
+ StringBuilder builder = new StringBuilder(count * 3 - 1);
+ for (int i = 0; i < count; i++) {
+ builder.append("..");
+ if (i < count - 1) {
+ builder.append("/");
+ }
+ }
+ insertValue = builder.toString();
+ }
+
+ @Override
+ protected String modifyImplementationHook(String input) {
+ return PathUtil.insertValueAsPathPart(input, insertValue, startPosition);
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ updateInsertValue();
+ }
+
+ public int getStartPosition() {
+ return startPosition;
+ }
+
+ public void setStartPosition(int startPosition) {
+ this.startPosition = startPosition;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+
+ if (r.nextBoolean()) {
+ int modifier = r.nextInt(MAX_INSERT_MODIFIER);
+ if (r.nextBoolean()) {
+ modifier *= -1;
+ }
+ modifier = count + modifier;
+ if (modifier <= 0) {
+ modifier = 1;
+ }
+ return new PathInsertDirectoryTraversalModification(modifier, startPosition);
+ } else {
+ int modifier = r.nextInt(MAX_INSERT_MODIFIER);
+ if (r.nextBoolean()) {
+ modifier *= -1;
+ }
+ modifier = startPosition + modifier;
+ if (modifier <= 0) {
+ modifier = 1;
+ }
+ return new PathInsertDirectoryTraversalModification(count, modifier);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + count;
+ hash = 31 * hash + startPosition;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ PathInsertDirectoryTraversalModification other =
+ (PathInsertDirectoryTraversalModification) obj;
+ if (startPosition != other.startPosition) {
+ return false;
+ }
+ return Objects.equals(count, other.count);
+ }
+
+ @Override
+ public String toString() {
+ return "PathInsertDirectoryTraversalModification{"
+ + "insertValue='"
+ + insertValue
+ + '\''
+ + ", count="
+ + count
+ + ", startPosition="
+ + startPosition
+ + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/path/PathInsertValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/path/PathInsertValueModification.java
new file mode 100644
index 00000000..60ab6dc5
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/path/PathInsertValueModification.java
@@ -0,0 +1,135 @@
+/*
+ * 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.path;
+
+import static de.rub.nds.modifiablevariable.util.StringUtil.backslashEscapeString;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import de.rub.nds.modifiablevariable.util.IllegalStringAdapter;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import java.util.Objects;
+import java.util.Random;
+
+/** Modification that inserts path parts to the original value. */
+@XmlRootElement
+@XmlType(propOrder = {"insertValue", "startPosition", "modificationFilter"})
+public class PathInsertValueModification extends VariableModification {
+
+ private static final int MAX_EXPLICIT_VALUE = 256;
+
+ private static final int MAX_INSERT_MODIFIER = 32;
+
+ @XmlJavaTypeAdapter(IllegalStringAdapter.class)
+ private String insertValue;
+
+ private int startPosition;
+
+ public PathInsertValueModification() {
+ super();
+ }
+
+ public PathInsertValueModification(String insertValue, int startPosition) {
+ super();
+ this.insertValue = insertValue;
+ this.startPosition = startPosition;
+ }
+
+ public PathInsertValueModification(PathInsertValueModification other) {
+ super(other);
+ insertValue = other.insertValue;
+ startPosition = other.startPosition;
+ }
+
+ @Override
+ public PathInsertValueModification createCopy() {
+ return new PathInsertValueModification(this);
+ }
+
+ @Override
+ protected String modifyImplementationHook(String input) {
+ return PathUtil.insertValueAsPathPart(input, insertValue, startPosition);
+ }
+
+ public String getInsertValue() {
+ return insertValue;
+ }
+
+ public void setInsertValue(String insertValue) {
+ this.insertValue = insertValue;
+ }
+
+ public int getStartPosition() {
+ return startPosition;
+ }
+
+ public void setStartPosition(int startPosition) {
+ this.startPosition = startPosition;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+
+ if (r.nextBoolean()) {
+ int index = r.nextInt(insertValue.length());
+ char randomChar = (char) r.nextInt(MAX_EXPLICIT_VALUE);
+ StringBuilder modifiedString = new StringBuilder(insertValue);
+ modifiedString.setCharAt(index, randomChar);
+ return new PathInsertValueModification(modifiedString.toString(), startPosition);
+ } else {
+ int modifier = r.nextInt(MAX_INSERT_MODIFIER);
+ if (r.nextBoolean()) {
+ modifier *= -1;
+ }
+ modifier = startPosition + modifier;
+ if (modifier <= 0) {
+ modifier = 1;
+ }
+ return new PathInsertValueModification(insertValue, modifier);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + insertValue.hashCode();
+ hash = 31 * hash + startPosition;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ PathInsertValueModification other = (PathInsertValueModification) obj;
+ if (startPosition != other.startPosition) {
+ return false;
+ }
+ return Objects.equals(insertValue, other.insertValue);
+ }
+
+ @Override
+ public String toString() {
+ return "PathInsertValueModification{"
+ + "insertValue='"
+ + backslashEscapeString(insertValue)
+ + '\''
+ + ", startPosition="
+ + startPosition
+ + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/path/PathModificationFactory.java b/src/main/java/de/rub/nds/modifiablevariable/path/PathModificationFactory.java
new file mode 100644
index 00000000..f143360d
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/path/PathModificationFactory.java
@@ -0,0 +1,146 @@
+/*
+ * 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.path;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import de.rub.nds.modifiablevariable.string.StringDeleteModification;
+import de.rub.nds.modifiablevariable.util.RandomHelper;
+import java.util.Random;
+
+/** */
+public final class PathModificationFactory {
+
+ private PathModificationFactory() {
+ super();
+ }
+
+ private enum ModificationType {
+ APPEND,
+ PREPEND,
+ INSERT,
+ DELETE,
+ INSERT_DIRECTORY_TRAVERSAL,
+ INSERT_DIRECTORY_SEPERATOR,
+ TOGGLE_ROOT
+ }
+
+ private static final int MODIFICATION_COUNT = ModificationType.values().length;
+
+ private static final int MAX_BYTE_LENGTH_INSERT = 200;
+
+ private static final int NUMBER_OF_PATH_PARTS_ESTIMATION = 50;
+
+ private static final int MAX_NUMBER_OF_DIRECTORY_TRAVERSAL_INSERT = 10;
+ private static final int MAX_NUMBER_OF_DIRECTORY_SEPERATOR_INSERT = 10;
+
+ public static VariableModification prependValue(String value) {
+ return new PathPrependValueModification(value);
+ }
+
+ public static VariableModification explicitValue(String value) {
+ return new PathExplicitValueModification(value);
+ }
+
+ public static VariableModification appendValue(String value) {
+ return new PathAppendValueModification(value);
+ }
+
+ public static VariableModification insertValue(String value, int position) {
+ return new PathInsertValueModification(value, position);
+ }
+
+ public static VariableModification delete(int position, int count) {
+ return new PathDeleteModification(position, count);
+ }
+
+ public static VariableModification insertDirectoryTraversal(int count, int position) {
+ return new PathInsertDirectoryTraversalModification(count, position);
+ }
+
+ public static VariableModification insertDirectorySeperator(int count, int position) {
+ return new PathInsertDirectorySeparatorModification(count, position);
+ }
+
+ public static VariableModification toggleRoot() {
+ return new PathToggleRootModification();
+ }
+
+ public static VariableModification createRandomModification(String originalValue) {
+ Random random = RandomHelper.getRandom();
+ ModificationType randomType = ModificationType.values()[random.nextInt(MODIFICATION_COUNT)];
+ int modificationStringLength;
+ int numberOfPathParts;
+ if (originalValue == null) {
+ numberOfPathParts = NUMBER_OF_PATH_PARTS_ESTIMATION;
+ } else {
+ String[] pathParts = originalValue.split("/");
+ if (pathParts.length == 0) {
+ if (randomType == ModificationType.INSERT
+ || randomType == ModificationType.DELETE) {
+ randomType = ModificationType.APPEND;
+ }
+ numberOfPathParts = 0;
+ } else {
+ if (pathParts[0].isEmpty()) {
+ numberOfPathParts = originalValue.split("/").length - 1;
+ } else {
+ numberOfPathParts = originalValue.split("/").length;
+ }
+ }
+ }
+ int insertPosition;
+ switch (randomType) {
+ case APPEND:
+ modificationStringLength = random.nextInt(MAX_BYTE_LENGTH_INSERT);
+ if (modificationStringLength == 0) {
+ modificationStringLength++;
+ }
+ byte[] bytesToAppend = new byte[modificationStringLength];
+ random.nextBytes(bytesToAppend);
+ return new PathAppendValueModification(new String(bytesToAppend));
+ case PREPEND:
+ modificationStringLength = random.nextInt(MAX_BYTE_LENGTH_INSERT);
+ if (modificationStringLength == 0) {
+ modificationStringLength++;
+ }
+ byte[] bytesToPrepend = new byte[modificationStringLength];
+ random.nextBytes(bytesToPrepend);
+ return new PathPrependValueModification(new String(bytesToPrepend));
+ case INSERT:
+ modificationStringLength = random.nextInt(MAX_BYTE_LENGTH_INSERT);
+ if (modificationStringLength == 0) {
+ modificationStringLength++;
+ }
+ byte[] bytesToInsert = new byte[modificationStringLength];
+ random.nextBytes(bytesToInsert);
+ insertPosition = random.nextInt(numberOfPathParts);
+ return new PathInsertValueModification(new String(bytesToInsert), insertPosition);
+ case INSERT_DIRECTORY_TRAVERSAL:
+ int numberOfDirectoryTraversal =
+ random.nextInt(MAX_NUMBER_OF_DIRECTORY_TRAVERSAL_INSERT);
+ insertPosition = random.nextInt(numberOfPathParts);
+ return new PathInsertDirectoryTraversalModification(
+ numberOfDirectoryTraversal, insertPosition);
+ case INSERT_DIRECTORY_SEPERATOR:
+ int numberOfDirectorySeperator =
+ random.nextInt(MAX_NUMBER_OF_DIRECTORY_SEPERATOR_INSERT);
+ insertPosition = random.nextInt(numberOfPathParts);
+ return new PathInsertDirectorySeparatorModification(
+ numberOfDirectorySeperator, insertPosition);
+ case TOGGLE_ROOT:
+ return new PathToggleRootModification();
+ case DELETE:
+ int startPosition = random.nextInt(numberOfPathParts - 1);
+ int count = random.nextInt(numberOfPathParts - startPosition);
+ count++;
+ return new StringDeleteModification(startPosition, count);
+ default:
+ throw new IllegalStateException("Unexpected modification type: " + randomType);
+ }
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/path/PathPrependValueModification.java b/src/main/java/de/rub/nds/modifiablevariable/path/PathPrependValueModification.java
new file mode 100644
index 00000000..e56f147f
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/path/PathPrependValueModification.java
@@ -0,0 +1,108 @@
+/*
+ * 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.path;
+
+import static de.rub.nds.modifiablevariable.util.StringUtil.backslashEscapeString;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import de.rub.nds.modifiablevariable.util.IllegalStringAdapter;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import java.util.Objects;
+import java.util.Random;
+
+/** Modification that prepends a string to the original value. */
+@XmlRootElement
+@XmlType(propOrder = {"prependValue", "modificationFilter"})
+public class PathPrependValueModification extends VariableModification {
+
+ private static final int MAX_EXPLICIT_VALUE = 256;
+
+ @XmlJavaTypeAdapter(IllegalStringAdapter.class)
+ private String prependValue;
+
+ public PathPrependValueModification() {
+ super();
+ }
+
+ public PathPrependValueModification(String prependValue) {
+ super();
+ this.prependValue = prependValue;
+ }
+
+ public PathPrependValueModification(PathPrependValueModification other) {
+ super(other);
+ prependValue = other.prependValue;
+ }
+
+ @Override
+ public PathPrependValueModification createCopy() {
+ return new PathPrependValueModification(this);
+ }
+
+ @Override
+ protected String modifyImplementationHook(String input) {
+ if (input == null) {
+ return null;
+ }
+ if (input.startsWith("/")) {
+ return "/" + prependValue + input;
+ }
+ return prependValue + "/" + input;
+ }
+
+ public String getPrependValue() {
+ return prependValue;
+ }
+
+ public void setPrependValue(String prependValue) {
+ this.prependValue = prependValue;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ Random r = new Random();
+ int index = r.nextInt(prependValue.length());
+ char randomChar = (char) r.nextInt(MAX_EXPLICIT_VALUE);
+ StringBuilder modifiedString = new StringBuilder(prependValue);
+ modifiedString.setCharAt(index, randomChar);
+ return new PathPrependValueModification(modifiedString.toString());
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + prependValue.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ PathPrependValueModification other = (PathPrependValueModification) obj;
+ return Objects.equals(prependValue, other.prependValue);
+ }
+
+ @Override
+ public String toString() {
+ return "PathPrependValueModification{"
+ + "prependValue='"
+ + backslashEscapeString(prependValue)
+ + '\''
+ + '}';
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/path/PathToggleRootModification.java b/src/main/java/de/rub/nds/modifiablevariable/path/PathToggleRootModification.java
new file mode 100644
index 00000000..8d6ee3e8
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/path/PathToggleRootModification.java
@@ -0,0 +1,68 @@
+/*
+ * 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.path;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+
+/** Modification that toggle the root slash of the original value. */
+@XmlRootElement
+@XmlType(propOrder = "modificationFilter")
+public class PathToggleRootModification extends VariableModification {
+
+ public PathToggleRootModification() {
+ super();
+ }
+
+ public PathToggleRootModification(PathToggleRootModification other) {
+ super(other);
+ }
+
+ @Override
+ public PathToggleRootModification createCopy() {
+ return new PathToggleRootModification(this);
+ }
+
+ @Override
+ protected String modifyImplementationHook(String input) {
+ if (input == null) {
+ return null;
+ }
+ if (!input.isEmpty() && input.charAt(0) == '/') {
+ return input.substring(1);
+ }
+ return "/" + input;
+ }
+
+ @Override
+ public VariableModification getModifiedCopy() {
+ return new PathToggleRootModification();
+ }
+
+ @Override
+ public int hashCode() {
+ return 7;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ return getClass() == obj.getClass();
+ }
+
+ @Override
+ public String toString() {
+ return "PathToggleRootModification{}";
+ }
+}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/path/PathUtil.java b/src/main/java/de/rub/nds/modifiablevariable/path/PathUtil.java
new file mode 100644
index 00000000..549f98ca
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/path/PathUtil.java
@@ -0,0 +1,81 @@
+/*
+ * 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.path;
+
+public final class PathUtil {
+
+ private PathUtil() {
+ super();
+ }
+
+ public static String insertValueAsPathPart(
+ String input, String insertValue, int startPosition) {
+ if (input == null) {
+ return null;
+ }
+
+ if (input.isEmpty()) {
+ return insertValue;
+ }
+ String[] pathParts = input.split("/");
+ boolean leadingSlash = pathParts[0].isEmpty();
+
+ // Wrap around and also allow to insert at the end of the original value
+ int insertPosition = getInsertPosition(startPosition, leadingSlash, pathParts);
+
+ if (insertPosition == 0 && leadingSlash) {
+ pathParts[insertPosition] = "/" + insertValue;
+ } else if (insertPosition == pathParts.length) {
+ pathParts[insertPosition - 1] = pathParts[insertPosition - 1] + "/" + insertValue;
+ } else {
+ pathParts[insertPosition] = insertValue + "/" + pathParts[insertPosition];
+ }
+ if (input.endsWith("/")) {
+ pathParts[pathParts.length - 1] += "/";
+ }
+ return String.join("/", pathParts);
+ }
+
+ private static int getInsertPosition(
+ int startPosition, boolean leadingSlash, String[] pathParts) {
+ int insertPosition;
+ if (leadingSlash) {
+ // If the path starts with a slash, skip the first empty path part.
+ insertPosition = startPosition % pathParts.length;
+ if (startPosition < 0) {
+ insertPosition += pathParts.length - 1;
+ }
+ insertPosition++;
+ } else {
+ insertPosition = startPosition % (pathParts.length + 1);
+ if (startPosition < 0) {
+ insertPosition += pathParts.length;
+ }
+ }
+ return insertPosition;
+ }
+
+ public static int getPathPartPosition(
+ int startPosition, boolean leadingSlash, String[] pathParts) {
+ int pathPartPosition;
+ if (leadingSlash) {
+ // If the path starts with a slash, skip the first empty path part.
+ pathPartPosition = startPosition % (pathParts.length - 1);
+ if (startPosition < 0) {
+ pathPartPosition += pathParts.length - 2;
+ }
+ pathPartPosition++;
+ } else {
+ pathPartPosition = startPosition % pathParts.length;
+ if (startPosition < 0) {
+ pathPartPosition += pathParts.length - 1;
+ }
+ }
+ return pathPartPosition;
+ }
+}
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 08d69948..2fd73b29 100644
--- a/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteAddModification.java
+++ b/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteAddModification.java
@@ -21,10 +21,23 @@ public class ByteAddModification extends VariableModification {
private Byte summand;
- public ByteAddModification() {}
+ public ByteAddModification() {
+ super();
+ }
+
+ public ByteAddModification(Byte summand) {
+ super();
+ this.summand = summand;
+ }
+
+ public ByteAddModification(ByteAddModification other) {
+ super(other);
+ summand = other.summand;
+ }
- public ByteAddModification(Byte bi) {
- this.summand = bi;
+ @Override
+ public ByteAddModification createCopy() {
+ return new ByteAddModification(this);
}
@Override
@@ -50,8 +63,8 @@ public VariableModification getModifiedCopy() {
@Override
public int hashCode() {
- int hash = 5;
- hash = 17 * hash + Objects.hashCode(this.summand);
+ int hash = 7;
+ hash = 31 * hash + summand;
return hash;
}
@@ -66,10 +79,12 @@ public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
- final ByteAddModification other = (ByteAddModification) obj;
- if (!Objects.equals(this.summand, other.summand)) {
- return false;
- }
- return true;
+ ByteAddModification other = (ByteAddModification) obj;
+ return Objects.equals(summand, other.summand);
+ }
+
+ @Override
+ public String toString() {
+ return "ByteAddModification{" + "summand=" + summand + '}';
}
}
diff --git a/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteExplicitValueFromFileModification.java b/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteExplicitValueFromFileModification.java
new file mode 100644
index 00000000..6460f962
--- /dev/null
+++ b/src/main/java/de/rub/nds/modifiablevariable/singlebyte/ByteExplicitValueFromFileModification.java
@@ -0,0 +1,87 @@
+/*
+ * 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.singlebyte;
+
+import de.rub.nds.modifiablevariable.VariableModification;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlType;
+import java.util.Objects;
+
+@XmlRootElement
+@XmlType(propOrder = "index")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ByteExplicitValueFromFileModification extends ByteExplicitValueModification {
+ private int index;
+
+ public ByteExplicitValueFromFileModification() {
+ super();
+ }
+
+ public ByteExplicitValueFromFileModification(int index, Byte explicitValue) {
+ super(explicitValue);
+ this.index = index;
+ }
+
+ public ByteExplicitValueFromFileModification(ByteExplicitValueFromFileModification other) {
+ super(other);
+ index = other.index;
+ }
+
+ @Override
+ public ByteExplicitValueFromFileModification createCopy() {
+ return new ByteExplicitValueFromFileModification(this);
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ @Override
+ public VariableModification