Skip to content

Commit ff7831b

Browse files
committed
Use rb_protect and Ruby internals to generate strings
1 parent 3ab7d62 commit ff7831b

File tree

2 files changed

+32
-23
lines changed

2 files changed

+32
-23
lines changed

ext/openssl/ossl_pkey.c

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -471,13 +471,14 @@ static const struct pkey_from_data_alias fcc_aliases[] = {
471471
};
472472

473473
struct pkey_from_data_arg {
474+
VALUE options;
474475
OSSL_PARAM_BLD *param_bld;
475476
const OSSL_PARAM *settable_params;
476477
const struct pkey_from_data_alias *aliases;
477478
};
478479

479480
static int
480-
add_parameter_to_builder(VALUE key, VALUE value, VALUE arg) {
481+
add_data_to_builder(VALUE key, VALUE value, VALUE arg) {
481482
if(NIL_P(value))
482483
return ST_CONTINUE;
483484

@@ -500,55 +501,53 @@ add_parameter_to_builder(VALUE key, VALUE value, VALUE arg) {
500501
case OSSL_PARAM_INTEGER:
501502
case OSSL_PARAM_UNSIGNED_INTEGER:
502503
if(!OSSL_PARAM_BLD_push_BN(params->param_bld, key_ptr, GetBNPtr(value))) {
503-
OSSL_PARAM_BLD_free(params->param_bld);
504504
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_BN");
505505
}
506506
break;
507507
case OSSL_PARAM_UTF8_STRING:
508508
StringValue(value);
509509
if(!OSSL_PARAM_BLD_push_utf8_string(params->param_bld, key_ptr, RSTRING_PTR(value), RSTRING_LENINT(value))) {
510-
OSSL_PARAM_BLD_free(params->param_bld);
511510
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_utf8_string");
512511
}
513512
break;
514513

515514
case OSSL_PARAM_OCTET_STRING:
516515
StringValue(value);
517516
if(!OSSL_PARAM_BLD_push_octet_string(params->param_bld, key_ptr, RSTRING_PTR(value), RSTRING_LENINT(value))) {
518-
OSSL_PARAM_BLD_free(params->param_bld);
519517
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_octet_string");
520518
}
521519
break;
522520
case OSSL_PARAM_UTF8_PTR:
523521
case OSSL_PARAM_OCTET_PTR:
524-
OSSL_PARAM_BLD_free(params->param_bld);
525522
ossl_raise(ePKeyError, "Unsupported parameter \"%s\", handling of OSSL_PARAM_UTF8_PTR and OSSL_PARAM_OCTET_PTR not implemented", key_ptr);
526523
break;
527524
}
528525

529526
return ST_CONTINUE;
530527
}
531528
}
532-
OSSL_PARAM_BLD_free(params->param_bld);
533529

534-
char message_buffer[512] = { 0 };
535-
char *cur = message_buffer;
536-
char *end = message_buffer + sizeof(message_buffer);
530+
VALUE supported_parameters = rb_ary_new();
531+
537532
for (const OSSL_PARAM *settable_params = params->settable_params; settable_params->key != NULL; settable_params++) {
538-
const char *fmt = cur == message_buffer ? "%s" : ", %s";
539-
if (cur > end)
540-
break;
541-
cur += snprintf(cur, end-cur, fmt, settable_params->key);
533+
rb_ary_push(supported_parameters, rb_str_new_cstr(settable_params->key));
542534
}
543535

544536
for(int i = 0; strlen(params->aliases[i].alias) > 0; i++) {
545-
const char *fmt = cur == message_buffer ? "%s" : ", %s";
546-
if (cur > end)
547-
break;
548-
cur += snprintf(cur, end-cur, fmt, params->aliases[i].alias);
537+
rb_ary_push(supported_parameters, rb_str_new_cstr(params->aliases[i].alias));
549538
}
550539

551-
ossl_raise(ePKeyError, "Invalid parameter \"%s\". Supported parameters: \"%s\"", key_ptr, message_buffer);
540+
ossl_raise(ePKeyError, "Invalid parameter \"%s\". Supported parameters: %"PRIsVALUE, key_ptr, rb_ary_join(supported_parameters, rb_str_new2(", ")));
541+
}
542+
543+
static VALUE
544+
add_data_to_builder_protected(VALUE value)
545+
{
546+
struct pkey_from_data_arg *args = (void *)value;
547+
548+
rb_hash_foreach(args->options, &add_data_to_builder, (VALUE) args);
549+
550+
return Qnil;
552551
}
553552

554553
static VALUE
@@ -567,6 +566,7 @@ pkey_from_data(int argc, VALUE *argv, VALUE self)
567566
struct pkey_from_data_arg from_data_args = { 0 };
568567

569568
from_data_args.param_bld = OSSL_PARAM_BLD_new();
569+
from_data_args.options = options;
570570

571571
if (from_data_args.param_bld == NULL) {
572572
EVP_PKEY_CTX_free(ctx);
@@ -577,6 +577,7 @@ pkey_from_data(int argc, VALUE *argv, VALUE self)
577577

578578
if (from_data_args.settable_params == NULL) {
579579
EVP_PKEY_CTX_free(ctx);
580+
OSSL_PARAM_BLD_free(from_data_args.param_bld);
580581
ossl_raise(ePKeyError, "EVP_PKEY_fromdata_settable");
581582
}
582583

@@ -585,7 +586,14 @@ pkey_from_data(int argc, VALUE *argv, VALUE self)
585586
else
586587
from_data_args.aliases = fcc_aliases;
587588

588-
rb_hash_foreach(options, &add_parameter_to_builder, (VALUE) &from_data_args);
589+
int state;
590+
rb_protect(add_data_to_builder_protected, (VALUE) &from_data_args, &state);
591+
592+
if(state) {
593+
EVP_PKEY_CTX_free(ctx);
594+
OSSL_PARAM_BLD_free(from_data_args.param_bld);
595+
rb_jump_tag(state);
596+
}
589597

590598
OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(from_data_args.param_bld);
591599
OSSL_PARAM_BLD_free(from_data_args.param_bld);
@@ -612,6 +620,7 @@ pkey_from_data(int argc, VALUE *argv, VALUE self)
612620

613621
return ossl_pkey_new(pkey);
614622
}
623+
615624
#endif
616625

617626
/*
@@ -686,11 +695,11 @@ ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self)
686695
static VALUE
687696
ossl_pkey_s_from_data(int argc, VALUE *argv, VALUE self)
688697
{
689-
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
698+
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
690699
return pkey_from_data(argc, argv, self);
691-
#else
700+
#else
692701
rb_raise(ePKeyError, "OpenSSL::PKey.from_data requires OpenSSL 3.0 or later");
693-
#endif
702+
#endif
694703
}
695704

696705
/*

test/openssl/test_pkey.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ def test_s_from_data_dsa_with_gem_specific_keys
413413
end
414414

415415
def test_s_from_data_dsa_with_invalid_parameter
416-
assert_raise_with_message(OpenSSL::PKey::PKeyError, /Invalid parameter "invalid"/) do
416+
assert_raise_with_message(OpenSSL::PKey::PKeyError, /Invalid parameter "invalid". Supported parameters: p, q, g, j/) do
417417
OpenSSL::PKey.from_data("DSA", invalid: 1234)
418418
end
419419
end

0 commit comments

Comments
 (0)