From acb33a245009031fa7d96cc5cdbf53010b07afdf Mon Sep 17 00:00:00 2001 From: bbrtj Date: Tue, 17 Sep 2024 11:17:52 +0200 Subject: [PATCH] Add a test for edge cases --- Secp256k1.xs | 6 ++++- t/edge-cases.t | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 t/edge-cases.t diff --git a/Secp256k1.xs b/Secp256k1.xs index 2455a33..7b3c20a 100644 --- a/Secp256k1.xs +++ b/Secp256k1.xs @@ -59,6 +59,10 @@ void secp256k1_perl_replace_signature(secp256k1_perl *perl_ctx, secp256k1_ecdsa_ secp256k1_perl* ctx_from_sv(SV* self) { + if (!(sv_isobject(self) && sv_derived_from(self, "Bitcoin::Secp256k1"))) { + croak("calling Bitcoin::Secp256k1 methods is only valid in object context"); + } + return (secp256k1_perl*) SvIV(SvRV(self)); } @@ -88,7 +92,7 @@ new(classname) SPAGAIN; if (count != 1) { - croak("Calling Bytes::Random::Secure::random_bytes went wrong in Bitcoin::Secp256k1::new"); + croak("calling Bytes::Random::Secure::random_bytes went wrong in Bitcoin::Secp256k1::new"); } tmp = POPs; diff --git a/t/edge-cases.t b/t/edge-cases.t new file mode 100644 index 0000000..9d20ea6 --- /dev/null +++ b/t/edge-cases.t @@ -0,0 +1,60 @@ +use Test2::V0; +use Bitcoin::Secp256k1; + +use lib 't/lib'; +use Secp256k1Test; + +################################################################################ +# This tests if all foreseeable edge cases are handled correctly +################################################################################ + +my $secp = Bitcoin::Secp256k1->new; +my %t = Secp256k1Test->test_data; + +subtest 'should die on constructor with arguments' => sub { + my $ex = dies { Bitcoin::Secp256k1->new('argument') }; + like $ex, qr/\QUsage: Bitcoin::Secp256k1::new(classname)\E/, 'exception ok'; +}; + +subtest 'should die on low level methods without constructed object' => sub { + my $ex = dies { Bitcoin::Secp256k1->_pubkey }; + like $ex, qr/calling Bitcoin::Secp256k1 methods is only valid in object context/, 'exception ok'; +}; + +subtest 'should die on high level methods without constructed object' => sub { + my $ex = dies { Bitcoin::Secp256k1->create_public_key("\x12" x 32) }; + like $ex, qr/calling Bitcoin::Secp256k1 methods is only valid in object context/, 'exception ok'; +}; + +subtest 'should die with reference private key' => sub { + my $ex = dies { $secp->create_public_key([]) }; + like $ex, qr/requires a 32-byte secret key/, 'exception ok'; +}; + +subtest 'should die with invalid length private key' => sub { + my $ex; + + $ex = dies { $secp->create_public_key("\x12" x 31) }; + like $ex, qr/requires a 32-byte secret key/, 'too short ok'; + + $ex = dies { $secp->create_public_key("\x12" x 33) }; + like $ex, qr/requires a 32-byte secret key/, 'too long ok'; +}; + +subtest 'should die with invalid public key' => sub { + my $ex = dies { $secp->verify_digest("\x12" x 65, $t{sig}, "\x12" x 32) }; + like $ex, qr/the input does not appear to be a valid public key/, 'exception ok'; +}; + +subtest 'should die with invalid signature' => sub { + my $ex = dies { $secp->verify_digest($t{pubkey}, "\x12" x 65, "\x12" x 32) }; + like $ex, qr/the input does not appear to be a valid signature/, 'exception ok'; +}; + +subtest 'should die with invalid digest' => sub { + my $ex = dies { $secp->verify_digest($t{pubkey}, $t{sig}, "\x12" x 35) }; + like $ex, qr/requires a 32-byte message hash/, 'exception ok'; +}; + +done_testing; +