skylot / jadx

Dex to Java decompiler
Apache License 2.0
41.81k stars 4.88k forks source link

JadxRuntimeException: Can't find block by offset #240

Open kismeter opened 6 years ago

kismeter commented 6 years ago

## The actually source code is below:

    /**
     * Returns the number of contacts in contacts content provider.
     */
    public int getContactCount() {
        // TODO: consider switching to a rawQuery("select count(*)...") on the database if
        // performance is a bottleneck.
        Cursor cursor = null;
        try {
            cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI,
                    ContactsDictionaryConstants.PROJECTION_ID_ONLY, null, null, null);
            if (null == cursor) {
                return 0;
            }
            return cursor.getCount();
        } catch (final SQLiteException e) {
            Log.e(TAG, "SQLiteException in the remote Contacts process.", e);
        } finally {
            if (null != cursor) {
                cursor.close();
            }
        }
        return 0;
    }

## when using jadx to decompile met the exception:

    public int getContactCount() {
        /* JADX: method processing error */
/*
Error: jadx.core.utils.exceptions.JadxRuntimeException: Can't find block by offset: 0x0035 in list []
    at jadx.core.utils.BlockUtils.getBlockByOffset(BlockUtils.java:43)
    at jadx.core.dex.instructions.IfNode.initBlocks(IfNode.java:60)
    at jadx.core.dex.visitors.blocksmaker.BlockFinish.initBlocksInIfNodes(BlockFinish.java:48)
    at jadx.core.dex.visitors.blocksmaker.BlockFinish.visit(BlockFinish.java:33)
    at jadx.core.dex.visitors.DepthTraversal.visit(DepthTraversal.java:31)
    at jadx.core.dex.visitors.DepthTraversal.visit(DepthTraversal.java:17)
    at jadx.core.ProcessClass.process(ProcessClass.java:34)
    at jadx.core.ProcessClass.processDependencies(ProcessClass.java:56)
    at jadx.core.ProcessClass.process(ProcessClass.java:39)
    at jadx.api.JadxDecompiler.processClass(JadxDecompiler.java:282)
    at jadx.api.JavaClass.decompile(JavaClass.java:62)
    at jadx.api.JadxDecompiler.lambda$appendSourcesSave$0(JadxDecompiler.java:200)
*/
        /*
        r9 = this;
        r8 = 0;
        r6 = 0;
        r0 = r9.mContext;    Catch:{ SQLiteException -> 0x0026, all -> 0x0037 }
        r0 = r0.getContentResolver();    Catch:{ SQLiteException -> 0x0026, all -> 0x0037 }
        r1 = android.provider.ContactsContract.Contacts.CONTENT_URI;     Catch:{ SQLiteException -> 0x0026, all -> 0x0037 }
        r2 = com.android.inputmethod.latin.ContactsDictionaryConstants.PROJECTION_ID_ONLY;   Catch:{ SQLiteException -> 0x0026, all -> 0x0037 }
        r3 = 0;  Catch:{ SQLiteException -> 0x0026, all -> 0x0037 }
        r4 = 0;  Catch:{ SQLiteException -> 0x0026, all -> 0x0037 }
        r5 = 0;  Catch:{ SQLiteException -> 0x0026, all -> 0x0037 }
        r6 = r0.query(r1, r2, r3, r4, r5);   Catch:{ SQLiteException -> 0x0026, all -> 0x0037 }
        if (r6 != 0) goto L_0x001c;
    L_0x0015:
        if (r6 == 0) goto L_0x001a;
    L_0x0017:
        r6.close();
    L_0x001a:
        r0 = r8;
    L_0x001b:
        return r0;
    L_0x001c:
        r0 = r6.getCount();  Catch:{ SQLiteException -> 0x0026, all -> 0x0037 }
        if (r6 == 0) goto L_0x001b;
    L_0x0022:
        r6.close();
        goto L_0x001b;
    L_0x0026:
        r7 = move-exception;
        r0 = "ContactsManager";  Catch:{ SQLiteException -> 0x0026, all -> 0x0037 }
        r1 = "SQLiteException in the remote Contacts process.";  Catch:{ SQLiteException -> 0x0026, all -> 0x0037 }
        android.util.Log.e(r0, r1, r7);  Catch:{ SQLiteException -> 0x0026, all -> 0x0037 }
        if (r6 == 0) goto L_0x0035;
    L_0x0032:
        r6.close();
    L_0x0035:
        r0 = r8;
        goto L_0x001b;
    L_0x0037:
        r0 = move-exception;
        if (r6 == 0) goto L_0x003d;
    L_0x003a:
        r6.close();
    L_0x003d:
        throw r0;
        */
        throw new UnsupportedOperationException("Method not decompiled: com.android.inputmethod.latin.ContactsManager.getContactCount():int");
    }
skylot commented 6 years ago

Thank you for this example. Now I'm working exactly on this issue in finally extract procedure, but still without success. But in latest master branch I made commit which skips finally block extraction if errors occurs and decompiled code looks like this:

    public int getContactCount() {
        Cursor cursor = null;
        try {
            cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI, ContactsDictionaryConstants.PROJECTION_ID_ONLY, null, null, null);
            if (cursor == null) {
                if (cursor != null) {
                    cursor.close();
                }
                return 0;
            }
            int count = cursor.getCount();
            if (cursor == null) {
                return count;
            }
            cursor.close();
            return count;
        } catch (SQLiteException e) {
            Log.e(TAG, "SQLiteException in the remote Contacts process.", e);
            if (cursor != null) {
                cursor.close();
            }
            return 0;
        } catch (Throwable th) {
            if (cursor != null) {
                cursor.close();
            }
            throw th;
        }
    }

It is not compilable, but almost correct and better than error.

kismeter commented 6 years ago

checked for some other finally related code, the finally block will decompiled as Throwable.