From 1b262e23b948e23a6b2923fd30c1e237635ed97e Mon Sep 17 00:00:00 2001 From: zunwang Date: Wed, 15 Jan 2025 11:51:03 +0100 Subject: [PATCH] method mightThrowExplicitly in ExceptionAnalyser --- .../exceptions/ExceptionAnalyserResult.java | 67 ++++++++++++ .../exceptions/StmtExceptionAnalyser.java | 103 ++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 sootup.java.core/src/main/java/sootup/java/core/exceptions/ExceptionAnalyserResult.java create mode 100644 sootup.java.core/src/main/java/sootup/java/core/exceptions/StmtExceptionAnalyser.java diff --git a/sootup.java.core/src/main/java/sootup/java/core/exceptions/ExceptionAnalyserResult.java b/sootup.java.core/src/main/java/sootup/java/core/exceptions/ExceptionAnalyserResult.java new file mode 100644 index 0000000000..59b91aedb5 --- /dev/null +++ b/sootup.java.core/src/main/java/sootup/java/core/exceptions/ExceptionAnalyserResult.java @@ -0,0 +1,67 @@ +package sootup.java.core.exceptions; + +import sootup.core.typehierarchy.TypeHierarchy; +import sootup.core.types.ClassType; +import sootup.core.util.ImmutableUtils; +import sootup.java.core.JavaIdentifierFactory; + +import javax.annotation.Nonnull; +import java.util.HashSet; +import java.util.Set; + +public class ExceptionAnalyserResult { + + private final Set exceptions; + + public ExceptionAnalyserResult (Set exceptions){ + this.exceptions = ImmutableUtils.immutableSetOf(exceptions); + } + + static ExceptionAnalyserResult createThrowableExceptions (){ + return new ExceptionAnalyserResult(ImmutableUtils.immutableSet(ExceptionType.THROWABLE)); + } + + static ExceptionAnalyserResult createNullPointerException(){ + return new ExceptionAnalyserResult(ImmutableUtils.immutableSet(ExceptionType.NUll_POINTER_EXCEPTION)); + } + + static ExceptionAnalyserResult createSingleException(@Nonnull ClassType exceptionType, @Nonnull TypeHierarchy typeHierarchy){ + if(!typeHierarchy.contains(exceptionType)){ + throw new IllegalArgumentException("The given exceptionType \"" + exceptionType + "\" is not in type hierarchy!"); + } + return new ExceptionAnalyserResult(ImmutableUtils.immutableSet(exceptionType)); + } + + static ExceptionAnalyserResult createEmptyException(){ + return new ExceptionAnalyserResult(ImmutableUtils.emptyImmutableSet()); + } + + public Set getExceptions(){ + return this.exceptions; + } + + protected ExceptionAnalyserResult addException(ClassType newException, TypeHierarchy typeHierarchy){ + if(!typeHierarchy.contains(newException)){ + throw new IllegalArgumentException("The given exceptionType \"" + newException + "\" is not in type hierarchy!"); + } + Set resultSet = new HashSet<>(this.exceptions); + for(ClassType exception : exceptions){ + if(exception.equals(newException) || typeHierarchy.isSubtype(exception, newException)){ + return this; + } + if(typeHierarchy.isSubtype(newException, exception)){ + resultSet.remove(exception); + } + } + resultSet.add(newException); + return new ExceptionAnalyserResult(resultSet); + } + + public static class ExceptionType{ + static final ClassType THROWABLE = JavaIdentifierFactory.getInstance().getClassType("java.lang.Throwable"); + static final ClassType NUll_POINTER_EXCEPTION = JavaIdentifierFactory.getInstance().getClassType("java.lang.NullPointerException"); + + } +} + + diff --git a/sootup.java.core/src/main/java/sootup/java/core/exceptions/StmtExceptionAnalyser.java b/sootup.java.core/src/main/java/sootup/java/core/exceptions/StmtExceptionAnalyser.java new file mode 100644 index 0000000000..4710169bb0 --- /dev/null +++ b/sootup.java.core/src/main/java/sootup/java/core/exceptions/StmtExceptionAnalyser.java @@ -0,0 +1,103 @@ +package sootup.java.core.exceptions; +/*- + * #%L + * Soot - a J*va Optimization Framework + * %% + * Copyright (C) 2019-2025 Zun Wang + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 2.1 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ + +import sootup.core.graph.MutableStmtGraph; +import sootup.core.jimple.basic.Immediate; +import sootup.core.jimple.basic.Local; +import sootup.core.jimple.basic.Value; +import sootup.core.jimple.common.expr.JNewExpr; +import sootup.core.jimple.common.stmt.AbstractDefinitionStmt; +import sootup.core.jimple.common.stmt.JThrowStmt; +import sootup.core.jimple.common.stmt.Stmt; +import sootup.core.typehierarchy.TypeHierarchy; +import sootup.core.types.ClassType; +import sootup.core.types.NullType; +import sootup.core.types.Type; +import sootup.core.types.UnknownType; + +import javax.annotation.Nonnull; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * An analyzer for a Stmt to determine the exceptions it might throw. + */ + +public class StmtExceptionAnalyser { + + private final TypeHierarchy hierarchy; + + public StmtExceptionAnalyser(TypeHierarchy hierarchy){ + this.hierarchy = hierarchy; + } + + public ExceptionAnalyserResult mightThrow(@Nonnull Stmt stmt, @Nonnull MutableStmtGraph graph){ + if(stmt instanceof JThrowStmt){ + return mightThrowExplicitly((JThrowStmt) stmt, graph); + }else { + return mightThrowImplicitly(stmt); + } + } + + public ExceptionAnalyserResult mightThrowExplicitly(@Nonnull JThrowStmt throwStmt, @Nonnull MutableStmtGraph graph){ + Immediate throwExpression = throwStmt.getOp(); + //todo: needs to check if all throwExpressions are locals + if(!(throwExpression instanceof Local)){ + throw new IllegalStateException("The given throwStmt: \"" + throwStmt +"\" doesn't throw a local!"); + } + Local exceptionLocal = (Local) throwExpression; + Type throwType = exceptionLocal.getType(); + if(throwType == null || throwType instanceof UnknownType){ + return ExceptionAnalyserResult.createThrowableExceptions(); + } + if(throwType instanceof NullType){ + return ExceptionAnalyserResult.createNullPointerException(); + } + if(!(throwType instanceof ClassType)){ + throw new IllegalStateException("The type of " + throwStmt +" is not a ClassType!"); + } + Type preciserType = findPreciserType(exceptionLocal,graph); + if(preciserType != null){ + throwType = preciserType; + } + if(!(preciserType instanceof ClassType)){ + throw new IllegalStateException("The type of " + preciserType +" is not a ClassType!"); + } + return ExceptionAnalyserResult.createSingleException((ClassType) throwType, hierarchy); + } + + private Type findPreciserType(@Nonnull Local local, @Nonnull MutableStmtGraph graph){ + Type preciserType = null; + Set defStmts = graph.getStmts().stream().filter(stmt -> stmt instanceof AbstractDefinitionStmt).collect(Collectors.toSet()); + Set aliasesOfGivenLocal = defStmts.stream().filter(stmt -> ((AbstractDefinitionStmt) stmt).getLeftOp()==local).map(stmt -> ((AbstractDefinitionStmt) stmt).getRightOp()).collect(Collectors.toSet()); + Set allocationTypes = aliasesOfGivenLocal.stream().filter(value -> value instanceof JNewExpr).map(value -> value.getType()).collect(Collectors.toSet()); + if(allocationTypes.size() == 1){ + preciserType = allocationTypes.iterator().next(); + } + return preciserType; + } + + private ExceptionAnalyserResult mightThrowImplicitly(Stmt stmt){ + return null; + } +}