Project

General

Profile

Actions

Bug #15792

closed

GC can leave strings used as hash keys in a corrupted state

Added by byroot (Jean Boussier) about 3 years ago. Updated almost 3 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:92412]

Description

The following script showcase the issue:

#!/usr/bin/env ruby --disable-gems
a = ('a' * 24).encode(Encoding::ASCII).gsub('x', '')
b = ('b' * 24).encode(Encoding::ASCII).gsub('x', '')

hash = {}
hash[a] = true
hash[b] = true

puts "Bebore garbage_collection: a=#{a.inspect} b=#{b.inspect}"
4.times { GC.start }
puts "After garbage_collection: a=#{a.inspect} b=#{b.inspect}"

Expected output:

Bebore garbage_collection: a="aaaaaaaaaaaaaaaaaaaaaaaa" b="bbbbbbbbbbbbbbbbbbbbbbbb"
After garbage_collection: a="aaaaaaaaaaaaaaaaaaaaaaaa" b="bbbbbbbbbbbbbbbbbbbbbbbb"

Actual output:

Ruby: 2.6.2
Bebore garbage_collection: a="aaaaaaaaaaaaaaaaaaaaaaaa" b="bbbbbbbbbbbbbbbbbbbbbbbb"
After garbage_collection: a="}\x0Eu\xDB\xFC\a\x00\x80\xE9\ru\xDB\xFC\a\x00\x10\x04\x00aaaaaa" b="\x00\x00\x00\x00\x00\x00\x00\xC0\x00\x00\x00\x00\x00\x00\x00\xC0\x02\x00bbbbbb"

We reduced the repro script as much as we could, both the .encode(ASCII) and the gsub are necessary for the bug to manifest itself.

We also used ObjectSpace.dump() to analyze the corrupted string.

b = "shared":true, "encoding":"US-ASCII", "references":["0x7faf4a01aeb8"]
0x7faf4a01aeb8 = "frozen":true, "fstring":true, "bytesize":24, "value":"bbbbbbbbbbbbbbbbbbbbbbbb", "encoding":"US-ASCII"

Big thanks to Édouard Chin who did most of the initial repro reduction.

Actions

Also available in: Atom PDF