TL;DR

A vulnerability in Ruby's Array#pack implementation can cause out-of-bounds reads from the packed string buffer by abusing repeat counts in pack templates. The issue affects Ruby 4.0.0 and earlier releases and is being tracked in PR #15763.

What happened

Researcher Luke Jahnke revisited integer-handling code in MRI Ruby and identified a memory-disclosure bug in Array#pack. The pack method parses a template string made of directives and optional repeat counts. The code converts the repeat count using an unsigned conversion routine but stores the result into a signed long, allowing very large unsigned values to be interpreted as negative counts. When a negative repeat count reaches the 'X' directive (which moves the write position backward), the implementation can enlarge the destination string instead of shrinking it. That growth can extend the reported string length and expose adjacent heap contents as NUL-padded bytes, producing memory disclosure and, in some cases, a crash. The defect is present in Ruby 4.0.0 and likely in much older releases; a corrective change is being tracked in PR #15763.

Why it matters

  • The flaw can disclose memory from Ruby process address space via Array#pack output.
  • It arises from mismatched unsigned/signed handling of pack repeat counts, a low-level parsing bug.
  • The vulnerable method is uncommon and attacker control over template arguments is said to be rare, limiting practical exploitation in many deployments.
  • Attempts to leak arbitrary amounts are constrained by internal string-capacity checks, but significant data can still be exposed.

Key facts

  • Discovered by Luke Jahnke while auditing MRI integer handling after the Ruby 4.0.0 release.
  • Vulnerability is in the Array#pack instance method, which uses a template string of directives and repeat counts.
  • Repeat counts are parsed with an unsigned conversion but stored into a signed long, producing negative values for large inputs.
  • The 'X' directive, intended to back up one byte, uses the repeat count to change string length; a negative count can make the method grow the string instead.
  • Growing the string in this way can expose heap bytes appended as NULs in the packed result, demonstrated with examples that show leaked bytes and eventual crashes.
  • rb_str_set_len checks string length against capacity and prevents arbitrary expansion; capacity was observed to round up to a power of two, which limits the maximum safe leak.
  • The issue affects Ruby 4.0.0 and prior versions, and the report notes it likely goes back as far as Ruby 1.6.7 (2002).
  • A fix is being tracked in pull request PR #15763.

What to watch next

  • Progress and outcome of the corrective change tracked in PR #15763 (confirmed in the source).
  • Whether updated Ruby releases and security advisories are published for affected versions (not confirmed in the source).
  • Whether applications in your environment use Array#pack with untrusted template arguments and need mitigation or review (not confirmed in the source).

Quick glossary

  • Array#pack: A Ruby instance method that converts array elements into a binary string according to a template of directives and repeat counts.
  • Template directive: A character in a pack template that specifies how to format or interpret data (for example, hex or base64 directives).
  • STRTOUL / ruby_strtoul: A routine that parses an unsigned long integer from a string representation; using unsigned conversions can differ from signed types in edge cases.
  • rb_str_set_len: An internal Ruby routine that sets the recorded length of a String and performs checks against the string's capacity to avoid buffer overflows.

Reader FAQ

Which Ruby versions are affected?
The report identifies Ruby 4.0.0 and prior as affected and notes the bug likely dates back to Ruby 1.6.7.

Can an attacker read arbitrary process memory?
No. The source shows internal capacity checks limit how much can be exposed; however, substantial adjacent heap data can still be leaked.

Is this easily exploitable in real-world applications?
The author states Array#pack is rarely used and attacker control over the template argument is uncommon, which reduces practical exposure.

Has the bug been fixed?
A corrective change is being tracked in PR #15763; the source does not confirm whether a fix has been merged or released.

Ruby Array Pack Bleed Luke Jahnke 28 December 2025 With the release of Ruby 4.0.0 on Christmas, I decided to revisit integer handling bugs within Ruby MRI, the canonical implementation…

Sources

Related posts

By

Leave a Reply

Your email address will not be published. Required fields are marked *