Blame SOURCES/31bit-OID-asn1.patch

de0c58
From 94aba76639cf4d5e30975d846bb0368db8202269 Mon Sep 17 00:00:00 2001
de0c58
From: Monis Khan <mkhan@redhat.com>
de0c58
Date: Wed, 12 Apr 2017 16:00:58 -0400
de0c58
Subject: [PATCH] encoding/asn1: support 31 bit identifiers with OID
de0c58
de0c58
The current implementation uses a max of 28 bits when decoding an
de0c58
ObjectIdentifier.  This change makes it so that an int64 is used to
de0c58
accumulate up to 35 bits.  If the resulting data would not overflow
de0c58
an int32, it is used as an int.  Thus up to 31 bits may be used to
de0c58
represent each subidentifier of an ObjectIdentifier.
de0c58
de0c58
Fixes #19933
de0c58
de0c58
Change-Id: I95d74b64b24cdb1339ff13421055bce61c80243c
de0c58
Reviewed-on: https://go-review.googlesource.com/40436
de0c58
Reviewed-by: Adam Langley <agl@golang.org>
de0c58
Run-TryBot: Adam Langley <agl@golang.org>
de0c58
---
de0c58
 src/encoding/asn1/asn1.go      | 15 ++++++++++++---
de0c58
 src/encoding/asn1/asn1_test.go |  3 +++
de0c58
 2 files changed, 15 insertions(+), 3 deletions(-)
de0c58
de0c58
diff --git a/src/encoding/asn1/asn1.go b/src/encoding/asn1/asn1.go
de0c58
index c2c0ee420ac..65f018d0148 100644
de0c58
--- a/src/encoding/asn1/asn1.go
de0c58
+++ b/src/encoding/asn1/asn1.go
de0c58
@@ -22,6 +22,7 @@ package asn1
de0c58
 import (
de0c58
 	"errors"
de0c58
 	"fmt"
de0c58
+	"math"
de0c58
 	"math/big"
de0c58
 	"reflect"
de0c58
 	"strconv"
de0c58
@@ -293,16 +294,24 @@ type Flag bool
de0c58
 // given byte slice. It returns the value and the new offset.
de0c58
 func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) {
de0c58
 	offset = initOffset
de0c58
+	var ret64 int64
de0c58
 	for shifted := 0; offset < len(bytes); shifted++ {
de0c58
-		if shifted == 4 {
de0c58
+		// 5 * 7 bits per byte == 35 bits of data
de0c58
+		// Thus the representation is either non-minimal or too large for an int32
de0c58
+		if shifted == 5 {
de0c58
 			err = StructuralError{"base 128 integer too large"}
de0c58
 			return
de0c58
 		}
de0c58
-		ret <<= 7
de0c58
+		ret64 <<= 7
de0c58
 		b := bytes[offset]
de0c58
-		ret |= int(b & 0x7f)
de0c58
+		ret64 |= int64(b & 0x7f)
de0c58
 		offset++
de0c58
 		if b&0x80 == 0 {
de0c58
+			ret = int(ret64)
de0c58
+			// Ensure that the returned value fits in an int on all platforms
de0c58
+			if ret64 > math.MaxInt32 {
de0c58
+				err = StructuralError{"base 128 integer too large"}
de0c58
+			}
de0c58
 			return
de0c58
 		}
de0c58
 	}
de0c58
diff --git a/src/encoding/asn1/asn1_test.go b/src/encoding/asn1/asn1_test.go
de0c58
index 9976656df89..2dd799f2362 100644
de0c58
--- a/src/encoding/asn1/asn1_test.go
de0c58
+++ b/src/encoding/asn1/asn1_test.go
de0c58
@@ -7,6 +7,7 @@ package asn1
de0c58
 import (
de0c58
 	"bytes"
de0c58
 	"fmt"
de0c58
+	"math"
de0c58
 	"math/big"
de0c58
 	"reflect"
de0c58
 	"strings"
de0c58
@@ -386,6 +387,8 @@ var tagAndLengthData = []tagAndLengthTest{
de0c58
 	{[]byte{0xa0, 0x81, 0x7f}, false, tagAndLength{}},
de0c58
 	// Tag numbers which would overflow int32 are rejected. (The value below is 2^31.)
de0c58
 	{[]byte{0x1f, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00}, false, tagAndLength{}},
de0c58
+	// Tag numbers that fit in an int32 are valid. (The value below is 2^31 - 1.)
de0c58
+	{[]byte{0x1f, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x00}, true, tagAndLength{tag: math.MaxInt32}},
de0c58
 	// Long tag number form may not be used for tags that fit in short form.
de0c58
 	{[]byte{0x1f, 0x1e, 0x00}, false, tagAndLength{}},
de0c58
 }