[dev.boringcrypto] all: merge master into dev.boringcrypto

Merge at CL 144340, in order to cherry-pick CL 149459 next to it, which
fixes a BoringCrypto specific breakage in the toolchain.

Change-Id: I30aeac344bbff279449e27876dc8f9c406e55e43
This commit is contained in:
Filippo Valsorda 2018-11-13 18:45:04 -05:00
commit 11e916773e
33 changed files with 688 additions and 176 deletions

View File

@ -14,6 +14,7 @@ import (
// io.ByteScanner, and io.RuneScanner interfaces by reading from
// a byte slice.
// Unlike a Buffer, a Reader is read-only and supports seeking.
// The zero value for Reader operates like a Reader of an empty slice.
type Reader struct {
s []byte
i int64 // current reading index
@ -75,10 +76,10 @@ func (r *Reader) ReadByte() (byte, error) {
// UnreadByte complements ReadByte in implementing the io.ByteScanner interface.
func (r *Reader) UnreadByte() error {
r.prevRune = -1
if r.i <= 0 {
return errors.New("bytes.Reader.UnreadByte: at beginning of slice")
}
r.prevRune = -1
r.i--
return nil
}
@ -101,6 +102,9 @@ func (r *Reader) ReadRune() (ch rune, size int, err error) {
// UnreadRune complements ReadRune in implementing the io.RuneScanner interface.
func (r *Reader) UnreadRune() error {
if r.i <= 0 {
return errors.New("bytes.Reader.UnreadRune: at beginning of slice")
}
if r.prevRune < 0 {
return errors.New("bytes.Reader.UnreadRune: previous operation was not ReadRune")
}

View File

@ -276,3 +276,45 @@ func TestReaderReset(t *testing.T) {
t.Errorf("ReadAll: got %q, want %q", got, want)
}
}
func TestReaderZero(t *testing.T) {
if l := (&Reader{}).Len(); l != 0 {
t.Errorf("Len: got %d, want 0", l)
}
if n, err := (&Reader{}).Read(nil); n != 0 || err != io.EOF {
t.Errorf("Read: got %d, %v; want 0, io.EOF", n, err)
}
if n, err := (&Reader{}).ReadAt(nil, 11); n != 0 || err != io.EOF {
t.Errorf("ReadAt: got %d, %v; want 0, io.EOF", n, err)
}
if b, err := (&Reader{}).ReadByte(); b != 0 || err != io.EOF {
t.Errorf("ReadByte: got %d, %v; want 0, io.EOF", b, err)
}
if ch, size, err := (&Reader{}).ReadRune(); ch != 0 || size != 0 || err != io.EOF {
t.Errorf("ReadRune: got %d, %d, %v; want 0, 0, io.EOF", ch, size, err)
}
if offset, err := (&Reader{}).Seek(11, io.SeekStart); offset != 11 || err != nil {
t.Errorf("Seek: got %d, %v; want 11, nil", offset, err)
}
if s := (&Reader{}).Size(); s != 0 {
t.Errorf("Size: got %d, want 0", s)
}
if (&Reader{}).UnreadByte() == nil {
t.Errorf("UnreadByte: got nil, want error")
}
if (&Reader{}).UnreadRune() == nil {
t.Errorf("UnreadRune: got nil, want error")
}
if n, err := (&Reader{}).WriteTo(ioutil.Discard); n != 0 || err != nil {
t.Errorf("WriteTo: got %d, %v; want 0, nil", n, err)
}
}

View File

@ -64,6 +64,9 @@ Flags:
instead of $GOROOT/pkg/$GOOS_$GOARCH.
-l
Disable inlining.
-lang version
Set language version to compile, as in -lang=go1.12.
Default is current version.
-largemodel
Generate code that assumes a large memory model.
-linkobj file

View File

@ -762,12 +762,20 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
sc := v.AuxValAndOff()
off := sc.Off()
val := sc.Val()
if val == 1 {
if val == 1 || val == -1 {
var asm obj.As
if v.Op == ssa.OpAMD64ADDQconstmodify {
asm = x86.AINCQ
if val == 1 {
asm = x86.AINCQ
} else {
asm = x86.ADECQ
}
} else {
asm = x86.AINCL
if val == 1 {
asm = x86.AINCL
} else {
asm = x86.ADECL
}
}
p := s.Prog(asm)
p.To.Type = obj.TYPE_MEM

View File

@ -117,8 +117,8 @@ var runtimeDecls = [...]struct {
{"selectsetpc", funcTag, 56},
{"selectgo", funcTag, 93},
{"block", funcTag, 5},
{"makeslice", funcTag, 95},
{"makeslice64", funcTag, 96},
{"makeslice", funcTag, 94},
{"makeslice64", funcTag, 95},
{"growslice", funcTag, 97},
{"memmove", funcTag, 98},
{"memclrNoHeapPointers", funcTag, 99},
@ -249,10 +249,10 @@ func runtimeTypes() []*types.Type {
typs[91] = types.NewPtr(typs[11])
typs[92] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[91]), anonfield(typs[79])}, []*Node{anonfield(typs[11])})
typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[32]), anonfield(typs[11])})
typs[94] = types.NewSlice(typs[2])
typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[94])})
typs[96] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[94])})
typs[97] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[94]), anonfield(typs[32])}, []*Node{anonfield(typs[94])})
typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[58])})
typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[58])})
typs[96] = types.NewSlice(typs[2])
typs[97] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[96]), anonfield(typs[32])}, []*Node{anonfield(typs[96])})
typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, nil)
typs[99] = functype(nil, []*Node{anonfield(typs[58]), anonfield(typs[47])}, nil)
typs[100] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, []*Node{anonfield(typs[11])})

View File

@ -153,8 +153,8 @@ func selectsetpc(cas *byte)
func selectgo(cas0 *byte, order0 *byte, ncases int) (int, bool)
func block()
func makeslice(typ *byte, len int, cap int) (ary []any)
func makeslice64(typ *byte, len int64, cap int64) (ary []any)
func makeslice(typ *byte, len int, cap int) unsafe.Pointer
func makeslice64(typ *byte, len int64, cap int64) unsafe.Pointer
func growslice(typ *byte, old []any, cap int) (ary []any)
func memmove(to *any, frm *any, length uintptr)
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)

View File

@ -0,0 +1,59 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gc
import (
"internal/testenv"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"testing"
)
const aliasSrc = `
package x
type T = int
`
func TestInvalidLang(t *testing.T) {
t.Parallel()
testenv.MustHaveGoBuild(t)
dir, err := ioutil.TempDir("", "TestInvalidLang")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
src := filepath.Join(dir, "alias.go")
if err := ioutil.WriteFile(src, []byte(aliasSrc), 0644); err != nil {
t.Fatal(err)
}
outfile := filepath.Join(dir, "alias.o")
if testLang(t, "go9.99", src, outfile) == nil {
t.Error("compilation with -lang=go9.99 succeeded unexpectedly")
}
if testLang(t, "go1.8", src, outfile) == nil {
t.Error("compilation with -lang=go1.8 succeeded unexpectedly")
}
if err := testLang(t, "go1.9", src, outfile); err != nil {
t.Errorf("compilation with -lang=go1.9 failed unexpectedly: %v", err)
}
}
func testLang(t *testing.T, lang, src, outfile string) error {
run := []string{testenv.GoToolPath(t), "tool", "compile", "-lang", lang, "-o", outfile, src}
t.Log(run)
out, err := exec.Command(run[0], run[1:]...).CombinedOutput()
t.Logf("%s", out)
return err
}

View File

@ -19,11 +19,13 @@ import (
"cmd/internal/sys"
"flag"
"fmt"
"go/build"
"io"
"io/ioutil"
"log"
"os"
"path"
"regexp"
"runtime"
"strconv"
"strings"
@ -211,6 +213,7 @@ func Main(archInit func(*Arch)) {
flag.StringVar(&flag_installsuffix, "installsuffix", "", "set pkg directory `suffix`")
objabi.Flagcount("j", "debug runtime-initialized variables", &Debug['j'])
objabi.Flagcount("l", "disable inlining", &Debug['l'])
flag.StringVar(&flag_lang, "lang", defaultLang(), "release to compile for")
flag.StringVar(&linkobj, "linkobj", "", "write linker-specific object to `file`")
objabi.Flagcount("live", "debug liveness analysis", &debuglive)
objabi.Flagcount("m", "print optimization decisions", &Debug['m'])
@ -277,6 +280,8 @@ func Main(archInit func(*Arch)) {
Exit(2)
}
checkLang()
thearch.LinkArch.Init(Ctxt)
if outfile == "" {
@ -1304,3 +1309,66 @@ func recordFlags(flags ...string) {
Ctxt.Data = append(Ctxt.Data, s)
s.P = cmd.Bytes()[1:]
}
// flag_lang is the language version we are compiling for, set by the -lang flag.
var flag_lang string
// defaultLang returns the default value for the -lang flag.
func defaultLang() string {
tags := build.Default.ReleaseTags
return tags[len(tags)-1]
}
// goVersionRE is a regular expression that matches the valid
// arguments to the -lang flag.
var goVersionRE = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
// A lang is a language version broken into major and minor numbers.
type lang struct {
major, minor int
}
// langWant is the desired language version set by the -lang flag.
var langWant lang
// langSupported reports whether language version major.minor is supported.
func langSupported(major, minor int) bool {
return langWant.major > major || (langWant.major == major && langWant.minor >= minor)
}
// checkLang verifies that the -lang flag holds a valid value, and
// exits if not. It initializes data used by langSupported.
func checkLang() {
var err error
langWant, err = parseLang(flag_lang)
if err != nil {
log.Fatalf("invalid value %q for -lang: %v", flag_lang, err)
}
if def := defaultLang(); flag_lang != def {
defVers, err := parseLang(def)
if err != nil {
log.Fatalf("internal error parsing default lang %q: %v", def, err)
}
if langWant.major > defVers.major || (langWant.major == defVers.major && langWant.major > defVers.minor) {
log.Fatalf("invalid value %q for -lang: max known version is %q", flag_lang, def)
}
}
}
// parseLang parses a -lang option into a langVer.
func parseLang(s string) (lang, error) {
matches := goVersionRE.FindStringSubmatch(s)
if matches == nil {
return lang{}, fmt.Errorf(`should be something like "go1.12"`)
}
major, err := strconv.Atoi(matches[1])
if err != nil {
return lang{}, err
}
minor, err := strconv.Atoi(matches[2])
if err != nil {
return lang{}, err
}
return lang{major: major, minor: minor}, nil
}

View File

@ -417,8 +417,11 @@ func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
param.Pragma = 0
}
return p.nod(decl, ODCLTYPE, n, nil)
nod := p.nod(decl, ODCLTYPE, n, nil)
if param.Alias && !langSupported(1, 9) {
yyerrorl(nod.Pos, "type aliases only supported as of -lang=go1.9")
}
return nod
}
func (p *noder) declNames(names []*syntax.Name) []*Node {

View File

@ -4,9 +4,9 @@ package gc
import "strconv"
const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDARRAYBYTESTRARRAYBYTESTRTMPARRAYRUNESTRSTRARRAYBYTESTRARRAYBYTETMPSTRARRAYRUNEASAS2AS2FUNCAS2RECVAS2MAPRAS2DOTTYPEASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTINDINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNOTCOMPLUSMINUSORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASEXCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELPROCRANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDDDDARGINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVEINDREGSPRETJMPGETGEND"
const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDARRAYBYTESTRARRAYBYTESTRTMPARRAYRUNESTRSTRARRAYBYTESTRARRAYBYTETMPSTRARRAYRUNEASAS2AS2FUNCAS2RECVAS2MAPRAS2DOTTYPEASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTINDINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNOTCOMPLUSMINUSORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICEHEADERSLICE3SLICE3ARRRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASEXCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELPROCRANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDDDDARGINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVEINDREGSPRETJMPGETGEND"
var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 73, 88, 100, 112, 127, 139, 141, 144, 151, 158, 165, 175, 179, 183, 191, 199, 208, 216, 219, 224, 231, 238, 244, 253, 261, 269, 275, 279, 288, 295, 299, 302, 309, 317, 325, 332, 338, 341, 347, 354, 362, 366, 373, 381, 383, 385, 387, 389, 391, 393, 396, 401, 409, 412, 421, 424, 428, 436, 443, 452, 455, 458, 461, 464, 467, 470, 476, 479, 482, 485, 489, 494, 498, 503, 508, 514, 519, 523, 528, 536, 544, 550, 559, 566, 570, 577, 584, 592, 596, 600, 604, 611, 618, 626, 632, 637, 642, 646, 651, 659, 664, 669, 673, 676, 684, 688, 690, 695, 699, 704, 710, 716, 722, 728, 733, 737, 744, 750, 755, 761, 764, 770, 777, 782, 786, 791, 795, 805, 810, 818, 824, 831, 838, 846, 852, 856, 859}
var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 73, 88, 100, 112, 127, 139, 141, 144, 151, 158, 165, 175, 179, 183, 191, 199, 208, 216, 219, 224, 231, 238, 244, 253, 261, 269, 275, 279, 288, 295, 299, 302, 309, 317, 325, 332, 338, 341, 347, 354, 362, 366, 373, 381, 383, 385, 387, 389, 391, 393, 396, 401, 409, 412, 421, 424, 428, 436, 443, 452, 455, 458, 461, 464, 467, 470, 476, 479, 482, 485, 489, 494, 498, 503, 508, 514, 519, 523, 528, 536, 544, 555, 561, 570, 577, 581, 588, 595, 603, 607, 611, 615, 622, 629, 637, 643, 648, 653, 657, 662, 670, 675, 680, 684, 687, 695, 699, 701, 706, 710, 715, 721, 727, 733, 739, 744, 748, 755, 761, 766, 772, 775, 781, 788, 793, 797, 802, 806, 816, 821, 829, 835, 842, 849, 857, 863, 867, 870}
func (i Op) String() string {
if i >= Op(len(_Op_index)-1) {

View File

@ -2321,6 +2321,12 @@ func (s *state) expr(n *Node) *ssa.Value {
data := s.expr(n.Right)
return s.newValue2(ssa.OpIMake, n.Type, tab, data)
case OSLICEHEADER:
p := s.expr(n.Left)
l := s.expr(n.List.First())
c := s.expr(n.List.Second())
return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c)
case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR:
v := s.expr(n.Left)
var i, j, k *ssa.Value

View File

@ -636,65 +636,66 @@ const (
ODCLCONST // const pi = 3.14
ODCLTYPE // type Int int or type Int = int
ODELETE // delete(Left, Right)
ODOT // Left.Sym (Left is of struct type)
ODOTPTR // Left.Sym (Left is of pointer to struct type)
ODOTMETH // Left.Sym (Left is non-interface, Right is method name)
ODOTINTER // Left.Sym (Left is interface, Right is method name)
OXDOT // Left.Sym (before rewrite to one of the preceding)
ODOTTYPE // Left.Right or Left.Type (.Right during parsing, .Type once resolved); after walk, .Right contains address of interface type descriptor and .Right.Right contains address of concrete type descriptor
ODOTTYPE2 // Left.Right or Left.Type (.Right during parsing, .Type once resolved; on rhs of OAS2DOTTYPE); after walk, .Right contains address of interface type descriptor
OEQ // Left == Right
ONE // Left != Right
OLT // Left < Right
OLE // Left <= Right
OGE // Left >= Right
OGT // Left > Right
OIND // *Left
OINDEX // Left[Right] (index of array or slice)
OINDEXMAP // Left[Right] (index of map)
OKEY // Left:Right (key:value in struct/array/map literal)
OSTRUCTKEY // Sym:Left (key:value in struct literal, after type checking)
OLEN // len(Left)
OMAKE // make(List) (before type checking converts to one of the following)
OMAKECHAN // make(Type, Left) (type is chan)
OMAKEMAP // make(Type, Left) (type is map)
OMAKESLICE // make(Type, Left, Right) (type is slice)
OMUL // Left * Right
ODIV // Left / Right
OMOD // Left % Right
OLSH // Left << Right
ORSH // Left >> Right
OAND // Left & Right
OANDNOT // Left &^ Right
ONEW // new(Left)
ONOT // !Left
OCOM // ^Left
OPLUS // +Left
OMINUS // -Left
OOROR // Left || Right
OPANIC // panic(Left)
OPRINT // print(List)
OPRINTN // println(List)
OPAREN // (Left)
OSEND // Left <- Right
OSLICE // Left[List[0] : List[1]] (Left is untypechecked or slice)
OSLICEARR // Left[List[0] : List[1]] (Left is array)
OSLICESTR // Left[List[0] : List[1]] (Left is string)
OSLICE3 // Left[List[0] : List[1] : List[2]] (Left is untypedchecked or slice)
OSLICE3ARR // Left[List[0] : List[1] : List[2]] (Left is array)
ORECOVER // recover()
ORECV // <-Left
ORUNESTR // Type(Left) (Type is string, Left is rune)
OSELRECV // Left = <-Right.Left: (appears as .Left of OCASE; Right.Op == ORECV)
OSELRECV2 // List = <-Right.Left: (apperas as .Left of OCASE; count(List) == 2, Right.Op == ORECV)
OIOTA // iota
OREAL // real(Left)
OIMAG // imag(Left)
OCOMPLEX // complex(Left, Right)
OALIGNOF // unsafe.Alignof(Left)
OOFFSETOF // unsafe.Offsetof(Left)
OSIZEOF // unsafe.Sizeof(Left)
ODELETE // delete(Left, Right)
ODOT // Left.Sym (Left is of struct type)
ODOTPTR // Left.Sym (Left is of pointer to struct type)
ODOTMETH // Left.Sym (Left is non-interface, Right is method name)
ODOTINTER // Left.Sym (Left is interface, Right is method name)
OXDOT // Left.Sym (before rewrite to one of the preceding)
ODOTTYPE // Left.Right or Left.Type (.Right during parsing, .Type once resolved); after walk, .Right contains address of interface type descriptor and .Right.Right contains address of concrete type descriptor
ODOTTYPE2 // Left.Right or Left.Type (.Right during parsing, .Type once resolved; on rhs of OAS2DOTTYPE); after walk, .Right contains address of interface type descriptor
OEQ // Left == Right
ONE // Left != Right
OLT // Left < Right
OLE // Left <= Right
OGE // Left >= Right
OGT // Left > Right
OIND // *Left
OINDEX // Left[Right] (index of array or slice)
OINDEXMAP // Left[Right] (index of map)
OKEY // Left:Right (key:value in struct/array/map literal)
OSTRUCTKEY // Sym:Left (key:value in struct literal, after type checking)
OLEN // len(Left)
OMAKE // make(List) (before type checking converts to one of the following)
OMAKECHAN // make(Type, Left) (type is chan)
OMAKEMAP // make(Type, Left) (type is map)
OMAKESLICE // make(Type, Left, Right) (type is slice)
OMUL // Left * Right
ODIV // Left / Right
OMOD // Left % Right
OLSH // Left << Right
ORSH // Left >> Right
OAND // Left & Right
OANDNOT // Left &^ Right
ONEW // new(Left)
ONOT // !Left
OCOM // ^Left
OPLUS // +Left
OMINUS // -Left
OOROR // Left || Right
OPANIC // panic(Left)
OPRINT // print(List)
OPRINTN // println(List)
OPAREN // (Left)
OSEND // Left <- Right
OSLICE // Left[List[0] : List[1]] (Left is untypechecked or slice)
OSLICEARR // Left[List[0] : List[1]] (Left is array)
OSLICESTR // Left[List[0] : List[1]] (Left is string)
OSLICE3 // Left[List[0] : List[1] : List[2]] (Left is untypedchecked or slice)
OSLICE3ARR // Left[List[0] : List[1] : List[2]] (Left is array)
OSLICEHEADER // sliceheader{Left, List[0], List[1]} (Left is unsafe.Pointer, List[0] is length, List[1] is capacity)
ORECOVER // recover()
ORECV // <-Left
ORUNESTR // Type(Left) (Type is string, Left is rune)
OSELRECV // Left = <-Right.Left: (appears as .Left of OCASE; Right.Op == ORECV)
OSELRECV2 // List = <-Right.Left: (apperas as .Left of OCASE; count(List) == 2, Right.Op == ORECV)
OIOTA // iota
OREAL // real(Left)
OIMAG // imag(Left)
OCOMPLEX // complex(Left, Right)
OALIGNOF // unsafe.Alignof(Left)
OOFFSETOF // unsafe.Offsetof(Left)
OSIZEOF // unsafe.Sizeof(Left)
// statements
OBLOCK // { List } (block of code)

View File

@ -1086,6 +1086,47 @@ func typecheck1(n *Node, top int) *Node {
n.Right = assignconv(r, t.Elem(), "send")
n.Type = nil
case OSLICEHEADER:
// Errors here are Fatalf instead of yyerror because only the compiler
// can construct an OSLICEHEADER node.
// Components used in OSLICEHEADER that are supplied by parsed source code
// have already been typechecked in e.g. OMAKESLICE earlier.
ok |= Erv
t := n.Type
if !t.IsSlice() {
Fatalf("invalid type %v for OSLICEHEADER", n.Type)
}
if !n.Left.Type.IsUnsafePtr() {
Fatalf("need unsafe.Pointer for OSLICEHEADER")
}
if x := n.List.Len(); x != 2 {
Fatalf("expected 2 params (len, cap) for OSLICEHEADER, got %d", x)
}
n.Left = typecheck(n.Left, Erv)
l := typecheck(n.List.First(), Erv)
c := typecheck(n.List.Second(), Erv)
l = defaultlit(l, types.Types[TINT])
c = defaultlit(c, types.Types[TINT])
if Isconst(l, CTINT) && l.Int64() < 0 {
Fatalf("len for OSLICEHEADER must be non-negative")
}
if Isconst(c, CTINT) && c.Int64() < 0 {
Fatalf("cap for OSLICEHEADER must be non-negative")
}
if Isconst(l, CTINT) && Isconst(c, CTINT) && l.Val().U.(*Mpint).Cmp(c.Val().U.(*Mpint)) > 0 {
Fatalf("len larger than cap for OSLICEHEADER")
}
n.List.SetFirst(l)
n.List.SetSecond(c)
case OSLICE, OSLICE3:
ok |= Erv
n.Left = typecheck(n.Left, Erv)

View File

@ -1118,6 +1118,11 @@ opswitch:
case ORECV:
Fatalf("walkexpr ORECV") // should see inside OAS only
case OSLICEHEADER:
n.Left = walkexpr(n.Left, init)
n.List.SetFirst(walkexpr(n.List.First(), init))
n.List.SetSecond(walkexpr(n.List.Second(), init))
case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
n.Left = walkexpr(n.Left, init)
low, high, max := n.SliceBounds()
@ -1339,8 +1344,13 @@ opswitch:
}
fn := syslook(fnname)
fn = substArgTypes(fn, t.Elem()) // any-1
n = mkcall1(fn, t, init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))
n.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))
n.Left.SetNonNil(true)
n.List.Set2(conv(len, types.Types[TINT]), conv(cap, types.Types[TINT]))
n.Op = OSLICEHEADER
n.Type = t
n = typecheck(n, Erv)
n = walkexpr(n, init)
}
case ORUNESTR:

View File

@ -7,6 +7,7 @@ package main_test
import (
"bytes"
"cmd/internal/sys"
"context"
"debug/elf"
"debug/macho"
"flag"
@ -108,6 +109,12 @@ var testGo string
var testTmpDir string
var testBin string
// testCtx is canceled when the test binary is about to time out.
//
// If https://golang.org/issue/28135 is accepted, uses of this variable in test
// functions should be replaced by t.Context().
var testCtx = context.Background()
// The TestMain function creates a go command for testing purposes and
// deletes it after the tests have been run.
func TestMain(m *testing.M) {
@ -120,6 +127,20 @@ func TestMain(m *testing.M) {
os.Unsetenv("GOROOT_FINAL")
flag.Parse()
timeoutFlag := flag.Lookup("test.timeout")
if timeoutFlag != nil {
// TODO(golang.org/issue/28147): The go command does not pass the
// test.timeout flag unless either -timeout or -test.timeout is explicitly
// set on the command line.
if d := timeoutFlag.Value.(flag.Getter).Get().(time.Duration); d != 0 {
aBitShorter := d * 95 / 100
var cancel context.CancelFunc
testCtx, cancel = context.WithTimeout(testCtx, aBitShorter)
defer cancel()
}
}
if *proxyAddr != "" {
StartProxy()
select {}

View File

@ -9,6 +9,7 @@ package main_test
import (
"bytes"
"context"
"fmt"
"internal/testenv"
"io/ioutil"
@ -55,21 +56,28 @@ func TestScript(t *testing.T) {
// A testScript holds execution state for a single test script.
type testScript struct {
t *testing.T
workdir string // temporary work dir ($WORK)
log bytes.Buffer // test execution log (printed at end of test)
mark int // offset of next log truncation
cd string // current directory during test execution; initially $WORK/gopath/src
name string // short name of test ("foo")
file string // full file name ("testdata/script/foo.txt")
lineno int // line number currently executing
line string // line currently executing
env []string // environment list (for os/exec)
envMap map[string]string // environment mapping (matches env)
stdout string // standard output from last 'go' command; for 'stdout' command
stderr string // standard error from last 'go' command; for 'stderr' command
stopped bool // test wants to stop early
start time.Time // time phase started
t *testing.T
workdir string // temporary work dir ($WORK)
log bytes.Buffer // test execution log (printed at end of test)
mark int // offset of next log truncation
cd string // current directory during test execution; initially $WORK/gopath/src
name string // short name of test ("foo")
file string // full file name ("testdata/script/foo.txt")
lineno int // line number currently executing
line string // line currently executing
env []string // environment list (for os/exec)
envMap map[string]string // environment mapping (matches env)
stdout string // standard output from last 'go' command; for 'stdout' command
stderr string // standard error from last 'go' command; for 'stderr' command
stopped bool // test wants to stop early
start time.Time // time phase started
background []backgroundCmd // backgrounded 'exec' and 'go' commands
}
type backgroundCmd struct {
cmd *exec.Cmd
wait <-chan struct{}
neg bool // if true, cmd should fail
}
var extraEnvKeys = []string{
@ -146,6 +154,17 @@ func (ts *testScript) run() {
}
defer func() {
// On a normal exit from the test loop, background processes are cleaned up
// before we print PASS. If we return early (e.g., due to a test failure),
// don't print anything about the processes that were still running.
for _, bg := range ts.background {
interruptProcess(bg.cmd.Process)
}
for _, bg := range ts.background {
<-bg.wait
}
ts.background = nil
markTime()
// Flush testScript log to testing.T log.
ts.t.Log("\n" + ts.abbrev(ts.log.String()))
@ -284,14 +303,23 @@ Script:
// Command can ask script to stop early.
if ts.stopped {
return
// Break instead of returning, so that we check the status of any
// background processes and print PASS.
break
}
}
for _, bg := range ts.background {
interruptProcess(bg.cmd.Process)
}
ts.cmdWait(false, nil)
// Final phase ended.
rewind()
markTime()
fmt.Fprintf(&ts.log, "PASS\n")
if !ts.stopped {
fmt.Fprintf(&ts.log, "PASS\n")
}
}
// scriptCmds are the script command implementations.
@ -317,6 +345,7 @@ var scriptCmds = map[string]func(*testScript, bool, []string){
"stdout": (*testScript).cmdStdout,
"stop": (*testScript).cmdStop,
"symlink": (*testScript).cmdSymlink,
"wait": (*testScript).cmdWait,
}
// addcrlf adds CRLF line endings to the named files.
@ -451,26 +480,43 @@ func (ts *testScript) cmdEnv(neg bool, args []string) {
// exec runs the given command.
func (ts *testScript) cmdExec(neg bool, args []string) {
if len(args) < 1 {
ts.fatalf("usage: exec program [args...]")
if len(args) < 1 || (len(args) == 1 && args[0] == "&") {
ts.fatalf("usage: exec program [args...] [&]")
}
var err error
ts.stdout, ts.stderr, err = ts.exec(args[0], args[1:]...)
if ts.stdout != "" {
fmt.Fprintf(&ts.log, "[stdout]\n%s", ts.stdout)
}
if ts.stderr != "" {
fmt.Fprintf(&ts.log, "[stderr]\n%s", ts.stderr)
if len(args) > 0 && args[len(args)-1] == "&" {
var cmd *exec.Cmd
cmd, err = ts.execBackground(args[0], args[1:len(args)-1]...)
if err == nil {
wait := make(chan struct{})
go func() {
ctxWait(testCtx, cmd)
close(wait)
}()
ts.background = append(ts.background, backgroundCmd{cmd, wait, neg})
}
ts.stdout, ts.stderr = "", ""
} else {
ts.stdout, ts.stderr, err = ts.exec(args[0], args[1:]...)
if ts.stdout != "" {
fmt.Fprintf(&ts.log, "[stdout]\n%s", ts.stdout)
}
if ts.stderr != "" {
fmt.Fprintf(&ts.log, "[stderr]\n%s", ts.stderr)
}
if err == nil && neg {
ts.fatalf("unexpected command success")
}
}
if err != nil {
fmt.Fprintf(&ts.log, "[%v]\n", err)
if !neg {
if testCtx.Err() != nil {
ts.fatalf("test timed out while running command")
} else if !neg {
ts.fatalf("unexpected command failure")
}
} else {
if neg {
ts.fatalf("unexpected command success")
}
}
}
@ -545,6 +591,14 @@ func (ts *testScript) cmdSkip(neg bool, args []string) {
if neg {
ts.fatalf("unsupported: ! skip")
}
// Before we mark the test as skipped, shut down any background processes and
// make sure they have returned the correct status.
for _, bg := range ts.background {
interruptProcess(bg.cmd.Process)
}
ts.cmdWait(false, nil)
if len(args) == 1 {
ts.t.Skip(args[0])
}
@ -687,6 +741,52 @@ func (ts *testScript) cmdSymlink(neg bool, args []string) {
ts.check(os.Symlink(args[2], ts.mkabs(args[0])))
}
// wait waits for background commands to exit, setting stderr and stdout to their result.
func (ts *testScript) cmdWait(neg bool, args []string) {
if neg {
ts.fatalf("unsupported: ! wait")
}
if len(args) > 0 {
ts.fatalf("usage: wait")
}
var stdouts, stderrs []string
for _, bg := range ts.background {
<-bg.wait
args := append([]string{filepath.Base(bg.cmd.Args[0])}, bg.cmd.Args[1:]...)
fmt.Fprintf(&ts.log, "[background] %s: %v\n", strings.Join(args, " "), bg.cmd.ProcessState)
cmdStdout := bg.cmd.Stdout.(*strings.Builder).String()
if cmdStdout != "" {
fmt.Fprintf(&ts.log, "[stdout]\n%s", cmdStdout)
stdouts = append(stdouts, cmdStdout)
}
cmdStderr := bg.cmd.Stderr.(*strings.Builder).String()
if cmdStderr != "" {
fmt.Fprintf(&ts.log, "[stderr]\n%s", cmdStderr)
stderrs = append(stderrs, cmdStderr)
}
if bg.cmd.ProcessState.Success() {
if bg.neg {
ts.fatalf("unexpected command success")
}
} else {
if testCtx.Err() != nil {
ts.fatalf("test timed out while running command")
} else if !bg.neg {
ts.fatalf("unexpected command failure")
}
}
}
ts.stdout = strings.Join(stdouts, "")
ts.stderr = strings.Join(stderrs, "")
ts.background = nil
}
// Helpers for command implementations.
// abbrev abbreviates the actual work directory in the string s to the literal string "$WORK".
@ -716,10 +816,51 @@ func (ts *testScript) exec(command string, args ...string) (stdout, stderr strin
var stdoutBuf, stderrBuf strings.Builder
cmd.Stdout = &stdoutBuf
cmd.Stderr = &stderrBuf
err = cmd.Run()
if err = cmd.Start(); err == nil {
err = ctxWait(testCtx, cmd)
}
return stdoutBuf.String(), stderrBuf.String(), err
}
// execBackground starts the given command line (an actual subprocess, not simulated)
// in ts.cd with environment ts.env.
func (ts *testScript) execBackground(command string, args ...string) (*exec.Cmd, error) {
cmd := exec.Command(command, args...)
cmd.Dir = ts.cd
cmd.Env = append(ts.env, "PWD="+ts.cd)
var stdoutBuf, stderrBuf strings.Builder
cmd.Stdout = &stdoutBuf
cmd.Stderr = &stderrBuf
return cmd, cmd.Start()
}
// ctxWait is like cmd.Wait, but terminates cmd with os.Interrupt if ctx becomes done.
//
// This differs from exec.CommandContext in that it prefers os.Interrupt over os.Kill.
// (See https://golang.org/issue/21135.)
func ctxWait(ctx context.Context, cmd *exec.Cmd) error {
errc := make(chan error, 1)
go func() { errc <- cmd.Wait() }()
select {
case err := <-errc:
return err
case <-ctx.Done():
interruptProcess(cmd.Process)
return <-errc
}
}
// interruptProcess sends os.Interrupt to p if supported, or os.Kill otherwise.
func interruptProcess(p *os.Process) {
if err := p.Signal(os.Interrupt); err != nil {
// Per https://golang.org/pkg/os/#Signal, “Interrupt is not implemented on
// Windows; using it with os.Process.Signal will return an error.”
// Fall back to Kill instead.
p.Kill()
}
}
// expand applies environment variable expansion to the string s.
func (ts *testScript) expand(s string) string {
return os.Expand(s, func(key string) string { return ts.envMap[key] })

View File

@ -99,16 +99,23 @@ The commands are:
With no arguments, print the environment (useful for debugging).
Otherwise add the listed key=value pairs to the environment.
- [!] exec program [args...]
- [!] exec program [args...] [&]
Run the given executable program with the arguments.
It must (or must not) succeed.
Note that 'exec' does not terminate the script (unlike in Unix shells).
If the last token is '&', the program executes in the background. The standard
output and standard error of the previous command is cleared, but the output
of the background process is buffered — and checking of its exit status is
delayed — until the next call to 'wait', 'skip', or 'stop' or the end of the
test. At the end of the test, any remaining background processes are
terminated using os.Interrupt (if supported) or os.Kill.
- [!] exists [-readonly] file...
Each of the listed files or directories must (or must not) exist.
If -readonly is given, the files or directories must be unwritable.
- [!] go args...
- [!] go args... [&]
Run the (test copy of the) go command with the given arguments.
It must (or must not) succeed.
@ -131,11 +138,11 @@ The commands are:
- [!] stderr [-count=N] pattern
Apply the grep command (see above) to the standard error
from the most recent exec or go command.
from the most recent exec, go, or wait command.
- [!] stdout [-count=N] pattern
Apply the grep command (see above) to the standard output
from the most recent exec or go command.
from the most recent exec, go, or wait command.
- stop [message]
Stop the test early (marking it as passing), including the message if given.
@ -143,6 +150,13 @@ The commands are:
- symlink file -> target
Create file as a symlink to target. The -> (like in ls -l output) is required.
- wait
Wait for all 'exec' and 'go' commands started in the background (with the '&'
token) to exit, and display success or failure status for them.
After a call to wait, the 'stderr' and 'stdout' commands will apply to the
concatenation of the corresponding streams of the background commands,
in the order in which those commands were started.
When TestScript runs a script and the script fails, by default TestScript shows
the execution of the most recent phase of the script (since the last # comment)
and only shows the # comments for earlier phases. For example, here is a

View File

@ -0,0 +1,22 @@
[!exec:echo] skip
[!exec:false] skip
exec echo foo
stdout foo
exec echo foo &
exec echo bar &
! exec false &
# Starting a background process should clear previous output.
! stdout foo
# Wait should set the output to the concatenated outputs of the background
# programs, in the order in which they were started.
wait
stdout 'foo\nbar'
# The end of the test should interrupt or kill any remaining background
# programs.
[!exec:sleep] skip
! exec sleep 86400 &

View File

@ -11,7 +11,6 @@ package tls
// https://www.imperialviolet.org/2013/02/04/luckythirteen.html.
import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/rsa"
@ -30,10 +29,7 @@ import (
// The configuration config must be non-nil and must include
// at least one certificate or else set GetCertificate.
func Server(conn net.Conn, config *Config) *Conn {
return &Conn{
conn: conn, config: config,
input: *bytes.NewReader(nil), // Issue 28269
}
return &Conn{conn: conn, config: config}
}
// Client returns a new TLS client side connection
@ -41,10 +37,7 @@ func Server(conn net.Conn, config *Config) *Conn {
// The config cannot be nil: users must set either ServerName or
// InsecureSkipVerify in the config.
func Client(conn net.Conn, config *Config) *Conn {
return &Conn{
conn: conn, config: config, isClient: true,
input: *bytes.NewReader(nil), // Issue 28269
}
return &Conn{conn: conn, config: config, isClient: true}
}
// A listener implements a network listener (net.Listener) for TLS connections.

View File

@ -45,6 +45,7 @@ type Context struct {
// which defaults to the list of Go releases the current release is compatible with.
// In addition to the BuildTags and ReleaseTags, build constraints
// consider the values of GOARCH and GOOS as satisfied tags.
// The last element in ReleaseTags is assumed to be the current release.
BuildTags []string
ReleaseTags []string
@ -296,6 +297,7 @@ func defaultContext() Context {
// say "+build go1.x", and code that should only be built before Go 1.x
// (perhaps it is the stub to use in that case) should say "+build !go1.x".
// NOTE: If you add to this list, also update the doc comment in doc.go.
// NOTE: The last element in ReleaseTags should be the current release.
const version = 11 // go1.11
for i := 1; i <= version; i++ {
c.ReleaseTags = append(c.ReleaseTags, "go1."+strconv.Itoa(i))

View File

@ -47,27 +47,18 @@ type x86 struct {
var PPC64 ppc64
// For ppc64x, it is safe to check only for ISA level starting on ISA v3.00,
// For ppc64(le), it is safe to check only for ISA level starting on ISA v3.00,
// since there are no optional categories. There are some exceptions that also
// require kernel support to work (darn, scv), so there are feature bits for
// those as well. The minimum processor requirement is POWER8 (ISA 2.07), so we
// maintain some of the old feature checks for optional categories for
// safety.
// those as well. The minimum processor requirement is POWER8 (ISA 2.07).
// The struct is padded to avoid false sharing.
type ppc64 struct {
_ CacheLinePad
HasVMX bool // Vector unit (Altivec)
HasDFP bool // Decimal Floating Point unit
HasVSX bool // Vector-scalar unit
HasHTM bool // Hardware Transactional Memory
HasISEL bool // Integer select
HasVCRYPTO bool // Vector cryptography
HasHTMNOSC bool // HTM: kernel-aborted transaction in syscalls
HasDARN bool // Hardware random number generator (requires kernel enablement)
HasSCV bool // Syscall vectored (requires kernel enablement)
IsPOWER8 bool // ISA v2.07 (POWER8)
IsPOWER9 bool // ISA v3.00 (POWER9)
_ CacheLinePad
_ CacheLinePad
HasDARN bool // Hardware random number generator (requires kernel enablement)
HasSCV bool // Syscall vectored (requires kernel enablement)
IsPOWER8 bool // ISA v2.07 (POWER8)
IsPOWER9 bool // ISA v3.00 (POWER9)
_ CacheLinePad
}
var ARM arm

View File

@ -21,44 +21,22 @@ const (
_PPC_FEATURE2_ARCH_3_00 = 0x00800000
// CPU features
_PPC_FEATURE_HAS_ALTIVEC = 0x10000000
_PPC_FEATURE_HAS_DFP = 0x00000400
_PPC_FEATURE_HAS_VSX = 0x00000080
_PPC_FEATURE2_HAS_HTM = 0x40000000
_PPC_FEATURE2_HAS_ISEL = 0x08000000
_PPC_FEATURE2_HAS_VEC_CRYPTO = 0x02000000
_PPC_FEATURE2_HTM_NOSC = 0x01000000
_PPC_FEATURE2_DARN = 0x00200000
_PPC_FEATURE2_SCV = 0x00100000
_PPC_FEATURE2_DARN = 0x00200000
_PPC_FEATURE2_SCV = 0x00100000
)
func doinit() {
options = []option{
{Name: "htm", Feature: &PPC64.HasHTM},
{Name: "htmnosc", Feature: &PPC64.HasHTMNOSC},
{Name: "darn", Feature: &PPC64.HasDARN},
{Name: "scv", Feature: &PPC64.HasSCV},
{Name: "power9", Feature: &PPC64.IsPOWER9},
// These capabilities should always be enabled on ppc64 and ppc64le:
{Name: "power8", Feature: &PPC64.IsPOWER8, Required: true},
{Name: "vmx", Feature: &PPC64.HasVMX, Required: true},
{Name: "dfp", Feature: &PPC64.HasDFP, Required: true},
{Name: "vsx", Feature: &PPC64.HasVSX, Required: true},
{Name: "isel", Feature: &PPC64.HasISEL, Required: true},
{Name: "vcrypto", Feature: &PPC64.HasVCRYPTO, Required: true},
}
// HWCAP feature bits
PPC64.HasVMX = isSet(HWCap, _PPC_FEATURE_HAS_ALTIVEC)
PPC64.HasDFP = isSet(HWCap, _PPC_FEATURE_HAS_DFP)
PPC64.HasVSX = isSet(HWCap, _PPC_FEATURE_HAS_VSX)
// HWCAP2 feature bits
PPC64.IsPOWER8 = isSet(HWCap2, _PPC_FEATURE2_ARCH_2_07)
PPC64.HasHTM = isSet(HWCap2, _PPC_FEATURE2_HAS_HTM)
PPC64.HasISEL = isSet(HWCap2, _PPC_FEATURE2_HAS_ISEL)
PPC64.HasVCRYPTO = isSet(HWCap2, _PPC_FEATURE2_HAS_VEC_CRYPTO)
PPC64.HasHTMNOSC = isSet(HWCap2, _PPC_FEATURE2_HTM_NOSC)
PPC64.IsPOWER9 = isSet(HWCap2, _PPC_FEATURE2_ARCH_3_00)
PPC64.HasDARN = isSet(HWCap2, _PPC_FEATURE2_DARN)
PPC64.HasSCV = isSet(HWCap2, _PPC_FEATURE2_SCV)

View File

@ -43,7 +43,7 @@ const debugFloat = false // enable for debugging
// precision of the argument with the largest precision value before any
// rounding takes place, and the rounding mode remains unchanged. Thus,
// uninitialized Floats provided as result arguments will have their
// precision set to a reasonable value determined by the operands and
// precision set to a reasonable value determined by the operands, and
// their mode is the zero value for RoundingMode (ToNearestEven).
//
// By setting the desired precision to 24 or 53 and using matching rounding
@ -56,6 +56,12 @@ const debugFloat = false // enable for debugging
// The zero (uninitialized) value for a Float is ready to use and represents
// the number +0.0 exactly, with precision 0 and rounding mode ToNearestEven.
//
// Operations always take pointer arguments (*Float) rather
// than Float values, and each unique Float value requires
// its own unique *Float pointer. To "copy" a Float value,
// an existing (or newly allocated) Float must be set to
// a new value using the Float.Set method; shallow copies
// of Floats are not supported and may lead to errors.
type Float struct {
prec uint32
mode RoundingMode

View File

@ -15,6 +15,13 @@ import (
// An Int represents a signed multi-precision integer.
// The zero value for an Int represents the value 0.
//
// Operations always take pointer arguments (*Int) rather
// than Int values, and each unique Int value requires
// its own unique *Int pointer. To "copy" an Int value,
// an existing (or newly allocated) Int must be set to
// a new value using the Int.Set method; shallow copies
// of Ints are not supported and may lead to errors.
type Int struct {
neg bool // sign
abs nat // absolute value of the integer

View File

@ -13,6 +13,13 @@ import (
// A Rat represents a quotient a/b of arbitrary precision.
// The zero value for a Rat represents the value 0.
//
// Operations always take pointer arguments (*Rat) rather
// than Rat values, and each unique Rat value requires
// its own unique *Rat pointer. To "copy" a Rat value,
// an existing (or newly allocated) Rat must be set to
// a new value using the Rat.Set method; shallow copies
// of Rats are not supported and may lead to errors.
type Rat struct {
// To make zero values for Rat work w/o initialization,
// a zero value of b (len(b) == 0) acts like b == 1.

View File

@ -53,8 +53,9 @@ var (
// available.
ErrNotSupported = &ProtocolError{"feature not supported"}
// ErrUnexpectedTrailer is returned by the Transport when a server
// replies with a Trailer header, but without a chunked reply.
// Deprecated: ErrUnexpectedTrailer is no longer returned by
// anything in the net/http package. Callers should not
// compare errors against this variable.
ErrUnexpectedTrailer = &ProtocolError{"trailer header without chunked transfer encoding"}
// ErrMissingBoundary is returned by Request.MultipartReader when the

View File

@ -157,6 +157,34 @@ var respTests = []respTest{
"Body here\ncontinued",
},
// Trailer header but no TransferEncoding
{
"HTTP/1.0 200 OK\r\n" +
"Trailer: Content-MD5, Content-Sources\r\n" +
"Content-Length: 10\r\n" +
"Connection: close\r\n" +
"\r\n" +
"Body here\n",
Response{
Status: "200 OK",
StatusCode: 200,
Proto: "HTTP/1.0",
ProtoMajor: 1,
ProtoMinor: 0,
Request: dummyReq("GET"),
Header: Header{
"Connection": {"close"},
"Content-Length": {"10"},
"Trailer": []string{"Content-MD5, Content-Sources"},
},
Close: true,
ContentLength: 10,
},
"Body here\n",
},
// Chunked response with Content-Length.
{
"HTTP/1.1 200 OK\r\n" +

View File

@ -740,6 +740,16 @@ func fixTrailer(header Header, te []string) (Header, error) {
if !ok {
return nil, nil
}
if !chunked(te) {
// Trailer and no chunking:
// this is an invalid use case for trailer header.
// Nevertheless, no error will be returned and we
// let users decide if this is a valid HTTP message.
// The Trailer header will be kept in Response.Header
// but not populate Response.Trailer.
// See issue #27197.
return nil, nil
}
header.Del("Trailer")
trailer := make(Header)
@ -763,10 +773,6 @@ func fixTrailer(header Header, te []string) (Header, error) {
if len(trailer) == 0 {
return nil, nil
}
if !chunked(te) {
// Trailer and no chunking
return nil, ErrUnexpectedTrailer
}
return trailer, nil
}

View File

@ -266,8 +266,11 @@ func testGdbPython(t *testing.T, cgo bool) {
infoLocalsRe1 := regexp.MustCompile(`slicevar *= *\[\]string *= *{"def"}`)
// Format output from gdb v8.2
infoLocalsRe2 := regexp.MustCompile(`^slicevar = .*\nmapvar = .*\nstrvar = 0x[0-9a-f]+ "abc"`)
// Format output from gdb v7.7
infoLocalsRe3 := regexp.MustCompile(`^mapvar = .*\nstrvar = "abc"\nslicevar *= *\[\]string`)
if bl := blocks["info locals"]; !infoLocalsRe1.MatchString(bl) &&
!infoLocalsRe2.MatchString(bl) {
!infoLocalsRe2.MatchString(bl) &&
!infoLocalsRe3.MatchString(bl) {
t.Fatalf("info locals failed: %s", bl)
}

View File

@ -31,7 +31,7 @@ func panicmakeslicecap() {
panic(errorString("makeslice: cap out of range"))
}
func makeslice(et *_type, len, cap int) slice {
func makeslice(et *_type, len, cap int) unsafe.Pointer {
mem, overflow := math.MulUintptr(et.size, uintptr(cap))
if overflow || mem > maxAlloc || len < 0 || len > cap {
// NOTE: Produce a 'len out of range' error instead of a
@ -45,12 +45,11 @@ func makeslice(et *_type, len, cap int) slice {
}
panicmakeslicecap()
}
p := mallocgc(mem, et, true)
return slice{p, len, cap}
return mallocgc(mem, et, true)
}
func makeslice64(et *_type, len64, cap64 int64) slice {
func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer {
len := int(len64)
if int64(len) != len64 {
panicmakeslicelen()

View File

@ -13,6 +13,7 @@ import (
// A Reader implements the io.Reader, io.ReaderAt, io.Seeker, io.WriterTo,
// io.ByteScanner, and io.RuneScanner interfaces by reading
// from a string.
// The zero value for Reader operates like a Reader of an empty string.
type Reader struct {
s string
i int64 // current reading index
@ -70,10 +71,10 @@ func (r *Reader) ReadByte() (byte, error) {
}
func (r *Reader) UnreadByte() error {
r.prevRune = -1
if r.i <= 0 {
return errors.New("strings.Reader.UnreadByte: at beginning of string")
}
r.prevRune = -1
r.i--
return nil
}
@ -94,6 +95,9 @@ func (r *Reader) ReadRune() (ch rune, size int, err error) {
}
func (r *Reader) UnreadRune() error {
if r.i <= 0 {
return errors.New("strings.Reader.UnreadRune: at beginning of string")
}
if r.prevRune < 0 {
return errors.New("strings.Reader.UnreadRune: previous operation was not ReadRune")
}

View File

@ -190,3 +190,45 @@ func TestReaderReset(t *testing.T) {
t.Errorf("ReadAll: got %q, want %q", got, want)
}
}
func TestReaderZero(t *testing.T) {
if l := (&strings.Reader{}).Len(); l != 0 {
t.Errorf("Len: got %d, want 0", l)
}
if n, err := (&strings.Reader{}).Read(nil); n != 0 || err != io.EOF {
t.Errorf("Read: got %d, %v; want 0, io.EOF", n, err)
}
if n, err := (&strings.Reader{}).ReadAt(nil, 11); n != 0 || err != io.EOF {
t.Errorf("ReadAt: got %d, %v; want 0, io.EOF", n, err)
}
if b, err := (&strings.Reader{}).ReadByte(); b != 0 || err != io.EOF {
t.Errorf("ReadByte: got %d, %v; want 0, io.EOF", b, err)
}
if ch, size, err := (&strings.Reader{}).ReadRune(); ch != 0 || size != 0 || err != io.EOF {
t.Errorf("ReadRune: got %d, %d, %v; want 0, 0, io.EOF", ch, size, err)
}
if offset, err := (&strings.Reader{}).Seek(11, io.SeekStart); offset != 11 || err != nil {
t.Errorf("Seek: got %d, %v; want 11, nil", offset, err)
}
if s := (&strings.Reader{}).Size(); s != 0 {
t.Errorf("Size: got %d, want 0", s)
}
if (&strings.Reader{}).UnreadByte() == nil {
t.Errorf("UnreadByte: got nil, want error")
}
if (&strings.Reader{}).UnreadRune() == nil {
t.Errorf("UnreadRune: got nil, want error")
}
if n, err := (&strings.Reader{}).WriteTo(ioutil.Discard); n != 0 || err != nil {
t.Errorf("WriteTo: got %d, %v; want 0, nil", n, err)
}
}

View File

@ -34,6 +34,8 @@ func SubMem(arr []int, b, c, d int) int {
arr[d] -= 15
// 386:`DECL\s\([A-Z]+\)\([A-Z]+\*4\)`
arr[b]--
// amd64:`DECQ\s64\([A-Z]+\)`
arr[8]--
// 386:"SUBL\t4"
// amd64:"SUBQ\t8"
return arr[0] - arr[1]