From 6742d0a085021d9638a4d59dd8fb562aec8d51a8 Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Wed, 18 Apr 2012 13:41:11 -0400 Subject: [PATCH] encoding/asn1: allow lengths up to the maximum int value. Previously we capped lengths at 2**24 rather than 2**31. R=golang-dev, r, r CC=golang-dev https://golang.org/cl/6050050 --- src/pkg/encoding/asn1/asn1.go | 16 +++++++++++----- src/pkg/encoding/asn1/asn1_test.go | 6 ++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/pkg/encoding/asn1/asn1.go b/src/pkg/encoding/asn1/asn1.go index 3bf81a68cf..ac2b5f8daa 100644 --- a/src/pkg/encoding/asn1/asn1.go +++ b/src/pkg/encoding/asn1/asn1.go @@ -377,11 +377,6 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i } else { // Bottom 7 bits give the number of length bytes to follow. numBytes := int(b & 0x7f) - // We risk overflowing a signed 32-bit number if we accept more than 3 bytes. - if numBytes > 3 { - err = StructuralError{"length too large"} - return - } if numBytes == 0 { err = SyntaxError{"indefinite length found (not DER)"} return @@ -394,8 +389,19 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i } b = bytes[offset] offset++ + if ret.length >= 1<<23 { + // We can't shift ret.length up without + // overflowing. + err = StructuralError{"length too large"} + return + } ret.length <<= 8 ret.length |= int(b) + if ret.length == 0 { + // DER requires that lengths be minimal. + err = StructuralError{"superfluous leading zeros in length"} + return + } } } diff --git a/src/pkg/encoding/asn1/asn1_test.go b/src/pkg/encoding/asn1/asn1_test.go index 93803f4353..eb848bdb4a 100644 --- a/src/pkg/encoding/asn1/asn1_test.go +++ b/src/pkg/encoding/asn1/asn1_test.go @@ -283,6 +283,12 @@ var tagAndLengthData = []tagAndLengthTest{ {[]byte{0x00, 0x83, 0x01, 0x00}, false, tagAndLength{}}, {[]byte{0x1f, 0x85}, false, tagAndLength{}}, {[]byte{0x30, 0x80}, false, tagAndLength{}}, + // Superfluous zeros in the length should be an error. + {[]byte{0xa0, 0x82, 0x00, 0x01}, false, tagAndLength{}}, + // Lengths up to the maximum size of an int should work. + {[]byte{0xa0, 0x84, 0x7f, 0xff, 0xff, 0xff}, true, tagAndLength{2, 0, 0x7fffffff, true}}, + // Lengths that would overflow an int should be rejected. + {[]byte{0xa0, 0x84, 0x80, 0x00, 0x00, 0x00}, false, tagAndLength{}}, } func TestParseTagAndLength(t *testing.T) { -- 2.48.1