summaryrefslogtreecommitdiff
path: root/ruby.c
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2025-10-21 20:27:36 -0400
committerPeter Zhu <peter@peterzhu.ca>2025-10-22 19:36:47 -0400
commitda4bd3b3df9f26b7941808b2e291a6d6494e6c2f (patch)
tree5aec70a5acc193a5421e27d1893c9c76ff60d499 /ruby.c
parentdfcb79ca63336b614392e49e1d903deca26aa3e4 (diff)
Fix memory leak when RUBYOPT is invalid
When RUBYOPT is invalid, it raises an error which causes moreswitches to leak memory. It can be seen when building with LSAN enabled: $ RUBY_FREE_AT_EXIT=1 RUBYOPT=f ruby ruby: invalid option -f (-h will show valid options) (RuntimeError) Direct leak of 16 byte(s) in 1 object(s) allocated from: #0 0x618cef8efa23 in malloc (miniruby+0x64a23) #1 0x618cefa0e8d8 in rb_gc_impl_malloc gc/default/default.c:8182:5 #2 0x618cef9f7f01 in ruby_xmalloc2_body gc.c:5182:12 #3 0x618cef9f7eac in ruby_xmalloc2 gc.c:5176:34 #4 0x618cefb547b2 in moreswitches ruby.c:919:18 #5 0x618cefb526fe in process_options ruby.c:2350:9 #6 0x618cefb524ac in ruby_process_options ruby.c:3202:12 #7 0x618cef9dc11f in ruby_options eval.c:119:16 #8 0x618cef8f2fb5 in rb_main main.c:42:26 #9 0x618cef8f2f59 in main main.c:62:12
Diffstat (limited to 'ruby.c')
-rw-r--r--ruby.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/ruby.c b/ruby.c
index 05a9fd4191..0f5e6d60f7 100644
--- a/ruby.c
+++ b/ruby.c
@@ -916,7 +916,9 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt)
argc = RSTRING_LEN(argary) / sizeof(ap);
ap = 0;
rb_str_cat(argary, (char *)&ap, sizeof(ap));
- argv = ptr = ALLOC_N(char *, argc);
+
+ VALUE ptr_obj;
+ argv = ptr = RB_ALLOCV_N(char *, ptr_obj, argc);
MEMMOVE(argv, RSTRING_PTR(argary), char *, argc);
while ((i = proc_options(argc, argv, opt, envopt)) > 1 && envopt && (argc -= i) > 0) {
@@ -948,7 +950,8 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt)
opt->crash_report = crash_report;
}
- ruby_xfree(ptr);
+ RB_ALLOCV_END(ptr_obj);
+
/* get rid of GC */
rb_str_resize(argary, 0);
rb_str_resize(argstr, 0);