diff --git a/MD5.xs b/MD5.xs index 581b0e6..1c61c13 100644 --- a/MD5.xs +++ b/MD5.xs @@ -699,6 +699,8 @@ context(ctx, ...) STRLEN len; unsigned long blocks = SvUV(ST(1)); unsigned char *buf = (unsigned char *)(SvPV(ST(2), len)); + if (len < 16) + croak("Digest::MD5 context state must be exactly 16 bytes, got %"UVuf, (UV)len); ctx->A = buf[ 0] | (buf[ 1]<<8) | (buf[ 2]<<16) | (buf[ 3]<<24); ctx->B = buf[ 4] | (buf[ 5]<<8) | (buf[ 6]<<16) | (buf[ 7]<<24); ctx->C = buf[ 8] | (buf[ 9]<<8) | (buf[10]<<16) | (buf[11]<<24); @@ -707,6 +709,8 @@ context(ctx, ...) ctx->bytes_high = blocks >> 26; if (items == 4) { buf = (unsigned char *)(SvPV(ST(3), len)); + if (len > 63) + croak("Digest::MD5 context data must be at most 63 bytes, got %"UVuf, (UV)len); MD5Update(ctx, buf, len); } XSRETURN(1); /* ctx */ diff --git a/t/context.t b/t/context.t index a4d9782..b54ec15 100644 --- a/t/context.t +++ b/t/context.t @@ -2,7 +2,7 @@ use strict; use warnings; -use Test::More tests => 35; +use Test::More tests => 37; use Digest::MD5; foreach my $length ( @@ -41,3 +41,11 @@ foreach my $length ( is $got, $expect, "[$length] saved context"; } + +# Validate that context() croaks on short state buffer +eval { Digest::MD5->new->context(0, "short") }; +like $@, qr/must be exactly 16 bytes/, "context() croaks on short state buffer"; + +# Validate that context() croaks on overlong unprocessed data +eval { Digest::MD5->new->context(0, "\0" x 16, "x" x 64) }; +like $@, qr/must be at most 63 bytes/, "context() croaks on overlong data buffer"; diff --git a/t/files.t b/t/files.t index 2810c12..7361710 100644 --- a/t/files.t +++ b/t/files.t @@ -22,7 +22,7 @@ EOT # This is the output of: 'md5sum README MD5.xs rfc1321.txt' $EXPECT = <