зеркало из https://github.com/github/ruby.git
Do not read cached_id from callcache on stack
The inline cache is initialized by vm_cc_attr_index_set only when
vm_cc_markable(cc). However, vm_getivar attempted to read the cache
even if the cc is not vm_cc_markable.
This caused a condition that depends on uninitialized value.
Here is an output of valgrind:
```
==10483== Conditional jump or move depends on uninitialised value(s)
==10483== at 0x4C1D60: vm_getivar (vm_insnhelper.c:1171)
==10483== by 0x4C1D60: vm_call_ivar (vm_insnhelper.c:3257)
==10483== by 0x4E8E48: vm_call_symbol (vm_insnhelper.c:3481)
==10483== by 0x4EAD8C: vm_sendish (vm_insnhelper.c:5035)
==10483== by 0x4C62B2: vm_exec_core (insns.def:820)
==10483== by 0x4DD519: rb_vm_exec (vm.c:0)
==10483== by 0x4F00B3: invoke_block (vm.c:1417)
==10483== by 0x4F00B3: invoke_iseq_block_from_c (vm.c:1473)
==10483== by 0x4F00B3: invoke_block_from_c_bh (vm.c:1491)
==10483== by 0x4D42B6: rb_yield (vm_eval.c:0)
==10483== by 0x259128: rb_ary_each (array.c:2733)
==10483== by 0x4E8730: vm_call_cfunc_with_frame (vm_insnhelper.c:3227)
==10483== by 0x4EAD8C: vm_sendish (vm_insnhelper.c:5035)
==10483== by 0x4C6254: vm_exec_core (insns.def:801)
==10483== by 0x4DD519: rb_vm_exec (vm.c:0)
==10483==
```
In fact, the CI on FreeBSD 12 started failing since ad63b668e2
.
```
gmake[1]: Entering directory '/usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby'
/usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:924:in `complete': undefined method `complete' for nil:NilClass (NoMethodError)
from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1816:in `block in visit'
from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1815:in `reverse_each'
from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1815:in `visit'
from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1847:in `block in complete'
from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1846:in `catch'
from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1846:in `complete'
from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1640:in `block in parse_in_order'
from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1632:in `catch'
from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1632:in `parse_in_order'
from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1626:in `order!'
from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1732:in `permute!'
from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1757:in `parse!'
from ./ext/extmk.rb:359:in `parse_args'
from ./ext/extmk.rb:396:in `<main>'
```
This change adds a guard to read the cache only when vm_cc_markable(cc).
It might be better to initialize the cache as INVALID_SHAPE_ID when the
cc is not vm_cc_markable.
This commit is contained in:
Родитель
66a650ec41
Коммит
7a9f865a1d
|
@ -385,6 +385,7 @@ vm_cc_attr_index_dest_shape_id(const struct rb_callcache *cc)
|
||||||
static inline void
|
static inline void
|
||||||
vm_cc_atomic_shape_and_index(const struct rb_callcache *cc, shape_id_t * shape_id, attr_index_t * index)
|
vm_cc_atomic_shape_and_index(const struct rb_callcache *cc, shape_id_t * shape_id, attr_index_t * index)
|
||||||
{
|
{
|
||||||
|
VM_ASSERT(vm_cc_markable(cc));
|
||||||
uintptr_t cache_value = cc->aux_.attr.value; // Atomically read 64 bits
|
uintptr_t cache_value = cc->aux_.attr.value; // Atomically read 64 bits
|
||||||
*shape_id = (shape_id_t)(cache_value >> SHAPE_FLAG_SHIFT);
|
*shape_id = (shape_id_t)(cache_value >> SHAPE_FLAG_SHIFT);
|
||||||
*index = (attr_index_t)(cache_value & SHAPE_FLAG_MASK) - 1;
|
*index = (attr_index_t)(cache_value & SHAPE_FLAG_MASK) - 1;
|
||||||
|
|
|
@ -1160,7 +1160,13 @@ vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_call
|
||||||
attr_index_t index;
|
attr_index_t index;
|
||||||
|
|
||||||
if (is_attr) {
|
if (is_attr) {
|
||||||
vm_cc_atomic_shape_and_index(cc, &cached_id, &index);
|
if (vm_cc_markable(cc)) {
|
||||||
|
vm_cc_atomic_shape_and_index(cc, &cached_id, &index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cached_id = INVALID_SHAPE_ID;
|
||||||
|
index = ATTR_INDEX_NOT_SET;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
vm_ic_atomic_shape_and_index(ic, &cached_id, &index);
|
vm_ic_atomic_shape_and_index(ic, &cached_id, &index);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче