maoabc / nmmp

dex-vm used to protect the android classes.dex file
736 stars 260 forks source link

为什么在数组aget时,int类型和short类型使用了不同的实现,导致数组越界读写时,aget int时不会报ArrayIndexOutOfBoundsException错误 #40

Closed bwmaples closed 1 year ago

bwmaples commented 2 years ago

如题我看int/long数组的aget用的是

HANDLE_OP_AGET(OP_AGET, "", {
    u4 *arrData = (u4 *) env->GetPrimitiveArrayCritical(arrayObj, NULL);
    u4 val = arrData[idx];
    env->ReleasePrimitiveArrayCritical(arrayObj, arrData, JNI_ABORT);

    SET_REGISTER(vdst, val);

})

而short/bool数组使用的

HANDLE_OP_AGET(OP_AGET_BYTE, "-byte", {
    jbyte val;
    env->GetByteArrayRegion((jbyteArray) arrayObj, idx, 1, &val);
    SET_REGISTER(vdst, val);
})

使用了不同的实现方式是有什么考虑么?

我发现使用GetPrimitiveArrayCritical时,数组越界是不会报ArrayIndexOutOfBoundsException,会取出一个未初始化的数字 使用Get***ArrayRegion函数,会报这个ArrayIndexOutOfBoundsException 想知道当时使用不同实现方式的考虑

maoabc commented 2 years ago

aget指令不光对int使用还有float,没法区分它处理的是int还是float,所以不处理直接把原始数据扔寄存器里,让后续指令自己区分。

maoabc commented 2 years ago

这问题,可能得在解释aget指令时,自己先检测一遍数组是否越界。

maoabc commented 2 years ago

又或者在处理dex时提前把数组类型区分出来,然后自己在vm里增加一条aget-float指令的解释,这样原来的aget只处理int数组(GetIntArrayRegion),新加的aget-float处理float数组(GetFloatArrayRegion)

bwmaples commented 2 years ago

哦哦哦,好的,牛的

bwmaples commented 2 years ago

又或者在处理dex时提前把数组类型区分出来,然后自己在vm里增加一条aget-float指令的解释,这样原来的aget只处理int数组(GetIntArrayRegion),新加的aget-float处理float数组(GetFloatArrayRegion)

自己增加一条新指令有点麻烦,主要是原来就没有这个指令。。。