Project

General

Profile

Actions

Bug #21438

closed

use-after-free when resizing exivars

Added by byroot (Jean Boussier) 7 days ago. Updated 1 day ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:122518]

Description

Here's a semi-reliable reproduction:

objs = 10_000.times.map do
  a = []
  a.instance_variable_set(:@a, 1)
  a
end

GC.stress = true
GC.auto_compact = true

steps = 1000.times.map do
  a = []
  a.instance_variable_set(:@a, 1)
  a.instance_variable_set(:@b, 2)
  a.instance_variable_set(:@c, 3)
  a.instance_variable_set(:@d, 4)
  a.instance_variable_set(:@e, 5)
  a.instance_variable_set(:@f, 6)
  a.instance_variable_set(:@g, 7)
  a.instance_variable_set(:@h, 8)
  # resize
  a.instance_variable_set(:@i, 9)
  a.instance_variable_set(:@j, 10)
  a
end
objs.clear

GC.stress = false
GC.auto_compact = false

The Exivar codepath uses st_update and allocate within the codebase.

If GC trigger, it may remove entires from the table, or delete+insert in case of compaction, and this can trigger a table rebuild of the generic fields st_table in the middle of calling the st_update callback.
This can cause entries to be reallocated or rearranged and the update to be for the wrong entry.

Auto compaction isn't strictly required to trigger the bug, but makes it more likely.

Actions

Also available in: Atom PDF

Like1
Like0Like0Like0