The per-thread lock history is stored in the "ulong lock_history" field,
with 8 bits per lock operation. On 32-bit systems only 4 entries fit,
but the dump code in ha_thread_dump_one() always read 8 of them,
shifting the value by up to 56, which is undefined behavior with a
32-bit operand. Recent clang versions may generate bad code that will
lead to a crash when using "show threads" on 32bits machines.
Let's keep the field an ulong and only iterate over the entries that
fit in it. On 64-bit nothing changes, and on 32-bit the last 4 entries
are dumped, which is all the field stores anyway.
This should be backported up to 3.2.
if (th_ctx->lock_history) {
int lkh, lkl, lbl;
int done;
+ int slots = sizeof(th_ctx->lock_history); /* number of 8-bit entries */
chunk_appendf(buf, " lock_hist:");
- for (lkl = 7; lkl >= 0; lkl--) {
+ for (lkl = slots - 1; lkl >= 0; lkl--) {
lkh = (th_ctx->lock_history >> (lkl * 8)) & 0xff;
if (!lkh)
continue;
done = 0;
for (lbl = 0; lbl < LOCK_LABELS; lbl++) {
/* find the latest occurrence of each label */
- for (lkl = 0; lkl < 8; lkl++) {
+ for (lkl = 0; lkl < slots; lkl++) {
lkh = (th_ctx->lock_history >> (lkl * 8)) & 0xff;
if (!lkh)
continue;
if ((lkh >> 2) == lbl)
break;
}
- if (lkl == 8) // not found
+ if (lkl == slots) // not found
continue;
if ((lkh & 3) == _LK_UN)
continue;