const int *dwarf_to_perf = is_abi32 ? regs_i386 : regs_x86_64;
/* Count bits and allocate regs_mapping: */
- int j, k, kmax, count; uint64_t bit;
- for (k = 0, kmax = -1, count = 0, bit = 1;
+ int j, k, count; uint64_t bit;
+ for (k = 0, count = 0, bit = 1;
k < PERF_REG_X86_64_MAX; k++, bit <<= 1)
{
if ((bit & perf_regs_mask)) {
count++;
- kmax = k;
}
}
ebl->cached_perf_regs_mask = perf_regs_mask;
ebl->cached_regs_mapping = (int *)calloc (count, sizeof(int));
+ if (count != 0 && ebl->cached_regs_mapping == NULL)
+ return false;
ebl->cached_n_regs_mapping = count;
/* Locations of perf_regs in the regs[] array, according to
- perf_regs_mask: */
+ perf_regs_mask. Initialize the whole array (not just up to the
+ highest set bit): the loop below indexes perf_to_regs[] by
+ dwarf_to_perf[i], which can be larger than the highest set bit in
+ perf_regs_mask. Leaving the tail uninitialized would read stack
+ garbage and could turn into an out-of-bounds write into the
+ cached_regs_mapping[] heap buffer. */
int perf_to_regs[PERF_REG_X86_64_MAX];
uint64_t expected_mask = is_abi32 ?
PERF_FRAME_REGISTERS_I386 : PERF_FRAME_REGISTERS_X86_64;
- for (j = 0, k = 0, bit = 1; k <= kmax; k++, bit <<= 1)
+ for (j = 0, k = 0, bit = 1; k < PERF_REG_X86_64_MAX; k++, bit <<= 1)
{
if ((bit & expected_mask) && (bit & perf_regs_mask))
{
{
k = dwarf_to_perf[i];
j = perf_to_regs[k];
- if (j < 0) continue;
+ if (j < 0 || j >= (int)ebl->cached_n_regs_mapping) continue;
ebl->cached_regs_mapping[j] = i;
}