fix: in bindings/ruby/test/jfk_reader/jfk_reader in jfk_reader.c (#3756)
* fix: V-002 security vulnerability Automated security fix generated by Orbis Security AI * fix(ruby): use Ruby allocator macros in jfk_reader and fix memory leak - Replace calloc/free with ALLOC_N/xfree to match Ruby binding conventions (ALLOC_N handles overflow checking and raises NoMemoryError on failure) - Free temporary samples buffer after conversion loop (was leaked) - Add NULL check for fopen return value with rb_raise - Add comment clarifying n_samples is a compile-time constant Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ruby): return false instead of rb_raise in memory_view callback rb_memory_view_get_func_t callbacks should communicate errors via return value (false), not exceptions. rb_memory_view_get has no exception-handling wrapper around get_func calls. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * replacing ALLOC_N with rb_protect as ALLOC_N raises Ruby exceptions --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0ccd896f5b
commit
b3877e10c0
|
|
@ -2,6 +2,24 @@
|
||||||
#include <ruby/memory_view.h>
|
#include <ruby/memory_view.h>
|
||||||
#include <ruby/encoding.h>
|
#include <ruby/encoding.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
VALUE audio_path;
|
||||||
|
int n_samples;
|
||||||
|
const char *audio_path_str;
|
||||||
|
float *data;
|
||||||
|
short *samples;
|
||||||
|
} jfk_alloc_args;
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
jfk_reader_alloc_resources(VALUE arg)
|
||||||
|
{
|
||||||
|
jfk_alloc_args *a = (jfk_alloc_args *)arg;
|
||||||
|
a->audio_path_str = StringValueCStr(a->audio_path);
|
||||||
|
a->data = ALLOC_N(float, a->n_samples);
|
||||||
|
a->samples = ALLOC_N(short, a->n_samples);
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
jfk_reader_initialize(VALUE self, VALUE audio_path)
|
jfk_reader_initialize(VALUE self, VALUE audio_path)
|
||||||
{
|
{
|
||||||
|
|
@ -13,21 +31,42 @@ static bool
|
||||||
jfk_reader_get_memory_view(const VALUE obj, rb_memory_view_t *view, int flags)
|
jfk_reader_get_memory_view(const VALUE obj, rb_memory_view_t *view, int flags)
|
||||||
{
|
{
|
||||||
VALUE audio_path = rb_iv_get(obj, "audio_path");
|
VALUE audio_path = rb_iv_get(obj, "audio_path");
|
||||||
const char *audio_path_str = StringValueCStr(audio_path);
|
// n_samples is a fixed constant (not derived from user input).
|
||||||
const int n_samples = 176000;
|
const int n_samples = 176000;
|
||||||
float *data = (float *)malloc(n_samples * sizeof(float));
|
|
||||||
short *samples = (short *)malloc(n_samples * sizeof(short));
|
|
||||||
FILE *file = fopen(audio_path_str, "rb");
|
|
||||||
|
|
||||||
fseek(file, 78, SEEK_SET);
|
jfk_alloc_args args = {
|
||||||
fread(samples, sizeof(short), n_samples, file);
|
.audio_path = audio_path,
|
||||||
fclose(file);
|
.n_samples = n_samples,
|
||||||
for (int i = 0; i < n_samples; i++) {
|
.audio_path_str = NULL,
|
||||||
data[i] = samples[i]/32768.0;
|
.data = NULL,
|
||||||
|
.samples = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
int state;
|
||||||
|
rb_protect(jfk_reader_alloc_resources, (VALUE)&args, &state);
|
||||||
|
if (state) {
|
||||||
|
if (args.samples) xfree(args.samples);
|
||||||
|
if (args.data) xfree(args.data);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FILE *file = fopen(args.audio_path_str, "rb");
|
||||||
|
if (file == NULL) {
|
||||||
|
xfree(args.samples);
|
||||||
|
xfree(args.data);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 78, SEEK_SET);
|
||||||
|
fread(args.samples, sizeof(short), n_samples, file);
|
||||||
|
fclose(file);
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
args.data[i] = args.samples[i] / 32768.0;
|
||||||
|
}
|
||||||
|
xfree(args.samples);
|
||||||
|
|
||||||
view->obj = obj;
|
view->obj = obj;
|
||||||
view->data = (void *)data;
|
view->data = (void *)args.data;
|
||||||
view->byte_size = sizeof(float) * n_samples;
|
view->byte_size = sizeof(float) * n_samples;
|
||||||
view->readonly = true;
|
view->readonly = true;
|
||||||
view->format = "f";
|
view->format = "f";
|
||||||
|
|
@ -45,6 +84,10 @@ jfk_reader_get_memory_view(const VALUE obj, rb_memory_view_t *view, int flags)
|
||||||
static bool
|
static bool
|
||||||
jfk_reader_release_memory_view(const VALUE obj, rb_memory_view_t *view)
|
jfk_reader_release_memory_view(const VALUE obj, rb_memory_view_t *view)
|
||||||
{
|
{
|
||||||
|
if (view->data) {
|
||||||
|
xfree(view->data);
|
||||||
|
view->data = NULL;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue