mirror of
https://github.com/tailix/libkernaux.git
synced 2026-08-15 11:00:07 -04:00
Ruby: protect from memory leak in case of exception
This commit is contained in:
parent
8cbbba15b2
commit
88469daa71
2 changed files with 124 additions and 20 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "dynarg.h"
|
#include "dynarg.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <mruby/array.h>
|
#include <mruby/array.h>
|
||||||
|
|
|
||||||
|
|
@ -2,23 +2,77 @@
|
||||||
|
|
||||||
#include "dynarg.h"
|
#include "dynarg.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifdef KERNAUX_VERSION_WITH_PRINTF
|
#ifdef KERNAUX_VERSION_WITH_PRINTF
|
||||||
|
|
||||||
|
static ID rb_intern_freeze = Qnil;
|
||||||
|
|
||||||
|
/*************
|
||||||
|
* ::KernAux *
|
||||||
|
*************/
|
||||||
|
|
||||||
|
static VALUE rb_KernAux = Qnil;
|
||||||
|
|
||||||
static VALUE rb_KernAux_snprintf1(int argc, const VALUE *argv, VALUE self);
|
static VALUE rb_KernAux_snprintf1(int argc, const VALUE *argv, VALUE self);
|
||||||
|
|
||||||
static ID rb_intern_freeze = Qnil;
|
static VALUE rb_KernAux_snprintf1_PROTECT(VALUE userdata);
|
||||||
static VALUE rb_KernAux = Qnil;
|
|
||||||
|
/************************
|
||||||
|
* ::KernAux::Snprintf1 *
|
||||||
|
************************/
|
||||||
|
|
||||||
|
static VALUE rb_KernAux_Snprintf1 = Qnil;
|
||||||
|
|
||||||
|
static size_t rb_KernAux_Snprintf1_DSIZE(const void *ptr);
|
||||||
|
|
||||||
|
const rb_data_type_t rb_KernAux_Snprintf1_DTYPE = {
|
||||||
|
.wrap_struct_name = "KernAux::Snprintf1",
|
||||||
|
.parent = NULL,
|
||||||
|
.data = NULL,
|
||||||
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
||||||
|
.function = {
|
||||||
|
.dfree = RUBY_DEFAULT_FREE,
|
||||||
|
.dsize = rb_KernAux_Snprintf1_DSIZE,
|
||||||
|
.dmark = NULL,
|
||||||
|
.dcompact = NULL,
|
||||||
|
.reserved = { 0 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rb_KernAux_Snprintf1_DATA {
|
||||||
|
const struct KernAux_PrintfFmt_Spec *spec;
|
||||||
|
const struct DynArg *dynarg;
|
||||||
|
int size;
|
||||||
|
const char *format;
|
||||||
|
char *str;
|
||||||
|
};
|
||||||
|
|
||||||
|
/********
|
||||||
|
* Main *
|
||||||
|
********/
|
||||||
|
|
||||||
void init_printf()
|
void init_printf()
|
||||||
{
|
{
|
||||||
rb_gc_register_mark_object(ID2SYM(rb_intern_freeze = rb_intern("freeze")));
|
rb_gc_register_mark_object(ID2SYM(rb_intern_freeze = rb_intern("freeze")));
|
||||||
|
|
||||||
rb_gc_register_mark_object(rb_KernAux = rb_define_module("KernAux"));
|
rb_gc_register_mark_object(rb_KernAux = rb_define_module("KernAux"));
|
||||||
|
|
||||||
|
rb_gc_register_mark_object(
|
||||||
|
rb_KernAux_Snprintf1 =
|
||||||
|
// @api private
|
||||||
|
rb_define_class_under(rb_KernAux, "Snprintf1", rb_cObject));
|
||||||
|
rb_funcall(rb_KernAux, rb_intern("private_constant"), 1, ID2SYM(rb_intern("Snprintf1")));
|
||||||
|
|
||||||
rb_define_singleton_method(rb_KernAux, "snprintf1",
|
rb_define_singleton_method(rb_KernAux, "snprintf1",
|
||||||
rb_KernAux_snprintf1, -1);
|
rb_KernAux_snprintf1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: rewrite to ensure no memory leak on exception.
|
/*************
|
||||||
|
* ::KernAux *
|
||||||
|
*************/
|
||||||
|
|
||||||
VALUE rb_KernAux_snprintf1(
|
VALUE rb_KernAux_snprintf1(
|
||||||
const int argc,
|
const int argc,
|
||||||
const VALUE *const argv_rb,
|
const VALUE *const argv_rb,
|
||||||
|
|
@ -82,32 +136,72 @@ VALUE rb_KernAux_snprintf1(
|
||||||
char *const str = malloc(size);
|
char *const str = malloc(size);
|
||||||
if (!str) rb_raise(rb_eNoMemError, "snprintf1 buffer malloc");
|
if (!str) rb_raise(rb_eNoMemError, "snprintf1 buffer malloc");
|
||||||
|
|
||||||
|
struct rb_KernAux_Snprintf1_DATA *userdata;
|
||||||
|
VALUE userdata_rb = TypedData_Make_Struct(
|
||||||
|
rb_KernAux_Snprintf1,
|
||||||
|
struct rb_KernAux_Snprintf1_DATA,
|
||||||
|
&rb_KernAux_Snprintf1_DTYPE,
|
||||||
|
userdata
|
||||||
|
);
|
||||||
|
if (NIL_P(userdata_rb) || userdata == NULL) {
|
||||||
|
free(str);
|
||||||
|
rb_raise(rb_eNoMemError, "snprintf1 userdata alloc");
|
||||||
|
}
|
||||||
|
|
||||||
|
userdata->spec = &spec;
|
||||||
|
userdata->dynarg = &dynarg;
|
||||||
|
userdata->size = size;
|
||||||
|
userdata->format = format;
|
||||||
|
userdata->str = str;
|
||||||
|
|
||||||
|
int state = 0;
|
||||||
|
VALUE result =
|
||||||
|
rb_protect(rb_KernAux_snprintf1_PROTECT, userdata_rb, &state);
|
||||||
|
|
||||||
|
free(str);
|
||||||
|
|
||||||
|
if (state == 0) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
rb_jump_tag(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE rb_KernAux_snprintf1_PROTECT(VALUE userdata_rb)
|
||||||
|
{
|
||||||
|
const struct rb_KernAux_Snprintf1_DATA *userdata = NULL;
|
||||||
|
TypedData_Get_Struct(
|
||||||
|
userdata_rb,
|
||||||
|
struct rb_KernAux_Snprintf1_DATA,
|
||||||
|
&rb_KernAux_Snprintf1_DTYPE,
|
||||||
|
userdata
|
||||||
|
);
|
||||||
|
|
||||||
int slen;
|
int slen;
|
||||||
if (spec.set_width) {
|
if (userdata->spec->set_width) {
|
||||||
if (spec.set_precision) {
|
if (userdata->spec->set_precision) {
|
||||||
slen = dynarg.use_dbl
|
slen = userdata->dynarg->use_dbl
|
||||||
? kernaux_snprintf(str, size, format, spec.width, spec.precision, dynarg.dbl)
|
? kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->width, userdata->spec->precision, userdata->dynarg->dbl)
|
||||||
: kernaux_snprintf(str, size, format, spec.width, spec.precision, dynarg.arg);
|
: kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->width, userdata->spec->precision, userdata->dynarg->arg);
|
||||||
} else {
|
} else {
|
||||||
slen = dynarg.use_dbl
|
slen = userdata->dynarg->use_dbl
|
||||||
? kernaux_snprintf(str, size, format, spec.width, dynarg.dbl)
|
? kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->width, userdata->dynarg->dbl)
|
||||||
: kernaux_snprintf(str, size, format, spec.width, dynarg.arg);
|
: kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->width, userdata->dynarg->arg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (spec.set_precision) {
|
if (userdata->spec->set_precision) {
|
||||||
slen = dynarg.use_dbl
|
slen = userdata->dynarg->use_dbl
|
||||||
? kernaux_snprintf(str, size, format, spec.precision, dynarg.dbl)
|
? kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->precision, userdata->dynarg->dbl)
|
||||||
: kernaux_snprintf(str, size, format, spec.precision, dynarg.arg);
|
: kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->precision, userdata->dynarg->arg);
|
||||||
} else {
|
} else {
|
||||||
slen = dynarg.use_dbl
|
slen = userdata->dynarg->use_dbl
|
||||||
? kernaux_snprintf(str, size, format, dynarg.dbl)
|
? kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->dynarg->dbl)
|
||||||
: kernaux_snprintf(str, size, format, dynarg.arg);
|
: kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->dynarg->arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const VALUE output_rb =
|
const VALUE output_rb =
|
||||||
rb_funcall(rb_str_new2(str), rb_intern_freeze, 0);
|
rb_funcall(rb_str_new2(userdata->str), rb_intern_freeze, 0);
|
||||||
free(str);
|
|
||||||
|
|
||||||
const VALUE result_rb = rb_ary_new2(2);
|
const VALUE result_rb = rb_ary_new2(2);
|
||||||
rb_ary_push(result_rb, output_rb);
|
rb_ary_push(result_rb, output_rb);
|
||||||
|
|
@ -115,4 +209,13 @@ VALUE rb_KernAux_snprintf1(
|
||||||
return rb_funcall(result_rb, rb_intern_freeze, 0);
|
return rb_funcall(result_rb, rb_intern_freeze, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************
|
||||||
|
* ::KernAux::Snprintf1 *
|
||||||
|
************************/
|
||||||
|
|
||||||
|
size_t rb_KernAux_Snprintf1_DSIZE(const void *const ptr)
|
||||||
|
{
|
||||||
|
return sizeof(struct rb_KernAux_Snprintf1_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // KERNAUX_VERSION_WITH_PRINTF
|
#endif // KERNAUX_VERSION_WITH_PRINTF
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue