Skip to content

Commit 013f442

Browse files
committed
Add missing swap instruction
Fixes issue https://github.com/diffblue/test-gen/issues/103. Swap instruction was not handled in convert_instructions. Includes the original Groovy regression test which sparked the issue ("swap2") and a simpler unit test ("swap1") which was created using ASM.
1 parent f791fef commit 013f442

File tree

8 files changed

+314
-0
lines changed

8 files changed

+314
-0
lines changed

regression/cbmc-java/swap1/Swap.class

678 Bytes
Binary file not shown.

regression/cbmc-java/swap1/Swap.java

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
public class Swap {
2+
public static void main(String[] args) {
3+
int x = 5;
4+
int result = x - 2;
5+
assert result == -3;
6+
}
7+
}
+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import java.nio.file.Files;
2+
import java.nio.file.Paths;
3+
4+
import org.objectweb.asm.*;
5+
public class SwapDump implements Opcodes {
6+
7+
public static byte[] dump () throws Exception {
8+
9+
ClassWriter cw = new ClassWriter(0);
10+
FieldVisitor fv;
11+
MethodVisitor mv;
12+
13+
cw.visit(52, ACC_PUBLIC + ACC_SUPER, "Swap", null, "java/lang/Object", null);
14+
15+
cw.visitSource("Swap.java", null);
16+
17+
{
18+
fv = cw.visitField(ACC_FINAL + ACC_STATIC + ACC_SYNTHETIC, "$assertionsDisabled", "Z", null, null);
19+
fv.visitEnd();
20+
}
21+
{
22+
mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
23+
mv.visitCode();
24+
Label l0 = new Label();
25+
mv.visitLabel(l0);
26+
mv.visitLineNumber(1, l0);
27+
mv.visitLdcInsn(Type.getType("LSwap;"));
28+
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "desiredAssertionStatus", "()Z", false);
29+
Label l1 = new Label();
30+
mv.visitJumpInsn(IFNE, l1);
31+
mv.visitInsn(ICONST_1);
32+
Label l2 = new Label();
33+
mv.visitJumpInsn(GOTO, l2);
34+
mv.visitLabel(l1);
35+
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
36+
mv.visitInsn(ICONST_0);
37+
mv.visitLabel(l2);
38+
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {Opcodes.INTEGER});
39+
mv.visitFieldInsn(PUTSTATIC, "Swap", "$assertionsDisabled", "Z");
40+
mv.visitInsn(RETURN);
41+
mv.visitMaxs(1, 0);
42+
mv.visitEnd();
43+
}
44+
{
45+
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
46+
mv.visitCode();
47+
Label l0 = new Label();
48+
mv.visitLabel(l0);
49+
mv.visitLineNumber(1, l0);
50+
mv.visitVarInsn(ALOAD, 0);
51+
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
52+
mv.visitInsn(RETURN);
53+
Label l1 = new Label();
54+
mv.visitLabel(l1);
55+
mv.visitLocalVariable("this", "LSwap;", null, l0, l1, 0);
56+
mv.visitMaxs(1, 1);
57+
mv.visitEnd();
58+
}
59+
{
60+
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
61+
mv.visitCode();
62+
Label l0 = new Label();
63+
mv.visitLabel(l0);
64+
mv.visitLineNumber(3, l0);
65+
mv.visitInsn(ICONST_5);
66+
mv.visitVarInsn(ISTORE, 1);
67+
Label l1 = new Label();
68+
mv.visitLabel(l1);
69+
mv.visitLineNumber(4, l1);
70+
mv.visitVarInsn(ILOAD, 1);
71+
mv.visitInsn(ICONST_2);
72+
mv.visitInsn(SWAP); // Manually added
73+
mv.visitInsn(ISUB);
74+
mv.visitVarInsn(ISTORE, 2);
75+
Label l2 = new Label();
76+
mv.visitLabel(l2);
77+
mv.visitLineNumber(5, l2);
78+
mv.visitFieldInsn(GETSTATIC, "Swap", "$assertionsDisabled", "Z");
79+
Label l3 = new Label();
80+
mv.visitJumpInsn(IFNE, l3);
81+
mv.visitVarInsn(ILOAD, 2);
82+
mv.visitIntInsn(BIPUSH, -3);
83+
mv.visitJumpInsn(IF_ICMPEQ, l3);
84+
mv.visitTypeInsn(NEW, "java/lang/AssertionError");
85+
mv.visitInsn(DUP);
86+
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/AssertionError", "<init>", "()V", false);
87+
mv.visitInsn(ATHROW);
88+
mv.visitLabel(l3);
89+
mv.visitLineNumber(6, l3);
90+
mv.visitFrame(Opcodes.F_APPEND,2, new Object[] {Opcodes.INTEGER, Opcodes.INTEGER}, 0, null);
91+
mv.visitInsn(RETURN);
92+
Label l4 = new Label();
93+
mv.visitLabel(l4);
94+
mv.visitLocalVariable("args", "[Ljava/lang/String;", null, l0, l4, 0);
95+
mv.visitLocalVariable("x", "I", null, l1, l4, 1);
96+
mv.visitLocalVariable("result", "I", null, l2, l4, 2);
97+
mv.visitMaxs(2, 3);
98+
mv.visitEnd();
99+
}
100+
cw.visitEnd();
101+
102+
return cw.toByteArray();
103+
}
104+
105+
public static void main(String[] args) throws Exception {
106+
Files.write(Paths.get("Swap.class"), dump());
107+
}
108+
}

regression/cbmc-java/swap1/test.desc

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
Swap.class
3+
4+
^EXIT=0
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
* Copyright 2002-2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.build.gradle
18+
19+
import org.gradle.api.*
20+
import org.gradle.api.artifacts.Configuration
21+
import org.gradle.api.artifacts.ProjectDependency;
22+
import org.gradle.api.artifacts.maven.Conf2ScopeMapping
23+
import org.gradle.api.plugins.MavenPlugin
24+
import org.gradle.plugins.ide.eclipse.EclipsePlugin
25+
import org.gradle.plugins.ide.idea.IdeaPlugin
26+
import org.gradle.api.invocation.*
27+
28+
/**
29+
* Gradle plugin that allows projects to merged together. Primarily developed to
30+
* allow Spring to support multiple incompatible versions of third-party
31+
* dependencies (for example Hibernate v3 and v4).
32+
* <p>
33+
* The 'merge' extension should be used to define how projects are merged, for example:
34+
* <pre class="code">
35+
* configure(subprojects) {
36+
* apply plugin: MergePlugin
37+
* }
38+
*
39+
* project("myproject") {
40+
* }
41+
*
42+
* project("myproject-extra") {
43+
* merge.into = project("myproject")
44+
* }
45+
* </pre>
46+
* <p>
47+
* This plugin adds two new configurations:
48+
* <ul>
49+
* <li>merging - Contains the projects being merged into this project<li>
50+
* <li>runtimeMerge - Contains all dependencies that are merge projects. These are used
51+
* to allow an IDE to reference merge projects.</li>
52+
* <ul>
53+
*
54+
* @author Rob Winch
55+
* @author Phillip Webb
56+
*/
57+
class MergePlugin implements Plugin<Project> {
58+
59+
private static boolean attachedProjectsEvaluated;
60+
61+
public void apply(Project project) {
62+
project.plugins.apply(MavenPlugin)
63+
project.plugins.apply(EclipsePlugin)
64+
project.plugins.apply(IdeaPlugin)
65+
66+
MergeModel model = project.extensions.create("merge", MergeModel)
67+
model.project = project
68+
project.configurations.create("merging")
69+
Configuration runtimeMerge = project.configurations.create("runtimeMerge")
70+
71+
// Ensure the IDE can reference merged projects
72+
project.eclipse.classpath.plusConfigurations += [ runtimeMerge ]
73+
project.idea.module.scopes.PROVIDED.plus += [ runtimeMerge ]
74+
75+
// Hook to perform the actual merge logic
76+
project.afterEvaluate{
77+
if (it.merge.into != null) {
78+
setup(it)
79+
}
80+
setupIdeDependencies(it)
81+
}
82+
83+
// Hook to build runtimeMerge dependencies
84+
if (!attachedProjectsEvaluated) {
85+
project.gradle.projectsEvaluated{
86+
postProcessProjects(it)
87+
}
88+
attachedProjectsEvaluated = true;
89+
}
90+
}
91+
92+
private void setup(Project project) {
93+
project.merge.into.dependencies.add("merging", project)
94+
project.dependencies.add("provided", project.merge.into.sourceSets.main.output)
95+
project.dependencies.add("runtimeMerge", project.merge.into)
96+
setupTaskDependencies(project)
97+
setupMaven(project)
98+
}
99+
100+
private void setupTaskDependencies(Project project) {
101+
// invoking a task will invoke the task with the same name on 'into' project
102+
["sourcesJar", "jar", "javadocJar", "javadoc", "install", "artifactoryPublish"].each {
103+
def task = project.tasks.findByPath(it)
104+
if (task) {
105+
task.enabled = false
106+
task.dependsOn(project.merge.into.tasks.findByPath(it))
107+
}
108+
}
109+
110+
// update 'into' project artifacts to contain the source artifact contents
111+
project.merge.into.sourcesJar.from(project.sourcesJar.source)
112+
project.merge.into.jar.from(project.sourceSets.main.output)
113+
project.merge.into.javadoc {
114+
source += project.javadoc.source
115+
classpath += project.javadoc.classpath
116+
}
117+
}
118+
119+
private void setupIdeDependencies(Project project) {
120+
project.configurations.each { c ->
121+
c.dependencies.findAll( { it instanceof org.gradle.api.artifacts.ProjectDependency } ).each { d ->
122+
d.dependencyProject.merge.from.each { from ->
123+
project.dependencies.add("runtimeMerge", from)
124+
}
125+
}
126+
}
127+
}
128+
129+
private void setupMaven(Project project) {
130+
project.configurations.each { configuration ->
131+
Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration])
132+
if (mapping.scope) {
133+
Configuration intoConfiguration = project.merge.into.configurations.create(
134+
project.name + "-" + configuration.name)
135+
configuration.excludeRules.each {
136+
configuration.exclude([
137+
(ExcludeRule.GROUP_KEY) : it.group,
138+
(ExcludeRule.MODULE_KEY) : it.module])
139+
}
140+
configuration.dependencies.each {
141+
def intoCompile = project.merge.into.configurations.getByName("compile")
142+
// Protect against changing a compile scope dependency (SPR-10218)
143+
if (!intoCompile.dependencies.contains(it)) {
144+
intoConfiguration.dependencies.add(it)
145+
}
146+
}
147+
def index = project.parent.childProjects.findIndexOf {p -> p.getValue() == project}
148+
project.merge.into.install.repositories.mavenInstaller.pom.scopeMappings.addMapping(
149+
mapping.priority + 100 + index, intoConfiguration, mapping.scope)
150+
}
151+
}
152+
}
153+
154+
private postProcessProjects(Gradle gradle) {
155+
gradle.allprojects(new Action<Project>() {
156+
public void execute(Project project) {
157+
project.configurations.getByName("runtime").allDependencies.withType(ProjectDependency).each{
158+
Configuration dependsOnMergedFrom = it.dependencyProject.configurations.getByName("merging");
159+
dependsOnMergedFrom.dependencies.each{ dep ->
160+
project.dependencies.add("runtimeMerge", dep.dependencyProject)
161+
}
162+
}
163+
}
164+
});
165+
}
166+
}
167+
168+
class MergeModel {
169+
Project project;
170+
Project into;
171+
List<Project> from = [];
172+
173+
public void setInto(Project into) {
174+
this.into = into;
175+
into.merge.from.add(project);
176+
}
177+
}

regression/cbmc-java/swap2/test.desc

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
org/springframework/build/gradle/MergePlugin$1$_execute_closure1$_closure2.class
3+
--function "org.springframework.build.gradle.MergePlugin\$1\$_execute_closure1\$_closure2.\$getCallSiteArray:()[Lorg/codehaus/groovy/runtime/callsite/CallSite;"
4+
^EXIT=0
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/java_bytecode/java_bytecode_convert_method.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -2381,6 +2381,12 @@ codet java_bytecode_convert_methodt::convert_instructions(
23812381
call.add_source_location()=i_it->source_location;
23822382
c=call;
23832383
}
2384+
else if(statement=="swap")
2385+
{
2386+
assert(op.size()==2 && results.size()==2);
2387+
results[1]=op[0];
2388+
results[0]=op[1];
2389+
}
23842390
else
23852391
{
23862392
c=codet(statement);

0 commit comments

Comments
 (0)