pkujhd / goloader

load and run golang code at runtime.
Apache License 2.0
506 stars 58 forks source link

may be a bug: the program handles the`findfunctab` does not consider the case where the function address spans 4kb #93

Closed fumeboy closed 11 months ago

fumeboy commented 11 months ago
// goloader/ld.go
    for k, _func := range linker._func {
        funcname := getfuncname(_func, module)
        x := linker.symMap[funcname].Offset
        b := x / pcbucketsize
        i := x % pcbucketsize / (pcbucketsize / nsub)
        for lb := b - len(funcbucket); lb >= 0; lb-- {
            funcbucket = append(funcbucket, findfuncbucket{
                idx: uint32(k)}) // notice here (A)
        }
        if funcbucket[b].subbuckets[i] == 0 && b != 0 && i != 0 { // and here (B)
            if k-int(funcbucket[b].idx) >= pcbucketsize/minfunc {
                return fmt.Errorf("over %d func in one funcbuckets", k-int(funcbucket[b].idx))
            }
            funcbucket[b].subbuckets[i] = byte(k - int(funcbucket[b].idx))
        }
    }

the findfunctab has bigbucket and subbucket.

first, this program set the bigbucket.idx with value of k, but should be k==0 ? 0 : k-1, suppose the address of a function (k-1) happens to be [4096-100, 4096 + 100], and now pc is 4096+50, this program will determine that this pc belongs to the k th function, not the k-1 th function

首先, 这个程序假设每个大桶的起始索引, 都是起始地址在这 4096byte 内的第一个函数的索引, 然而有可能一个函数的地址, 恰好“骑”在这 4KB 的分界线上, 它的起始地址在前一个大桶, 但是终结地址在第二个 4096byte, 这意味着属于第二个 4096byte 的 pc 值, 有可能是第 k-1 函数, 而不是第 k 函数; 这个很危险, 会导致程序 throw

second, this program set the subbucket.idx but ignore the empty subbucket between 2 set subbucket, and these empty subbucket should be fill by prev bucket with non-zero value

其次, 这个程序设置了小桶的值后, 忽略了中间空桶的填充, 不过这个是小问题, 只是 findfunc 有可能从 0 开始查找, 这不会导致程序 throw

fumeboy commented 11 months ago

cc @eh-steve

pkujhd commented 11 months ago

the wrong func id won't cause a crash . it gives generate-stack function wrong function name. but still a case will be panic. when the last function cross 4k boundary, it will be visit out of bounds of pclntable. i will fix it