Bug #10453


NUM2CHR() does not perform additional bounds checks

Added by silverhammermba (Max Anselm) over 8 years ago. Updated about 3 years ago.

Target version:
ruby -v:
ruby 2.1.4p265 (2014-10-27 revision 48166) [x86_64-linux]


NUM2CHR() just calls rb_num2int_inline() and masks off the high bytes. Consequently, passing any value larger than a char and no bigger than an int will return some garbage value (rather than raising RangeError).

To reproduce, compile and run:

#include <ruby.h>
#include <limits.h>

int main(int argc, char* argv[])
    char z = NUM2CHR(y);
    printf("%hhd\n", z);
    return ruby_cleanup(0);

Segfault from uncaught RangeError.

Prints -1


num2chr-range-check-10453.patch (1.35 KB) num2chr-range-check-10453.patch jeremyevans0 (Jeremy Evans), 08/12/2019 02:38 AM

Related issues 1 (0 open1 closed)

Related to Ruby master - Bug #15460: Behaviour of String#setbyte changedClosedshyouhei (Shyouhei Urabe)Actions

Updated by nobu (Nobuyoshi Nakada) over 8 years ago

  • Description updated (diff)
  • Category set to core
  • Status changed from Open to Assigned
  • Assignee set to matz (Yukihiro Matsumoto)
  • Target version set to 2.2.0

NUM2CHR rather should never raise RangeError for any arguments?

Updated by silverhammermba (Max Anselm) over 8 years ago

I would expect it to raise RangeError if the num exceeds the size of a char. That is the behavior of the all of the other NUM2* macros.

Actions #3

Updated by naruse (Yui NARUSE) about 5 years ago

  • Target version deleted (2.2.0)

Updated by jeremyevans0 (Jeremy Evans) over 3 years ago

Attached is a patch that will add a range check to NUM2CHR. However, it breaks a test:

1) Error:
RangeError: value to large to convert to char: 12356
    /home/jeremy/tmp/ruby/test/stringio/test_stringio.rb:567:in `putc'
    /home/jeremy/tmp/ruby/test/stringio/test_stringio.rb:567:in `test_putc_nonascii'

It is possibly, maybe even likely, that it will break third party C extensions as well (403 matches for NUM2CHR for Ruby on GitHub:

Updated by nobu (Nobuyoshi Nakada) over 3 years ago

As CHR should stand for char type of C, so exceeding the limit of char will make confusion, I guess.

I'm curious for what purpose @silverhammermba (Max Anselm) needs the range check.
If it is to get a codepoint, I don't think extracting the first byte from a string argument reasonable.

Actions #6

Updated by mame (Yusuke Endoh) about 3 years ago

  • Related to Bug #15460: Behaviour of String#setbyte changed added

Updated by mame (Yusuke Endoh) about 3 years ago

  • Status changed from Assigned to Rejected

See #15460. String#setbyte has accepted not only 0..255 but also any integers. Once it had been limited only to 0..255, but it caused a compatibility issue, and eventually was reverted.

I don't think that this is a good idea in terms of compatibility, unless there is a special reason to make it strict.

I tentatively close this because there is no response from OP. If we have a response, I'd be happy to reopen.


Also available in: Atom PDF