All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.dex2jar.ir.ts.array.ArrayNullPointerTransformer Maven / Gradle / Ivy

There is a newer version: 2.25.11
Show newest version
/*
 * dex2jar - Tools to work with android .dex and java .class files
 * Copyright (c) 2009-2012 Panxiaobo
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.googlecode.dex2jar.ir.ts.array;

import java.util.ArrayList;
import java.util.List;

import com.googlecode.dex2jar.ir.IrMethod;
import com.googlecode.dex2jar.ir.expr.ArrayExpr;
import com.googlecode.dex2jar.ir.expr.Constant;
import com.googlecode.dex2jar.ir.expr.Exprs;
import com.googlecode.dex2jar.ir.expr.FieldExpr;
import com.googlecode.dex2jar.ir.expr.Local;
import com.googlecode.dex2jar.ir.expr.Value;
import com.googlecode.dex2jar.ir.expr.Value.E1Expr;
import com.googlecode.dex2jar.ir.expr.Value.E2Expr;
import com.googlecode.dex2jar.ir.expr.Value.EnExpr;
import com.googlecode.dex2jar.ir.expr.Value.VT;
import com.googlecode.dex2jar.ir.stmt.Stmt;
import com.googlecode.dex2jar.ir.stmt.Stmt.E1Stmt;
import com.googlecode.dex2jar.ir.stmt.Stmt.E2Stmt;
import com.googlecode.dex2jar.ir.stmt.Stmt.ST;
import com.googlecode.dex2jar.ir.stmt.StmtList;
import com.googlecode.dex2jar.ir.stmt.Stmts;
import com.googlecode.dex2jar.ir.ts.Transformer;

/**
 * run after {@link com.googlecode.dex2jar.ir.ts.ConstTransformer}, to deal with following code
 * 
 * 
 * int[] a = null;
 * int b = a[1];
 * 
* * replace {@code int b = a[1];} to {@code throw new NullPointException()}, and we get * *
 * int[] a = null;
 * throw new NullPointException();
 * 
* * @author Panxiaobo * */ public class ArrayNullPointerTransformer implements Transformer { @Override public void transform(IrMethod irMethod) { for (Stmt p = irMethod.stmts.getFirst(); p != null;) { if (arrayNPE(p)) { Stmt q = p.getNext(); replaceNPE(irMethod.stmts, irMethod.locals, p); p = q; continue; } p = p.getNext(); } } private void replaceNPE(StmtList stmts, List locals, Stmt p) { List values = new ArrayList(); switch (p.et) { case E1: tryAdd(((E1Stmt) p).op.trim(), values); break; case E2: E2Stmt e2 = (E2Stmt) p; switch (e2.op1.trim().vt) { case LOCAL: tryAdd(e2.op2.trim(), values); break; case ARRAY: ArrayExpr ae = (ArrayExpr) e2.op1.trim(); if (tryAdd(ae.op1.trim(), values)) { if (tryAdd(ae.op2.trim(), values)) { tryAdd(e2.op2.trim(), values); } } break; case FIELD:// putfield FieldExpr fe = (FieldExpr) e2.op1.trim(); if (fe.op == null || fe.op.trim() == null || tryAdd(fe.op.trim(), values)) { tryAdd(e2.op2.trim(), values); } break; default: if (tryAdd(e2.op2.trim(), values)) { tryAdd(e2.op1.trim(), values); } } default: } for (Value value : values) { switch (value.vt) { case CONSTANT: case LOCAL: break; default: Local n = Exprs.nLocal("xxx"); locals.add(n); stmts.insertBefore(p, Stmts.nAssign(n, value)); } } stmts.insertBefore(p, Stmts.nThrow(Exprs.nInvokeNew(new Value[0], new String[0], "Ljava/lang/NullPointerException;"))); stmts.remove(p); } private boolean tryAdd(Value value, List values) { if (!arrayNPE(value)) { values.add(value); return true; } else { switch (value.et) { case E0: values.add(value); break; case E1: E1Expr e1 = (E1Expr) value; if (e1.op == null || e1.op.trim() == null) { return false; } tryAdd(e1.op.trim(), values); break; case E2: E2Expr e2 = (E2Expr) value; if (e2.vt == VT.ARRAY && e2.op1.trim().vt == VT.CONSTANT) { Constant cst = (Constant) e2.op1.trim(); if (cst.value.equals(Integer.valueOf(0))) { tryAdd(e2.op2.trim(), values); return false; } } if (tryAdd(e2.op1.trim(), values)) { tryAdd(e2.op2.trim(), values); } case En: for (Value vb : ((EnExpr) value).ops) { if (!tryAdd(vb.trim(), values)) { break; } } } } return false; } private boolean arrayNPE(Stmt p) { switch (p.et) { case E0: return false; case E1: if (p.st == ST.GOTO) { return false; } return arrayNPE(((E1Stmt) p).op.trim()); case E2: E2Stmt e2 = (E2Stmt) p; switch (e2.op1.trim().vt) { case ARRAY: case FIELD: return arrayNPE(e2.op1.trim()) || arrayNPE(e2.op2.trim()); default: return arrayNPE(e2.op2.trim()) || arrayNPE(e2.op1.trim()); } case En: return false; } return false; } private boolean arrayNPE(Value value) { switch (value.et) { case E0: return false; case E1: E1Expr e1 = (E1Expr) value; if (e1.op == null || e1.op.trim() == null) { return false; } return arrayNPE(e1.op.trim()); case E2: E2Expr e2 = (E2Expr) value; if (e2.vt == VT.ARRAY && e2.op1.trim().vt == VT.CONSTANT) { Constant cst = (Constant) e2.op1.trim(); if (cst.value.equals(Integer.valueOf(0))) { return true; } } return arrayNPE(e2.op1.trim()) || arrayNPE(e2.op2.trim()); case En: for (Value vb : ((EnExpr) value).ops) { if (arrayNPE(vb.trim())) { return true; } } } return false; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy