google / smali

Other
201 stars 35 forks source link

Bad index for debug_info_item parameter_name: 2ffffff >= 1e58 #64

Open woxin123 opened 3 months ago

woxin123 commented 3 months ago

reason is:

private int writeDebugItem(@Nonnull DexDataWriter writer,
                           @Nullable Iterable<? extends StringKey> parameterNames,
                           @Nullable Iterable<? extends DebugItem> debugItems) throws IOException {
    int parameterCount = 0;
    int lastNamedParameterIndex = -1;
    if (parameterNames != null) {
        parameterCount = IteratorUtils.size(parameterNames);
        int index = 0;
        for (StringKey parameterName: parameterNames) {
            if (parameterName != null) {
                lastNamedParameterIndex = index;
            }
            index++;
        }
    }
    if (lastNamedParameterIndex == -1 && (debugItems == null 
            || !debugItems.iterator().hasNext())) {
        return NO_OFFSET;
    }
    int debugItemOffset = writer.getPosition();
    int startingLineNumber = 0;
    if (debugItems != null) {
        for (DebugItem debugItem: debugItems) {
            if (debugItem instanceof LineNumber) {
                startingLineNumber = ((LineNumber)debugItem).getLineNumber();
                break;
            }
        }
    }
    ByteArrayOutputStream tempByteOutput = new ByteArrayOutputStream();
    DexDataWriter tempDataWriter = new DexDataWriter(tempByteOutput, 0, 64);
    DebugWriter tempDebugWriter = new DebugWriter(stringSection, typeSection, tempDataWriter);
    tempDataWriter.writeUleb128(startingLineNumber);

The parameterNames type is is TransformedIterator.

public class TransformedIterator<F extends Object, T extends Object>
        implements Iterator<T>, Iterable<T> {
    final Iterator<? extends F> backingIterator;
    final Function<F, T> transformFunction;

    public TransformedIterator(Iterable<? extends F> backingIterable,
            Function<F, T> transformFunction) {
        this.backingIterator = backingIterable.iterator();
        this.transformFunction = transformFunction;
    }

    public TransformedIterator(Iterator<? extends F> backingIterator,
            Function<F, T> transformFunction) {
        this.backingIterator = backingIterator;
        this.transformFunction = transformFunction;
    }

    @Override
    public final boolean hasNext() {
        return backingIterator.hasNext();
    }

    @Override
    public final T next() {
        return transformFunction.apply(backingIterator.next());
    }

    @Override
    public final void remove() {
        backingIterator.remove();
    }

    @Override
    public final Iterator<T> iterator() {
        return this;
    }
}

It can be used only once.

UltraSina commented 2 months ago

i have the same problem do you finded any solation?

melcz commented 2 months ago

Could you add a minimal example of how you're using the DexWriter api where this issue reproduces?

oSumAtrIX commented 2 months ago

@melcz I can reproduce but creating a minimal reproducible setup in my case is difficult. In short, it should be reproducible when reading and writing the DEX files of YouTube. You may install it on an emulator which does not have Google services after debug signing it.

Suppressed: java.io.IOException: Failed to open dex files from 
/data/app/~~c9nURA4iZl9uCXlGO1vVkw==/com.google.android.youtube-s_uOp52RcMZhFI2YJnjZ7Q==/base.apk because: 
Failure to verify dex file '/data/app/~~c9nURA4iZl9uCXlGO1vVkw==/com.google.android.youtube-
s_uOp52RcMZhFI2YJnjZ7Q==/base.apk': Bad index for debug_info_item parameter_name: b45b0c2 >= a1da
woxin123 commented 2 months ago

@melcz Rewrite debugItems can reproduce this issue.

val dexFile = DexFileFactory.loadDexFile(dex, Opcodes.forApi(21))
val reWriter = DexRewriter(object : RewriterModule() {
    override fun getClassDefRewriter(rewriters: Rewriters): Rewriter<ClassDef> =
        Rewriter<ClassDef> { classDef ->
            val directMethods = mutableListOf<ImmutableMethod>()
            val virtualMethods = mutableListOf<ImmutableMethod>()
            classDef.directMethods.forEach { method ->
                val immutableMethod = ImmutableMethod(
                    method.definingClass,
                    method.name,
                    method.parameters,
                    method.returnType,
                    method.accessFlags,
                    method.annotations,
                    method.hiddenApiRestrictions,
                    optiMethodDebugItem(method)
                )
                directMethods.add(immutableMethod)
            }
            classDef.virtualMethods.forEach { method ->
                val immutableMethod = ImmutableMethod(
                    method.definingClass,
                    method.name,
                    method.parameters,
                    method.returnType,
                    method.accessFlags,
                    method.annotations,
                    method.hiddenApiRestrictions,
                    optiMethodDebugItem(method)
                )
                virtualMethods.add(immutableMethod)
            }
            return@Rewriter ImmutableClassDef(
                classDef.type,
                classDef.accessFlags,
                classDef.superclass,
                classDef.interfaces,
                null,
                classDef.annotations,
                classDef.staticFields,
                classDef.instanceFields,
                directMethods,
                virtualMethods
            )
        }
})
val newDexFile = reWriter.dexFileRewriter.rewrite(dexFile)
DexFileFactory.writeDexFile(dex.absolutePath, newDexFile)

private fun optiMethodDebugItem(
    method: Method,
    debugItemInsSizeStatic: MutableList<Int>,
    dump: DebugItemDump,
): ImmutableMethodImplementation? {
    val implementation = method.implementation ?: return nul
    return ImmutableMethodImplementation(
        implementation.registerCount,
        implementation.instructions,
        implementation.tryBlocks,
        getNewDebugItem(method)
    )
}
private fun getNewDebugItem(
    method: Method,
): List<DebugItem>? {
    // ...
    return method.implementation?.debugItems?.toList()
}
UltraSina commented 2 months ago

Could you add a minimal example of how you're using the DexWriter api where this issue reproduces?

i use dex pool , but i fixed the problem

melcz commented 1 month ago

Please test with a build off the rewriter branch: https://github.com/google/smali/tree/rewriter