From b17daed79a600593053b0262a438b010351836e7 Mon Sep 17 00:00:00 2001 From: Markus Schmidt Date: Thu, 28 Sep 2023 12:52:12 +0200 Subject: [PATCH] prepare bugfixing/testcase for LocalSplitter/DeadAssignmentEliminator bugs mentioned in #664 --- .../JavaClassPathAnalysisInputLocation.java | 4 +- .../BytecodeBodyInterceptors.java | 28 ++-- .../java/sootup/tests/bugs/Issue664Test.java | 45 ++++++ .../apache/jsp/java_detection_samples.java | 147 ++++++++++++++++++ 4 files changed, 212 insertions(+), 12 deletions(-) create mode 100644 sootup.tests/src/test/java/sootup/tests/bugs/Issue664Test.java create mode 100644 sootup.tests/src/test/resources/bugs/664_struce-compiled/org/apache/jsp/java_detection_samples.java diff --git a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/JavaClassPathAnalysisInputLocation.java b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/JavaClassPathAnalysisInputLocation.java index 5370cd8e3d6..c13c7cd6913 100644 --- a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/JavaClassPathAnalysisInputLocation.java +++ b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/JavaClassPathAnalysisInputLocation.java @@ -94,7 +94,9 @@ public JavaClassPathAnalysisInputLocation( cpEntries = explodeClassPath(classPath); if (cpEntries.isEmpty()) { - throw new IllegalStateException("Empty class path is given."); + throw new IllegalStateException( + "Empty class path is given. Executed WorkingDirectory is " + + new File("").getAbsolutePath()); } } diff --git a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/interceptors/BytecodeBodyInterceptors.java b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/interceptors/BytecodeBodyInterceptors.java index 2eab5cc898f..a5787cb7b0d 100644 --- a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/interceptors/BytecodeBodyInterceptors.java +++ b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/interceptors/BytecodeBodyInterceptors.java @@ -29,19 +29,25 @@ /** Built-in sets of {@link BodyInterceptor}s for the bytecode frontend */ public enum BytecodeBodyInterceptors { Default( - new CastAndReturnInliner(), - new UnreachableCodeEliminator(), + + // new CastAndReturnInliner(), + // new UnreachableCodeEliminator(), new LocalSplitter(), - new Aggregator(), - new TypeAssigner(), + // new Aggregator(), + + // new TypeAssigner(), // ms: is already called from typeassigner? new LocalNameStandardizer(), - new CopyPropagator(), - new DeadAssignmentEliminator(), - new ConditionalBranchFolder(), - new EmptySwitchEliminator(), - new NopEliminator(), - new UnusedLocalEliminator(), - new UnreachableCodeEliminator()); + // new CopyPropagator(), + + new DeadAssignmentEliminator() + /* + new ConditionalBranchFolder(), + new EmptySwitchEliminator(), + new NopEliminator(), + new UnusedLocalEliminator(), + new UnreachableCodeEliminator() + */ + ); @Nonnull private final List bodyInterceptors; diff --git a/sootup.tests/src/test/java/sootup/tests/bugs/Issue664Test.java b/sootup.tests/src/test/java/sootup/tests/bugs/Issue664Test.java new file mode 100644 index 00000000000..3a4b63b9ba2 --- /dev/null +++ b/sootup.tests/src/test/java/sootup/tests/bugs/Issue664Test.java @@ -0,0 +1,45 @@ +package sootup.tests.bugs; + +import categories.Java8Test; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import sootup.core.graph.StmtGraph; +import sootup.core.model.SourceType; +import sootup.core.signatures.MethodSignature; +import sootup.core.util.DotExporter; +import sootup.java.bytecode.inputlocation.BytecodeClassLoadingOptions; +import sootup.java.bytecode.inputlocation.JavaClassPathAnalysisInputLocation; +import sootup.java.core.JavaProject; +import sootup.java.core.language.JavaLanguage; +import sootup.java.core.views.JavaView; + +@Category(Java8Test.class) +public class Issue664Test { + @Test + public void testJar_missing_if_flows() { + + JavaProject applicationProject = + JavaProject.builder(new JavaLanguage(8)) + .addInputLocation( + new JavaClassPathAnalysisInputLocation( + "src/test/resources/bugs/664_struce-compiled/", SourceType.Application)) + .build(); + + JavaView view = applicationProject.createMutableView(); + view.configBodyInterceptors(analysisInputLocation -> BytecodeClassLoadingOptions.Default); + + final MethodSignature methodSignature = + view.getIdentifierFactory() + .parseMethodSignature( + ""); + final StmtGraph stmtGraph = view.getMethod(methodSignature).get().getBody().getStmtGraph(); + System.out.println(DotExporter.createUrlToWebeditor(stmtGraph)); + + // TODO: Fix LocalSplitter - generates the precondition that the DeadAssignmentEliminator wants + // to remove Stmts.. i.e. it does not connect all Locals or does not remove/replace the + // previously used Locals? + // TODO: Fix DeadAssignmentEliminator (removes a branchtarget from IfStmt which results in an + // invalid StmtGrph) + + } +} diff --git a/sootup.tests/src/test/resources/bugs/664_struce-compiled/org/apache/jsp/java_detection_samples.java b/sootup.tests/src/test/resources/bugs/664_struce-compiled/org/apache/jsp/java_detection_samples.java new file mode 100644 index 00000000000..b30d5043613 --- /dev/null +++ b/sootup.tests/src/test/resources/bugs/664_struce-compiled/org/apache/jsp/java_detection_samples.java @@ -0,0 +1,147 @@ +/* + * Generated by the Jasper component of Apache Tomcat + * Version: JspC/ApacheTomcat9 + * Note: The last modified time of this file was set to + * the last modified time of the source file after + * generation to assist with modification tracking. + */ +package org.apache.jsp; + +import javax.servlet.*; +import javax.servlet.http.*; +import javax.servlet.jsp.*; +import java.util.List; +import java.util.ArrayList; + +public final class java_detection_samples extends org.apache.jasper.runtime.HttpJspBase + implements org.apache.jasper.runtime.JspSourceDependent, + org.apache.jasper.runtime.JspSourceImports { + + private static final javax.servlet.jsp.JspFactory _jspxFactory = + javax.servlet.jsp.JspFactory.getDefaultFactory(); + + private static java.util.Map _jspx_dependants; + + private static final java.util.Set _jspx_imports_packages; + + private static final java.util.Set _jspx_imports_classes; + + static { + _jspx_imports_packages = new java.util.HashSet<>(); + _jspx_imports_packages.add("javax.servlet"); + _jspx_imports_packages.add("javax.servlet.http"); + _jspx_imports_packages.add("javax.servlet.jsp"); + _jspx_imports_classes = new java.util.HashSet<>(); + _jspx_imports_classes.add("java.util.List"); + _jspx_imports_classes.add("java.util.ArrayList"); + } + + private volatile javax.el.ExpressionFactory _el_expressionfactory; + private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager; + + public java.util.Map getDependants() { + return _jspx_dependants; + } + + public java.util.Set getPackageImports() { + return _jspx_imports_packages; + } + + public java.util.Set getClassImports() { + return _jspx_imports_classes; + } + + public javax.el.ExpressionFactory _jsp_getExpressionFactory() { + if (_el_expressionfactory == null) { + synchronized (this) { + if (_el_expressionfactory == null) { + _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); + } + } + } + return _el_expressionfactory; + } + + public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() { + if (_jsp_instancemanager == null) { + synchronized (this) { + if (_jsp_instancemanager == null) { + _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); + } + } + } + return _jsp_instancemanager; + } + + public void _jspInit() { + } + + public void _jspDestroy() { + } + + public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) + throws java.io.IOException, javax.servlet.ServletException { + + if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) { + final java.lang.String _jspx_method = request.getMethod(); + if ("OPTIONS".equals(_jspx_method)) { + response.setHeader("Allow","GET, HEAD, POST, OPTIONS"); + return; + } + if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) { + response.setHeader("Allow","GET, HEAD, POST, OPTIONS"); + response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET, POST or HEAD. Jasper also permits OPTIONS"); + return; + } + } + + final javax.servlet.jsp.PageContext pageContext; + javax.servlet.http.HttpSession session = null; + final javax.servlet.ServletContext application; + final javax.servlet.ServletConfig config; + javax.servlet.jsp.JspWriter out = null; + final java.lang.Object page = this; + javax.servlet.jsp.JspWriter _jspx_out = null; + javax.servlet.jsp.PageContext _jspx_page_context = null; + + + try { + response.setContentType("text/html"); + pageContext = _jspxFactory.getPageContext(this, request, response, + null, true, 8192, true); + _jspx_page_context = pageContext; + application = pageContext.getServletContext(); + config = pageContext.getServletConfig(); + session = pageContext.getSession(); + out = pageContext.getOut(); + _jspx_out = out; + + out.write('\n'); + out.write('\n'); + out.write('\n'); + + List names = new ArrayList<>(); + names.add("s"); + + names.forEach(System.out::println); + + out.write('\n'); + } catch (java.lang.Throwable t) { + if (!(t instanceof javax.servlet.jsp.SkipPageException)){ + out = _jspx_out; + if (out != null && out.getBufferSize() != 0) + try { + if (response.isCommitted()) { + out.flush(); + } else { + out.clearBuffer(); + } + } catch (java.io.IOException e) {} + if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); + else throw new ServletException(t); + } + } finally { + _jspxFactory.releasePageContext(_jspx_page_context); + } + } +}