APPS/storeutl: fix case where uri and outfile are the same

Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25559)
This commit is contained in:
Dr. David von Oheimb 2024-09-27 08:24:45 +02:00 committed by Tomas Mraz
parent d1a0bbe658
commit 187952d449
3 changed files with 26 additions and 12 deletions

View File

@ -18,9 +18,11 @@
static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
int expected, int criterion, OSSL_STORE_SEARCH *search,
int text, int noout, int recursive, int indent, BIO *out,
int text, int noout, int recursive, int indent, const char *outfile,
const char *prog, OSSL_LIB_CTX *libctx);
static BIO *out = NULL;
typedef enum OPTION_choice {
OPT_COMMON,
OPT_ENGINE, OPT_OUT, OPT_PASSIN,
@ -71,7 +73,6 @@ int storeutl_main(int argc, char *argv[])
{
int ret = 1, noout = 0, text = 0, recursive = 0;
char *outfile = NULL, *passin = NULL, *passinarg = NULL;
BIO *out = NULL;
ENGINE *e = NULL;
OPTION_CHOICE o;
char *prog;
@ -311,13 +312,9 @@ int storeutl_main(int argc, char *argv[])
pw_cb_data.password = passin;
pw_cb_data.prompt_info = argv[0];
out = bio_open_default(outfile, 'w', FORMAT_TEXT);
if (out == NULL)
goto end;
ret = process(argv[0], get_ui_method(), &pw_cb_data,
expected, criterion, search,
text, noout, recursive, 0, out, prog, libctx);
text, noout, recursive, 0, outfile, prog, libctx);
end:
EVP_MD_free(digest);
@ -348,7 +345,7 @@ static int indent_printf(int indent, BIO *bio, const char *format, ...)
static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
int expected, int criterion, OSSL_STORE_SEARCH *search,
int text, int noout, int recursive, int indent, BIO *out,
int text, int noout, int recursive, int indent, const char *outfile,
const char *prog, OSSL_LIB_CTX *libctx)
{
OSSL_STORE_CTX *store_ctx = NULL;
@ -427,6 +424,13 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
indent_printf(indent, bio_out, "%d: %s\n", items, infostr);
}
if (out == NULL) {
if ((out = bio_open_default(outfile, 'w', FORMAT_TEXT)) == NULL) {
ret++;
goto end2;
}
}
/*
* Unfortunately, PEM_X509_INFO_write_bio() is sorely lacking in
* functionality, so we must figure out how exactly to write things
@ -438,7 +442,7 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
const char *suburi = OSSL_STORE_INFO_get0_NAME(info);
ret += process(suburi, uimeth, uidata,
expected, criterion, search,
text, noout, recursive, indent + 2, out, prog,
text, noout, recursive, indent + 2, outfile, prog,
libctx);
}
break;

View File

@ -45,8 +45,11 @@ Print out a usage message.
=item B<-out> I<filename>
specifies the output filename to write to or standard output by
default.
This specifies the output file to write to.
Standard output is used if this option is not present.
The output file can be the same as the input,
which leads to replacing the file contents.
Note that file I/O is not atomic. The output file is truncated and then written.
=item B<-noout>

View File

@ -16,6 +16,8 @@ use OpenSSL::Test::Utils;
my $test_name = "test_store";
setup($test_name);
require(srctop_file("test", "recipes", "tconversion.pl")); # for test_file_contains()
my $use_md5 = !disabled("md5");
my $use_des = !(disabled("des") || disabled("legacy")); # also affects 3des and pkcs12 app
my $use_dsa = !disabled("dsa");
@ -106,7 +108,7 @@ push @methods, [ @prov_method ];
push @methods, [qw(-engine loader_attic)]
unless disabled('loadereng');
my $n = 2 + scalar @methods
my $n = 4 + scalar @methods
* ( (3 * scalar @noexist_files)
+ (6 * scalar @src_files)
+ (2 * scalar @data_files)
@ -172,6 +174,11 @@ indir "store_$$" => sub {
my $rehash = init_rehash();
ok(run(app(["openssl", "storeutl", "-out", "cacert.pem", "cacert.pem"])),
"identical infile and outfile");
test_file_contains("storeutl output on same input",
"cacert.pem", "Total found: 1");
foreach my $method (@methods) {
my @storeutl = ( qw(openssl storeutl), @$method );