ankane/ruby-polars

Big Decimal causes rust index out of bounds.

pstalcup opened this issue · 1 comments

When I run this code in polars 0.8.0, I get a rust panic.

Polars::DataFrame.new([{a: BigDecimal("1e1")}])
thread '<unnamed>' panicked at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/polars-core-0.36.2/src/fmt.rs:1203:22:
index out of bounds: the len is 38 but the index is 18446744073709551615
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Running with the full backtrace enabled (as suggested by the error) generates):

3.2.2 :001 > Polars::DataFrame.new([{a: BigDecimal("1e1")}])
thread '<unnamed>' panicked at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/polars-core-0.36.2/src/fmt.rs:1203:22:
index out of bounds: the len is 38 but the index is 18446744073709551615
stack backtrace:
   0:        0x11cebf288 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h298c9ab285ff3934
   1:        0x11cede928 - core::fmt::write::h4e276abdb6d0c2a1
   2:        0x11cebd008 - std::io::Write::write_fmt::hd421848f5f0bf9d0
   3:        0x11cebf0c4 - std::sys_common::backtrace::print::hd8bd9ecab1f94b94
   4:        0x11cec03fc - std::panicking::default_hook::{{closure}}::h520eeb743fc98fb4
   5:        0x11cec0144 - std::panicking::default_hook::ha6550ffe49b63df1
   6:        0x11cec0824 - std::panicking::rust_panic_with_hook::hddb0e884a202de7c
   7:        0x11cec0724 - std::panicking::begin_panic_handler::{{closure}}::hd2798398a2fd9077
   8:        0x11cebf6f0 - std::sys_common::backtrace::__rust_end_short_backtrace::h9201cc364dbb8a23
   9:        0x11cec04c0 - _rust_begin_unwind
  10:        0x11d0c35f4 - core::panicking::panic_fmt::h4d5168028d4c43c7
  11:        0x11d0c3780 - core::panicking::panic_bounds_check::h17fa693e54374598
  12:        0x11c8d74c4 - polars_core::fmt::decimal::format_decimal::h79f6db754e64a156
  13:        0x11c647548 - polars_core::fmt::<impl core::fmt::Display for polars_core::datatypes::any_value::AnyValue>::fmt::h8a7af42ec90cf95f
  14:        0x11cede928 - core::fmt::write::h4e276abdb6d0c2a1
  15:        0x11ced62c0 - alloc::fmt::format::format_inner::h0896aa5e753a5414
  16:        0x11c9061c8 - polars_core::series::Series::str_value::hc94a2e5d812eaee7
  17:        0x11c30492c - <core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::fold::hbb7ededb66d98d12
  18:        0x11c35b3f8 - <alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter::h3e43f4e31c35e60b
  19:        0x11c6464a8 - polars_core::fmt::<impl core::fmt::Display for polars_core::frame::DataFrame>::fmt::h3c49372c8eba2c38
  20:        0x11cede928 - core::fmt::write::h4e276abdb6d0c2a1
  21:        0x11ced62c0 - alloc::fmt::format::format_inner::h0896aa5e753a5414
  22:        0x11aabc120 - std::panicking::try::h685e869281d7d140
  23:        0x11ad635b0 - polars::init::anon::h22fd8ada86c37f29
  24:        0x100c593fc - vm_call_cfunc_with_frame
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_insnhelper.c:3268:11
  25:        0x100c5b75c - vm_sendish
  26:        0x100c3cef4 - vm_exec_core
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/insns.def:820:11
  27:        0x100c5036c - rb_vm_exec
  28:        0x100c5fb70 - invoke_iseq_block_from_c
  29:        0x100c5fb70 - invoke_block_from_c_bh
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/vm.c:1472:20
  30:        0x100c5f2f4 - vm_yield_with_cref
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/vm.c:1509:12
  31:        0x100c5f2f4 - vm_yield
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/vm.c:1517:12
  32:        0x100c5f2f4 - rb_yield_0
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_eval.c:1348:12
  33:        0x100c5f2f4 - loop_i
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_eval.c:1447:9
  34:        0x100a95e1c - rb_vrescue2
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/eval.c:917:18
  35:        0x100a95c84 - rb_rescue2
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/eval.c:898:17
  36:        0x100c4bb6c - rb_f_loop
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_eval.c:1498:12
  37:        0x100c593fc - vm_call_cfunc_with_frame
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_insnhelper.c:3268:11
  38:        0x100c5b75c - vm_sendish
  39:        0x100c3cea8 - vm_exec_core
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/insns.def:801:11
  40:        0x100c5036c - rb_vm_exec
  41:        0x100c5fb70 - invoke_iseq_block_from_c
  42:        0x100c5fb70 - invoke_block_from_c_bh
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/vm.c:1472:20
  43:        0x100c5f23c - vm_yield_with_cref
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/vm.c:1509:12
  44:        0x100c5f23c - vm_yield
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/vm.c:1517:12
  45:        0x100c5f23c - rb_yield_0
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_eval.c:1348:12
  46:        0x100c5f23c - catch_i
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_eval.c:2311:12
  47:        0x100c4b1c0 - vm_catch_protect
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_eval.c:2393:15
  48:        0x100c4ba8c - rb_catch_obj
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_eval.c:2419:17
  49:        0x100c4ba8c - rb_f_catch
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_eval.c:2369:12
  50:        0x100c593fc - vm_call_cfunc_with_frame
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_insnhelper.c:3268:11
  51:        0x100c5b75c - vm_sendish
  52:        0x100c3cea8 - vm_exec_core
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/insns.def:801:11
  53:        0x100c5036c - rb_vm_exec
  54:        0x100c5fb70 - invoke_iseq_block_from_c
  55:        0x100c5fb70 - invoke_block_from_c_bh
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/vm.c:1472:20
  56:        0x100c5f23c - vm_yield_with_cref
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/vm.c:1509:12
  57:        0x100c5f23c - vm_yield
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/vm.c:1517:12
  58:        0x100c5f23c - rb_yield_0
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_eval.c:1348:12
  59:        0x100c5f23c - catch_i
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_eval.c:2311:12
  60:        0x100c4b1c0 - vm_catch_protect
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_eval.c:2393:15
  61:        0x100c4ba8c - rb_catch_obj
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_eval.c:2419:17
  62:        0x100c4ba8c - rb_f_catch
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_eval.c:2369:12
  63:        0x100c593fc - vm_call_cfunc_with_frame
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_insnhelper.c:3268:11
  64:        0x100c5b75c - vm_sendish
  65:        0x100c3cea8 - vm_exec_core
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/insns.def:801:11
  66:        0x100c5036c - rb_vm_exec
  67:        0x100af72b4 - load_iseq_eval
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/load.c:697:5
  68:        0x100af4eec - require_internal
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/load.c:1203:21
  69:        0x100af42b8 - rb_require_string
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/load.c:1294:18
  70:        0x100af42b8 - rb_f_require
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/load.c:938:12
  71:        0x100c593fc - vm_call_cfunc_with_frame
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_insnhelper.c:3268:11
  72:        0x100c55814 - vm_call_alias
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./vm_insnhelper.c:3447:12
  73:        0x100c5b75c - vm_sendish
  74:        0x100c3cef4 - vm_exec_core
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/insns.def:820:11
  75:        0x100c5036c - rb_vm_exec
  76:        0x100a952fc - rb_ec_exec_node
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/eval.c:289:9
  77:        0x100a95168 - ruby_run_node
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/eval.c:330:30
  78:        0x100547f34 - rb_main
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./main.c:38:12
  79:        0x100547f34 - main
                               at /Users/pstalcup/.rvm/src/ruby-3.2.2/./main.c:57:12
/Users/pstalcup/.rvm/gems/ruby-3.2.2@tiosftr/gems/polars-df-0.8.0-arm64-darwin/lib/polars/data_frame.rb:543:in `to_s': index out of bounds: the len is 38 but the index is 18446744073709551615 (fatal)

Reading through the error and some further debugging it seems to imply that it is the fact that this big decimal has a positive value after the e and no decimal part before the e, as none of the following generate errors:

Polars::DataFrame.new([{a: BigDecimal("1.1e1")}])
Polars::DataFrame.new([{a: BigDecimal("1e0")}])
Polars::DataFrame.new([{a: BigDecimal("1e-1")}])

I realize that BigDecimal support is still not fully there and we've changed our flow to avoid it where possible, but I just wanted to point out these errors.

ankane commented

Hi @pstalcup, thanks for reporting (and sorry you keep running into bugs)! Fixed in the commit above.