Skip to content

TypeError/ArgumentError can't be coerced into BigDecimal or Segmentation fault after gc compaction #340

Description

@tompng

Found while debugging #339, Related to #337

((Real*)x)->obj, a reference from T_DATA to VALUE, will be garbled after gc compaction.

typedef struct {
    VALUE  obj;     /* Back pointer(VALUE) for Ruby object.     */
    size_t MaxPrec;
    size_t Prec;
    SIGNED_VALUE exponent;
    short  sign;
    short  flag;
    DECDIG frac[FLEXIBLE_ARRAY_SIZE];
} Real;

After compaction, obj can be a reference to any kind of object.
The usage of obj field is limited. We should remove it from struct.

Reproduction code

p BigDecimal::VERSION
#=> "3.1.9", "3.2.1"

x = BigDecimal('1.5')
nan = BigDecimal("NaN")
inf = BigDecimal("Infinity")

GC.verify_compaction_references(expand_heap: true, toward: :empty)

x.divmod(inf) # Segfault
x.remainder(inf) # Segfault
nan + nan # Segfault
nan - nan # Segfault
BigMath.log(x, 10) # ??? can't be coerced into BigDecimal (TypeError)
BigMath.exp(x, 10) # Segfault
x**x # ??? can't be coerced into BigDecimal (ArgumentError)
x.power(x, 10) # ??? can't be coerced into BigDecimal (ArgumentError)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions