Skip to content

Commit 05e8fd6

Browse files
authored
Fix duplicated locals with arguments (#7683)
When hoisting local variables remove the locals that could be have the same name than arguments. This could happen resulting of the instrumentation by the tracer that reshuffle the local variable table and then reassign dedicated slots to those arguments
1 parent 1392830 commit 05e8fd6

File tree

4 files changed

+23
-6
lines changed

4 files changed

+23
-6
lines changed

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/CapturedContextInstrumentor.java

+16-2
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ private Collection<LocalVariableNode> initAndHoistLocalVars(InsnList insnList) {
476476
}
477477
checkHoistableLocalVar(localVar, localVarsByName, localVarsBySlot, hoistableVarByName);
478478
}
479+
removeDuplicatesFromArgs(hoistableVarByName, localVarsBySlotArray);
479480
// hoist vars
480481
List<LocalVariableNode> results = new ArrayList<>();
481482
for (Map.Entry<String, List<LocalVariableNode>> entry : hoistableVarByName.entrySet()) {
@@ -512,6 +513,19 @@ private Collection<LocalVariableNode> initAndHoistLocalVars(InsnList insnList) {
512513
return results;
513514
}
514515

516+
private void removeDuplicatesFromArgs(
517+
Map<String, List<LocalVariableNode>> hoistableVarByName,
518+
LocalVariableNode[] localVarsBySlotArray) {
519+
for (int idx = 0; idx < argOffset; idx++) {
520+
LocalVariableNode localVar = localVarsBySlotArray[idx];
521+
if (localVar == null) {
522+
continue;
523+
}
524+
// we are removing local variables that are arguments
525+
hoistableVarByName.remove(localVar.name);
526+
}
527+
}
528+
515529
private LabelNode findLatestLabel(InsnList instructions, Set<LabelNode> endLabels) {
516530
for (AbstractInsnNode insn = instructions.getLast(); insn != null; insn = insn.getPrevious()) {
517531
if (insn instanceof LabelNode && endLabels.contains(insn)) {
@@ -762,8 +776,8 @@ private void collectArguments(InsnList insnList, Snapshot.Kind kind) {
762776
int slot = isStatic ? 0 : 1;
763777
for (Type argType : argTypes) {
764778
String currentArgName = null;
765-
if (slot < localVarsBySlot.length) {
766-
LocalVariableNode localVarNode = localVarsBySlot[slot];
779+
if (slot < localVarsBySlotArray.length) {
780+
LocalVariableNode localVarNode = localVarsBySlotArray[slot];
767781
currentArgName = localVarNode != null ? localVarNode.name : null;
768782
}
769783
if (currentArgName == null) {

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/Instrumentor.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public abstract class Instrumentor {
4545
protected final LabelNode methodEnterLabel;
4646
protected int localVarBaseOffset;
4747
protected int argOffset;
48-
protected final LocalVariableNode[] localVarsBySlot;
48+
protected final LocalVariableNode[] localVarsBySlotArray;
4949
protected LabelNode returnHandlerLabel;
5050
protected final List<CapturedContextInstrumentor.FinallyBlock> finallyBlocks = new ArrayList<>();
5151

@@ -68,7 +68,7 @@ public Instrumentor(
6868
for (Type t : argTypes) {
6969
argOffset += t.getSize();
7070
}
71-
localVarsBySlot = extractLocalVariables(argTypes);
71+
localVarsBySlotArray = extractLocalVariables(argTypes);
7272
}
7373

7474
public abstract InstrumentationResult.Status instrument();

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/MetricInstrumentor.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -697,8 +697,8 @@ private ASMHelper.Type tryRetrieveArgument(String head, InsnList insnList) {
697697
int slot = instrumentor.isStatic ? 0 : 1;
698698
for (Type argType : argTypes) {
699699
String currentArgName = null;
700-
if (instrumentor.localVarsBySlot.length > 0) {
701-
LocalVariableNode localVarNode = instrumentor.localVarsBySlot[slot];
700+
if (instrumentor.localVarsBySlotArray.length > 0) {
701+
LocalVariableNode localVarNode = instrumentor.localVarsBySlotArray[slot];
702702
currentArgName = localVarNode != null ? localVarNode.name : null;
703703
}
704704
if (currentArgName == null) {

dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/TracerDebuggerIntegrationTest.java

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static org.junit.jupiter.api.Assertions.assertEquals;
55
import static org.junit.jupiter.api.Assertions.assertFalse;
66
import static org.junit.jupiter.api.Assertions.assertNotNull;
7+
import static org.junit.jupiter.api.Assertions.assertNull;
78
import static org.junit.jupiter.api.Assertions.assertTrue;
89

910
import com.datadog.debugger.agent.JsonSnapshotSerializer;
@@ -99,6 +100,8 @@ void testTracerSameMethod() throws Exception {
99100
Snapshot snapshot = request.getDebugger().getSnapshot();
100101
assertEquals(PROBE_ID.getId(), snapshot.getProbe().getId());
101102
assertEquals(42, snapshot.getCaptures().getEntry().getArguments().get("argInt").getValue());
103+
// no locals captured
104+
assertNull(snapshot.getCaptures().getEntry().getLocals());
102105
assertTrue(Pattern.matches("[0-9a-f]+", request.getTraceId()));
103106
assertTrue(Pattern.matches("\\d+", request.getSpanId()));
104107
}

0 commit comments

Comments
 (0)