Skip to content

Commit

Permalink
Maintain id if generalize applied to two similar IdentifiedArrayRefer…
Browse files Browse the repository at this point in the history
…enceValue
  • Loading branch information
nmsa authored and Oberon Swings committed Nov 17, 2023
1 parent ece26d2 commit 8c64cbf
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package proguard.evaluation.value;

import java.util.Objects;
import proguard.classfile.Clazz;

/**
Expand Down Expand Up @@ -128,6 +129,26 @@ public int equal(ReferenceValue other)
// return generalize((ArrayReferenceValue)other);
// }

public ReferenceValue generalize(IdentifiedArrayReferenceValue other)
{
if (this.equals(other)) return this;

if (Objects.equals(this.type, other.type) &&
Objects.equals(this.id, other.id) &&
this.referencedClass == other.referencedClass &&
this.valuefactory == other.valuefactory)
{
return new IdentifiedArrayReferenceValue(
this.type,
this.referencedClass,
this.mayBeExtension || other.mayBeExtension,
this.arrayLength.generalize(other.arrayLength),
this.valuefactory,
this.id
);
}
return generalize((ArrayReferenceValue)other);
}

public int equal(IdentifiedArrayReferenceValue other)
{
Expand Down
77 changes: 72 additions & 5 deletions base/src/test/kotlin/proguard/DetailedArrayTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNot
import io.kotest.matchers.types.beInstanceOf
import io.kotest.matchers.types.shouldBeInstanceOf
import io.kotest.matchers.types.shouldNotBeInstanceOf
import proguard.evaluation.ExecutingInvocationUnit
import proguard.evaluation.PartialEvaluator
import proguard.evaluation.ParticularReferenceValueFactory
import proguard.evaluation.value.ArrayReferenceValue
import proguard.evaluation.value.DetailedArrayReferenceValue
import proguard.evaluation.value.DetailedArrayValueFactory
import proguard.evaluation.value.IdentifiedArrayReferenceValue
import proguard.evaluation.value.ParticularValueFactory
import proguard.evaluation.value.UnknownIntegerValue
import proguard.evaluation.value.ValueFactory
Expand All @@ -21,11 +23,7 @@ import proguard.testutils.PartialEvaluatorUtil
class DetailedArrayTest : FreeSpec({
val valueFactory: ValueFactory = ParticularValueFactory(DetailedArrayValueFactory(), ParticularReferenceValueFactory())
val invocationUnit = ExecutingInvocationUnit.Builder().build(valueFactory)
val partialEvaluator = PartialEvaluator(
valueFactory,
invocationUnit,
false
)
val partialEvaluator = PartialEvaluator(valueFactory, invocationUnit, false)

"Array values evaluated correctly" - {

Expand Down Expand Up @@ -328,4 +326,73 @@ class DetailedArrayTest : FreeSpec({
number shouldBe UnknownIntegerValue()
}
}

"Array reference generalization" - {
val code = JavaSource(
"Test.java",
"""
import java.util.Random;

public class Test {

Random r = new Random();

public void arrayReferenceTest() {
byte[] array = {0, 1, 2, 3, 4, 5};
array[1] = 11;
if (r.nextInt() > 5) {
array[5] = 55;
}
array[2] = 22;
}

public void arrayReferenceRedefinedTest() {
byte[] array = {0, 1, 2, 3, 4, 5};
array[1] = 11;
if (r.nextInt() > 5) {
array = new byte[]{5, 4, 3, 2, 1, 0};
}
array[2] = 22;
}
}
"""
)

val (classPool, _) = ClassPoolBuilder.fromSource(code, javacArguments = listOf("-g", "-source", "1.8", "-target", "1.8"))

"IdentifiedArrayReference generalize maintains id" {
val (instructions, variableTable) = PartialEvaluatorUtil.evaluate(
"Test",
"arrayReferenceTest",
"()V",
classPool,
partialEvaluator
)

val (aastoreInstruction, _) = instructions[26] // aastore
val firstArray = partialEvaluator
.getVariablesAfter(aastoreInstruction).getValue(variableTable["array"]!!)
firstArray.shouldBeInstanceOf<IdentifiedArrayReferenceValue>()

val (finalInstruction, _) = instructions.last()
val finalArray = partialEvaluator
.getVariablesAfter(finalInstruction).getValue(variableTable["array"]!!)
finalArray.shouldBeInstanceOf<IdentifiedArrayReferenceValue>()

finalArray.id shouldBe firstArray.id
finalArray.type shouldBe "[B"
}

"IdentifiedArrayReference redefined in branch generalize looses id" {
val (instructions, variableTable) = PartialEvaluatorUtil.evaluate(
"Test", "arrayReferenceRedefinedTest", "()V", classPool, partialEvaluator
)

val (instruction, _) = instructions.last()
val array = partialEvaluator.getVariablesAfter(instruction).getValue(variableTable["array"]!!)
array.shouldNotBeInstanceOf<IdentifiedArrayReferenceValue>()
array.shouldBeInstanceOf<ArrayReferenceValue>()
array.type shouldBe "[B"
}
}
})
1 change: 1 addition & 0 deletions docs/md/releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Enable new `PartialEvaluator` error message format by default.
- Add the ability to implement a custom renaming strategy for `ClassReferenceFixer`.
- Add new `MaxStackSizeComputer` to compute the maximum stack size of a code attribute which is more memory efficient than the existing `StackSizeComputer`.
- Add `IdentifiedArrayReferenceValue.generalize()` to maintain `ID` when applied to two instances with same `ID`.

## Version 9.1

Expand Down

0 comments on commit 8c64cbf

Please sign in to comment.