|
|
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 |
}
|