mirror of
https://github.com/golang/go
synced 2024-11-22 05:54:40 -07:00
encoding/asn1: promote untyped strings to UTF8 as needed.
Previously, strings that didn't have an explicit ASN.1 string type were taken to be ASN.1 PrintableStrings. This resulted in an error if a unrepresentable charactor was included. For compatibility reasons, I'm too afraid to switch the default string type to UTF8String, but this patch causes untyped strings to become UTF8Strings if they contain a charactor that's not valid in a PrintableString. Fixes #3791. R=golang-dev, bradfitz, r, r CC=golang-dev https://golang.org/cl/6348074
This commit is contained in:
parent
685a61df7e
commit
eeffa738a9
@ -251,7 +251,7 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{
|
||||
CommonName: commonName,
|
||||
Organization: []string{"Acme Co"},
|
||||
Organization: []string{"Σ Acme Co"},
|
||||
},
|
||||
NotBefore: time.Unix(1000, 0),
|
||||
NotAfter: time.Unix(100000, 0),
|
||||
|
@ -98,6 +98,8 @@ func parseFieldParameters(str string) (ret fieldParameters) {
|
||||
ret.stringType = tagIA5String
|
||||
case part == "printable":
|
||||
ret.stringType = tagPrintableString
|
||||
case part == "utf8":
|
||||
ret.stringType = tagUTF8String
|
||||
case strings.HasPrefix(part, "default:"):
|
||||
i, err := strconv.ParseInt(part[8:], 10, 64)
|
||||
if err == nil {
|
||||
|
@ -6,11 +6,13 @@ package asn1
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// A forkableWriter is an in-memory buffer that can be
|
||||
@ -280,6 +282,11 @@ func marshalIA5String(out *forkableWriter, s string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func marshalUTF8String(out *forkableWriter, s string) (err error) {
|
||||
_, err = out.Write([]byte(s))
|
||||
return
|
||||
}
|
||||
|
||||
func marshalTwoDigits(out *forkableWriter, v int) (err error) {
|
||||
err = out.WriteByte(byte('0' + (v/10)%10))
|
||||
if err != nil {
|
||||
@ -446,10 +453,13 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
|
||||
}
|
||||
return
|
||||
case reflect.String:
|
||||
if params.stringType == tagIA5String {
|
||||
switch params.stringType {
|
||||
case tagIA5String:
|
||||
return marshalIA5String(out, v.String())
|
||||
} else {
|
||||
case tagPrintableString:
|
||||
return marshalPrintableString(out, v.String())
|
||||
default:
|
||||
return marshalUTF8String(out, v.String())
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -492,11 +502,27 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
|
||||
}
|
||||
class := classUniversal
|
||||
|
||||
if params.stringType != 0 {
|
||||
if tag != tagPrintableString {
|
||||
return StructuralError{"Explicit string type given to non-string member"}
|
||||
if params.stringType != 0 && tag != tagPrintableString {
|
||||
return StructuralError{"Explicit string type given to non-string member"}
|
||||
}
|
||||
|
||||
if tag == tagPrintableString {
|
||||
if params.stringType == 0 {
|
||||
// This is a string without an explicit string type. We'll use
|
||||
// a PrintableString if the character set in the string is
|
||||
// sufficiently limited, otherwise we'll use a UTF8String.
|
||||
for _, r := range v.String() {
|
||||
if r >= utf8.RuneSelf || !isPrintable(byte(r)) {
|
||||
if !utf8.ValidString(v.String()) {
|
||||
return errors.New("asn1: string not valid UTF-8")
|
||||
}
|
||||
tag = tagUTF8String
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tag = params.stringType
|
||||
}
|
||||
tag = params.stringType
|
||||
}
|
||||
|
||||
if params.set {
|
||||
|
@ -122,6 +122,7 @@ var marshalTests = []marshalTest{
|
||||
{testSET([]int{10}), "310302010a"},
|
||||
{omitEmptyTest{[]string{}}, "3000"},
|
||||
{omitEmptyTest{[]string{"1"}}, "30053003130131"},
|
||||
{"Σ", "0c02cea3"},
|
||||
}
|
||||
|
||||
func TestMarshal(t *testing.T) {
|
||||
@ -137,3 +138,10 @@ func TestMarshal(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidUTF8(t *testing.T) {
|
||||
_, err := Marshal(string([]byte{0xff, 0xff}))
|
||||
if err == nil {
|
||||
t.Errorf("invalid UTF8 string was accepted")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user