diff options
author | Michael Stapelberg <stapelberg@debian.org> | 2014-08-13 09:15:02 +0200 |
---|---|---|
committer | Michael Stapelberg <stapelberg@debian.org> | 2014-08-13 09:15:02 +0200 |
commit | 64f344c0c94601934187163f7b353d009dc1b63f (patch) | |
tree | 8eb83dcc45c151c8e1461ca6d67ea7da4137ed00 /src | |
parent | 8a39ee361feb9bf46d728ff1ba4f07ca1d9610b1 (diff) | |
download | golang-64f344c0c94601934187163f7b353d009dc1b63f.tar.gz |
Imported Upstream version 1.3.1upstream/1.3.1
Diffstat (limited to 'src')
-rw-r--r-- | src/cmd/6g/ggen.c | 2 | ||||
-rw-r--r-- | src/cmd/6g/peep.c | 5 | ||||
-rw-r--r-- | src/cmd/8g/ggen.c | 2 | ||||
-rw-r--r-- | src/cmd/8g/peep.c | 5 | ||||
-rw-r--r-- | src/cmd/cgo/gcc.go | 57 | ||||
-rw-r--r-- | src/cmd/gc/array.c | 14 | ||||
-rw-r--r-- | src/cmd/gc/bv.c | 36 | ||||
-rw-r--r-- | src/cmd/gc/go.h | 2 | ||||
-rw-r--r-- | src/cmd/gc/plive.c | 52 | ||||
-rw-r--r-- | src/pkg/compress/gzip/gzip.go | 3 | ||||
-rw-r--r-- | src/pkg/compress/zlib/writer.go | 3 | ||||
-rw-r--r-- | src/pkg/crypto/rsa/pkcs1v15.go | 43 | ||||
-rw-r--r-- | src/pkg/crypto/rsa/pkcs1v15_test.go | 20 | ||||
-rw-r--r-- | src/pkg/crypto/subtle/constant_time.go | 9 | ||||
-rw-r--r-- | src/pkg/net/dnsconfig_unix.go | 10 | ||||
-rw-r--r-- | src/pkg/net/fd_unix.go | 18 | ||||
-rw-r--r-- | src/pkg/net/fd_windows.go | 9 | ||||
-rw-r--r-- | src/pkg/net/sock_posix.go | 22 | ||||
-rw-r--r-- | src/pkg/net/testdata/resolv.conf | 1 | ||||
-rw-r--r-- | src/pkg/runtime/sys_windows_386.s | 5 | ||||
-rw-r--r-- | src/pkg/runtime/sys_windows_amd64.s | 5 | ||||
-rw-r--r-- | src/pkg/runtime/traceback_arm.c | 9 | ||||
-rw-r--r-- | src/pkg/runtime/traceback_x86.c | 2 |
23 files changed, 240 insertions, 94 deletions
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c index c385798f2..9665d831b 100644 --- a/src/cmd/6g/ggen.c +++ b/src/cmd/6g/ggen.c @@ -943,7 +943,7 @@ cgen_hmul(Node *nl, Node *nr, Node *res) if(t->width == 1) { // byte multiply behaves differently. nodreg(&ax, t, D_AH); - nodreg(&dx, t, D_DL); + nodreg(&dx, t, D_DX); gmove(&ax, &dx); } nodreg(&dx, t, D_DX); diff --git a/src/cmd/6g/peep.c b/src/cmd/6g/peep.c index 0f2720443..24617836f 100644 --- a/src/cmd/6g/peep.c +++ b/src/cmd/6g/peep.c @@ -838,6 +838,11 @@ copyu(Prog *p, Adr *v, Adr *s) static int copyas(Adr *a, Adr *v) { + if(D_AL <= a->type && a->type <= D_R15B) + fatal("use of byte register"); + if(D_AL <= v->type && v->type <= D_R15B) + fatal("use of byte register"); + if(a->type != v->type) return 0; if(regtyp(v)) diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c index 2285a04e6..5e3140480 100644 --- a/src/cmd/8g/ggen.c +++ b/src/cmd/8g/ggen.c @@ -991,7 +991,7 @@ cgen_hmul(Node *nl, Node *nr, Node *res) if(t->width == 1) { // byte multiply behaves differently. nodreg(&ax, t, D_AH); - nodreg(&dx, t, D_DL); + nodreg(&dx, t, D_DX); gmove(&ax, &dx); } nodreg(&dx, t, D_DX); diff --git a/src/cmd/8g/peep.c b/src/cmd/8g/peep.c index a4e516dd3..e2f3a003d 100644 --- a/src/cmd/8g/peep.c +++ b/src/cmd/8g/peep.c @@ -634,6 +634,11 @@ copyu(Prog *p, Adr *v, Adr *s) static int copyas(Adr *a, Adr *v) { + if(D_AL <= a->type && a->type <= D_BL) + fatal("use of byte register"); + if(D_AL <= v->type && v->type <= D_BL) + fatal("use of byte register"); + if(a->type != v->type) return 0; if(regtyp(v)) diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 7a802102d..f55cfbac4 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -552,8 +552,8 @@ func (p *Package) loadDWARF(f *File, names []*Name) { n.Const = fmt.Sprintf("%#x", enumVal[i]) } } + conv.FinishType(pos) } - } // mangleName does name mangling to translate names @@ -926,6 +926,12 @@ type typeConv struct { m map[dwarf.Type]*Type typedef map[string]ast.Expr + // Map from types to incomplete pointers to those types. + ptrs map[dwarf.Type][]*Type + + // Fields to be processed by godefsField after completing pointers. + todoFlds [][]*ast.Field + // Predeclared types. bool ast.Expr byte ast.Expr // denotes padding @@ -950,6 +956,7 @@ func (c *typeConv) Init(ptrSize, intSize int64) { c.ptrSize = ptrSize c.intSize = intSize c.m = make(map[dwarf.Type]*Type) + c.ptrs = make(map[dwarf.Type][]*Type) c.bool = c.Ident("bool") c.byte = c.Ident("byte") c.int8 = c.Ident("int8") @@ -1029,6 +1036,32 @@ func (tr *TypeRepr) Set(repr string, fargs ...interface{}) { tr.FormatArgs = fargs } +// FinishType completes any outstanding type mapping work. +// In particular, it resolves incomplete pointer types and also runs +// godefsFields on any new struct types. +func (c *typeConv) FinishType(pos token.Pos) { + // Completing one pointer type might produce more to complete. + // Keep looping until they're all done. + for len(c.ptrs) > 0 { + for dtype := range c.ptrs { + // Note Type might invalidate c.ptrs[dtype]. + t := c.Type(dtype, pos) + for _, ptr := range c.ptrs[dtype] { + ptr.Go.(*ast.StarExpr).X = t.Go + ptr.C.Set("%s*", t.C) + } + delete(c.ptrs, dtype) + } + } + + // Now that pointer types are completed, we can invoke godefsFields + // to rewrite struct definitions. + for _, fld := range c.todoFlds { + godefsFields(fld) + } + c.todoFlds = nil +} + // Type returns a *Type with the same memory layout as // dtype when used as the type of a variable or a struct field. func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { @@ -1068,13 +1101,12 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { t.Go = c.Opaque(t.Size) break } - gt := &ast.ArrayType{ - Len: c.intExpr(dt.Count), - } - t.Go = gt // publish before recursive call sub := c.Type(dt.Type, pos) t.Align = sub.Align - gt.Elt = sub.Go + t.Go = &ast.ArrayType{ + Len: c.intExpr(dt.Count), + Elt: sub.Go, + } t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count) case *dwarf.BoolType: @@ -1184,11 +1216,10 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { break } - gt := &ast.StarExpr{} - t.Go = gt // publish before recursive call - sub := c.Type(dt.Type, pos) - gt.X = sub.Go - t.C.Set("%s*", sub.C) + // Placeholder initialization; completed in FinishType. + t.Go = &ast.StarExpr{} + t.C.Set("<incomplete>*") + c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t) case *dwarf.QualType: // Ignore qualifier. @@ -1265,8 +1296,8 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { } name := c.Ident("_Ctype_" + dt.Name) goIdent[name.Name] = name - t.Go = name // publish before recursive call sub := c.Type(dt.Type, pos) + t.Go = name t.Size = sub.Size t.Align = sub.Align oldType := typedef[name.Name] @@ -1604,7 +1635,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct csyntax = buf.String() if *godefs || *cdefs { - godefsFields(fld) + c.todoFlds = append(c.todoFlds, fld) } expr = &ast.StructType{Fields: &ast.FieldList{List: fld}} return diff --git a/src/cmd/gc/array.c b/src/cmd/gc/array.c index 5e53c1ff0..611fc9fbd 100644 --- a/src/cmd/gc/array.c +++ b/src/cmd/gc/array.c @@ -108,20 +108,6 @@ arrayadd(Array *array, void *element) arrayset(array, array->length - 1, element); } -int32 -arrayindexof(Array *array, void *element) -{ - void *p; - int32 i; - - for(i = 0; i < array->length; i++) { - p = arrayget(array, i); - if(memcmp(p, &element, array->size) == 0) - return i; - } - return -1; -} - void arraysort(Array *array, int (*cmp)(const void*, const void*)) { diff --git a/src/cmd/gc/bv.c b/src/cmd/gc/bv.c index 2efbbc565..0e8f8d473 100644 --- a/src/cmd/gc/bv.c +++ b/src/cmd/gc/bv.c @@ -9,6 +9,8 @@ enum { WORDSIZE = sizeof(uint32), WORDBITS = 32, + WORDMASK = WORDBITS - 1, + WORDSHIFT = 5, }; static uintptr @@ -94,13 +96,35 @@ bvconcat(Bvec *src1, Bvec *src2) int bvget(Bvec *bv, int32 i) { - uint32 mask, word; - if(i < 0 || i >= bv->n) fatal("bvget: index %d is out of bounds with length %d\n", i, bv->n); - mask = 1U << (i % WORDBITS); - word = bv->b[i / WORDBITS] & mask; - return word ? 1 : 0; + return (bv->b[i>>WORDSHIFT] >> (i&WORDMASK)) & 1; +} + +// bvnext returns the smallest index >= i for which bvget(bv, i) == 1. +// If there is no such index, bvnext returns -1. +int +bvnext(Bvec *bv, int32 i) +{ + uint32 w; + + // Jump i ahead to next word with bits. + if((bv->b[i>>WORDSHIFT]>>(i&WORDMASK)) == 0) { + i &= ~WORDMASK; + i += WORDBITS; + while(i < bv->n && bv->b[i>>WORDSHIFT] == 0) + i += WORDBITS; + } + if(i >= bv->n) + return -1; + + // Find 1 bit. + w = bv->b[i>>WORDSHIFT]>>(i&WORDMASK); + while((w&1) == 0) { + w>>=1; + i++; + } + return i; } int @@ -109,7 +133,7 @@ bvisempty(Bvec *bv) int32 i; for(i = 0; i < bv->n; i += WORDBITS) - if(bv->b[i / WORDBITS] != 0) + if(bv->b[i>>WORDSHIFT] != 0) return 0; return 1; } diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 413e71069..ee879f67f 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -1017,7 +1017,6 @@ int32 arraylength(Array *array); void* arrayget(Array *array, int32 index); void arrayset(Array *array, int32 index, void *element); void arrayadd(Array *array, void *element); -int32 arrayindexof(Array* array, void *element); void arraysort(Array* array, int (*cmp)(const void*, const void*)); /* @@ -1043,6 +1042,7 @@ int bvcmp(Bvec *bv1, Bvec *bv2); void bvcopy(Bvec *dst, Bvec *src); Bvec* bvconcat(Bvec *src1, Bvec *src2); int bvget(Bvec *bv, int32 i); +int32 bvnext(Bvec *bv, int32 i); int bvisempty(Bvec *bv); void bvnot(Bvec *bv); void bvor(Bvec *dst, Bvec *src1, Bvec *src2); diff --git a/src/cmd/gc/plive.c b/src/cmd/gc/plive.c index eb8901733..7a40ab559 100644 --- a/src/cmd/gc/plive.c +++ b/src/cmd/gc/plive.c @@ -283,13 +283,30 @@ getvariables(Node *fn) // For arguments and results, the bitmap covers all variables, // so we must include all the variables, even the ones without // pointers. + // + // The Node.opt field is available for use by optimization passes. + // We use it to hold the index of the node in the variables array, plus 1 + // (so that 0 means the Node is not in the variables array). + // Each pass should clear opt when done, but you never know, + // so clear them all ourselves too. + // The Node.curfn field is supposed to be set to the current function + // already, but for some compiler-introduced names it seems not to be, + // so fix that here. + // Later, when we want to find the index of a node in the variables list, + // we will check that n->curfn == curfn and n->opt > 0. Then n->opt - 1 + // is the index in the variables list. + ll->n->opt = nil; + ll->n->curfn = curfn; switch(ll->n->class) { case PAUTO: - if(haspointers(ll->n->type)) + if(haspointers(ll->n->type)) { + ll->n->opt = (void*)(uintptr)(arraylength(result)+1); arrayadd(result, &ll->n); + } break; case PPARAM: case PPARAMOUT: + ll->n->opt = (void*)(uintptr)(arraylength(result)+1); arrayadd(result, &ll->n); break; } @@ -718,14 +735,16 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit) } if(info.flags & (LeftRead | LeftWrite | LeftAddr)) { from = &prog->from; - if (from->node != nil && from->sym != nil) { + if (from->node != nil && from->sym != nil && from->node->curfn == curfn) { switch(from->node->class & ~PHEAP) { case PAUTO: case PPARAM: case PPARAMOUT: - pos = arrayindexof(vars, from->node); + pos = (int)(uintptr)from->node->opt - 1; // index in vars if(pos == -1) goto Next; + if(pos >= arraylength(vars) || *(Node**)arrayget(vars, pos) != from->node) + fatal("bad bookkeeping in liveness %N %d", from->node, pos); if(from->node->addrtaken) { bvset(avarinit, pos); } else { @@ -741,14 +760,16 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit) Next: if(info.flags & (RightRead | RightWrite | RightAddr)) { to = &prog->to; - if (to->node != nil && to->sym != nil) { + if (to->node != nil && to->sym != nil && to->node->curfn == curfn) { switch(to->node->class & ~PHEAP) { case PAUTO: case PPARAM: case PPARAMOUT: - pos = arrayindexof(vars, to->node); + pos = (int)(uintptr)to->node->opt - 1; // index in vars if(pos == -1) goto Next1; + if(pos >= arraylength(vars) || *(Node**)arrayget(vars, pos) != to->node) + fatal("bad bookkeeping in liveness %N %d", to->node, pos); if(to->node->addrtaken) { if(prog->as != AVARKILL) bvset(avarinit, pos); @@ -1020,6 +1041,9 @@ checkptxt(Node *fn, Prog *firstp) { Prog *p; + if(debuglive == 0) + return; + for(p = firstp; p != P; p = p->link) { if(0) print("analyzing '%P'\n", p); @@ -1172,21 +1196,17 @@ twobitlivepointermap(Liveness *lv, Bvec *liveout, Array *vars, Bvec *args, Bvec vlong xoffset; int32 i; - for(i = 0; i < arraylength(vars); i++) { + for(i = 0; (i = bvnext(liveout, i)) >= 0; i++) { node = *(Node**)arrayget(vars, i); switch(node->class) { case PAUTO: - if(bvget(liveout, i)) { - xoffset = node->xoffset + stkptrsize; - twobitwalktype1(node->type, &xoffset, locals); - } + xoffset = node->xoffset + stkptrsize; + twobitwalktype1(node->type, &xoffset, locals); break; case PPARAM: case PPARAMOUT: - if(bvget(liveout, i)) { - xoffset = node->xoffset; - twobitwalktype1(node->type, &xoffset, args); - } + xoffset = node->xoffset; + twobitwalktype1(node->type, &xoffset, args); break; } } @@ -1937,6 +1957,7 @@ liveness(Node *fn, Prog *firstp, Sym *argssym, Sym *livesym) Array *cfg, *vars; Liveness *lv; int debugdelta; + NodeList *l; // Change name to dump debugging information only for a specific function. debugdelta = 0; @@ -1977,6 +1998,9 @@ liveness(Node *fn, Prog *firstp, Sym *argssym, Sym *livesym) twobitwritesymbol(lv->argslivepointers, argssym); // Free everything. + for(l=fn->dcl; l != nil; l = l->next) + if(l->n != N) + l->n->opt = nil; freeliveness(lv); arrayfree(vars); freecfg(cfg); diff --git a/src/pkg/compress/gzip/gzip.go b/src/pkg/compress/gzip/gzip.go index 3a0bf54e1..5131d128e 100644 --- a/src/pkg/compress/gzip/gzip.go +++ b/src/pkg/compress/gzip/gzip.go @@ -245,7 +245,8 @@ func (z *Writer) Flush() error { return z.err } -// Close closes the Writer. It does not close the underlying io.Writer. +// Close closes the Writer, flushing any unwritten data to the underlying +// io.Writer, but does not close the underlying io.Writer. func (z *Writer) Close() error { if z.err != nil { return z.err diff --git a/src/pkg/compress/zlib/writer.go b/src/pkg/compress/zlib/writer.go index fac7e15a7..3b4313a8b 100644 --- a/src/pkg/compress/zlib/writer.go +++ b/src/pkg/compress/zlib/writer.go @@ -174,7 +174,8 @@ func (z *Writer) Flush() error { return z.err } -// Calling Close does not close the wrapped io.Writer originally passed to NewWriter. +// Close closes the Writer, flushing any unwritten data to the underlying +// io.Writer, but does not close the underlying io.Writer. func (z *Writer) Close() error { if !z.wroteHeader { z.err = z.writeHeader() diff --git a/src/pkg/crypto/rsa/pkcs1v15.go b/src/pkg/crypto/rsa/pkcs1v15.go index d9957aec1..59e8bb5b7 100644 --- a/src/pkg/crypto/rsa/pkcs1v15.go +++ b/src/pkg/crypto/rsa/pkcs1v15.go @@ -53,11 +53,14 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out [ if err := checkPub(&priv.PublicKey); err != nil { return nil, err } - valid, out, err := decryptPKCS1v15(rand, priv, ciphertext) - if err == nil && valid == 0 { - err = ErrDecryption + valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext) + if err != nil { + return } - + if valid == 0 { + return nil, ErrDecryption + } + out = out[index:] return } @@ -80,21 +83,32 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by } k := (priv.N.BitLen() + 7) / 8 if k-(len(key)+3+8) < 0 { - err = ErrDecryption - return + return ErrDecryption } - valid, msg, err := decryptPKCS1v15(rand, priv, ciphertext) + valid, em, index, err := decryptPKCS1v15(rand, priv, ciphertext) if err != nil { return } - valid &= subtle.ConstantTimeEq(int32(len(msg)), int32(len(key))) - subtle.ConstantTimeCopy(valid, key, msg) + if len(em) != k { + // This should be impossible because decryptPKCS1v15 always + // returns the full slice. + return ErrDecryption + } + + valid &= subtle.ConstantTimeEq(int32(len(em)-index), int32(len(key))) + subtle.ConstantTimeCopy(valid, key, em[len(em)-len(key):]) return } -func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, msg []byte, err error) { +// decryptPKCS1v15 decrypts ciphertext using priv and blinds the operation if +// rand is not nil. It returns one or zero in valid that indicates whether the +// plaintext was correctly structured. In either case, the plaintext is +// returned in em so that it may be read independently of whether it was valid +// in order to maintain constant memory access patterns. If the plaintext was +// valid then index contains the index of the original message in em. +func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) { k := (priv.N.BitLen() + 7) / 8 if k < 11 { err = ErrDecryption @@ -107,7 +121,7 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid return } - em := leftPad(m.Bytes(), k) + em = leftPad(m.Bytes(), k) firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0) secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2) @@ -115,8 +129,7 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid // octets, followed by a 0, followed by the message. // lookingForIndex: 1 iff we are still looking for the zero. // index: the offset of the first zero byte. - var lookingForIndex, index int - lookingForIndex = 1 + lookingForIndex := 1 for i := 2; i < len(em); i++ { equals0 := subtle.ConstantTimeByteEq(em[i], 0) @@ -129,8 +142,8 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid validPS := subtle.ConstantTimeLessOrEq(2+8, index) valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS - msg = em[index+1:] - return + index = subtle.ConstantTimeSelect(valid, index+1, 0) + return valid, em, index, nil } // nonZeroRandomBytes fills the given slice with non-zero random octets. diff --git a/src/pkg/crypto/rsa/pkcs1v15_test.go b/src/pkg/crypto/rsa/pkcs1v15_test.go index 37c14d1d9..2dc5dbc2c 100644 --- a/src/pkg/crypto/rsa/pkcs1v15_test.go +++ b/src/pkg/crypto/rsa/pkcs1v15_test.go @@ -227,6 +227,26 @@ func TestUnpaddedSignature(t *testing.T) { } } +func TestShortSessionKey(t *testing.T) { + // This tests that attempting to decrypt a session key where the + // ciphertext is too small doesn't run outside the array bounds. + ciphertext, err := EncryptPKCS1v15(rand.Reader, &rsaPrivateKey.PublicKey, []byte{1}) + if err != nil { + t.Fatalf("Failed to encrypt short message: %s", err) + } + + var key [32]byte + if err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, ciphertext, key[:]); err != nil { + t.Fatalf("Failed to decrypt short message: %s", err) + } + + for _, v := range key { + if v != 0 { + t.Fatal("key was modified when ciphertext was invalid") + } + } +} + // In order to generate new test vectors you'll need the PEM form of this key: // -----BEGIN RSA PRIVATE KEY----- // MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 diff --git a/src/pkg/crypto/subtle/constant_time.go b/src/pkg/crypto/subtle/constant_time.go index de1a4e8c5..9c4b14a65 100644 --- a/src/pkg/crypto/subtle/constant_time.go +++ b/src/pkg/crypto/subtle/constant_time.go @@ -49,9 +49,14 @@ func ConstantTimeEq(x, y int32) int { return int(z & 1) } -// ConstantTimeCopy copies the contents of y into x iff v == 1. If v == 0, x is left unchanged. -// Its behavior is undefined if v takes any other value. +// ConstantTimeCopy copies the contents of y into x (a slice of equal length) +// if v == 1. If v == 0, x is left unchanged. Its behavior is undefined if v +// takes any other value. func ConstantTimeCopy(v int, x, y []byte) { + if len(x) != len(y) { + panic("subtle: slices have different lengths") + } + xmask := byte(v - 1) ymask := byte(^(v - 1)) for i := 0; i < len(x); i++ { diff --git a/src/pkg/net/dnsconfig_unix.go b/src/pkg/net/dnsconfig_unix.go index af288253e..db45716f1 100644 --- a/src/pkg/net/dnsconfig_unix.go +++ b/src/pkg/net/dnsconfig_unix.go @@ -75,19 +75,19 @@ func dnsReadConfig(filename string) (*dnsConfig, error) { for i := 1; i < len(f); i++ { s := f[i] switch { - case len(s) >= 6 && s[0:6] == "ndots:": + case hasPrefix(s, "ndots:"): n, _, _ := dtoi(s, 6) if n < 1 { n = 1 } conf.ndots = n - case len(s) >= 8 && s[0:8] == "timeout:": + case hasPrefix(s, "timeout:"): n, _, _ := dtoi(s, 8) if n < 1 { n = 1 } conf.timeout = n - case len(s) >= 8 && s[0:9] == "attempts:": + case hasPrefix(s, "attempts:"): n, _, _ := dtoi(s, 9) if n < 1 { n = 1 @@ -103,3 +103,7 @@ func dnsReadConfig(filename string) (*dnsConfig, error) { return conf, nil } + +func hasPrefix(s, prefix string) bool { + return len(s) >= len(prefix) && s[:len(prefix)] == prefix +} diff --git a/src/pkg/net/fd_unix.go b/src/pkg/net/fd_unix.go index b82ecd11c..e22861abb 100644 --- a/src/pkg/net/fd_unix.go +++ b/src/pkg/net/fd_unix.go @@ -68,16 +68,19 @@ func (fd *netFD) name() string { return fd.net + ":" + ls + "->" + rs } -func (fd *netFD) connect(la, ra syscall.Sockaddr) error { +func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error { // Do not need to call fd.writeLock here, // because fd is not yet accessible to user, // so no concurrent operations are possible. - if err := fd.pd.PrepareWrite(); err != nil { - return err - } switch err := syscall.Connect(fd.sysfd, ra); err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: case nil, syscall.EISCONN: + if !deadline.IsZero() && deadline.Before(time.Now()) { + return errTimeout + } + if err := fd.init(); err != nil { + return err + } return nil case syscall.EINVAL: // On Solaris we can see EINVAL if the socket has @@ -92,6 +95,13 @@ func (fd *netFD) connect(la, ra syscall.Sockaddr) error { default: return err } + if err := fd.init(); err != nil { + return err + } + if !deadline.IsZero() { + fd.setWriteDeadline(deadline) + defer fd.setWriteDeadline(noDeadline) + } for { // Performing multiple connect system calls on a // non-blocking socket under Unix variants does not diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go index a1f6bc5f8..d1129dccc 100644 --- a/src/pkg/net/fd_windows.go +++ b/src/pkg/net/fd_windows.go @@ -313,10 +313,17 @@ func (fd *netFD) setAddr(laddr, raddr Addr) { runtime.SetFinalizer(fd, (*netFD).Close) } -func (fd *netFD) connect(la, ra syscall.Sockaddr) error { +func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error { // Do not need to call fd.writeLock here, // because fd is not yet accessible to user, // so no concurrent operations are possible. + if err := fd.init(); err != nil { + return err + } + if !deadline.IsZero() { + fd.setWriteDeadline(deadline) + defer fd.setWriteDeadline(noDeadline) + } if !canUseConnectEx(fd.net) { return syscall.Connect(fd.sysfd, ra) } diff --git a/src/pkg/net/sock_posix.go b/src/pkg/net/sock_posix.go index a6ef874c9..c80c7d6a2 100644 --- a/src/pkg/net/sock_posix.go +++ b/src/pkg/net/sock_posix.go @@ -107,24 +107,18 @@ func (fd *netFD) dial(laddr, raddr sockaddr, deadline time.Time, toAddr func(sys } } } - if err := fd.init(); err != nil { - return err - } var rsa syscall.Sockaddr if raddr != nil { if rsa, err = raddr.sockaddr(fd.family); err != nil { return err - } else if rsa != nil { - if !deadline.IsZero() { - fd.setWriteDeadline(deadline) - } - if err := fd.connect(lsa, rsa); err != nil { - return err - } - fd.isConnected = true - if !deadline.IsZero() { - fd.setWriteDeadline(noDeadline) - } + } + if err := fd.connect(lsa, rsa, deadline); err != nil { + return err + } + fd.isConnected = true + } else { + if err := fd.init(); err != nil { + return err } } lsa, _ = syscall.Getsockname(fd.sysfd) diff --git a/src/pkg/net/testdata/resolv.conf b/src/pkg/net/testdata/resolv.conf index b5972e09c..3841bbf90 100644 --- a/src/pkg/net/testdata/resolv.conf +++ b/src/pkg/net/testdata/resolv.conf @@ -3,3 +3,4 @@ domain Home nameserver 192.168.1.1 options ndots:5 timeout:10 attempts:3 rotate +options attempts 3 diff --git a/src/pkg/runtime/sys_windows_386.s b/src/pkg/runtime/sys_windows_386.s index e0c0631cf..576831d2c 100644 --- a/src/pkg/runtime/sys_windows_386.s +++ b/src/pkg/runtime/sys_windows_386.s @@ -88,6 +88,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 // fetch g get_tls(DX) + CMPL DX, $0 + JNE 3(PC) + MOVL $0, AX // continue + JMP done MOVL m(DX), AX CMPL AX, $0 JNE 2(PC) @@ -100,6 +104,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 CALL runtime·sighandler(SB) // AX is set to report result back to Windows +done: // restore callee-saved registers MOVL 24(SP), DI MOVL 20(SP), SI diff --git a/src/pkg/runtime/sys_windows_amd64.s b/src/pkg/runtime/sys_windows_amd64.s index 94845903e..d161be6a5 100644 --- a/src/pkg/runtime/sys_windows_amd64.s +++ b/src/pkg/runtime/sys_windows_amd64.s @@ -120,6 +120,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 // fetch g get_tls(DX) + CMPQ DX, $0 + JNE 3(PC) + MOVQ $0, AX // continue + JMP done MOVQ m(DX), AX CMPQ AX, $0 JNE 2(PC) @@ -132,6 +136,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 CALL runtime·sighandler(SB) // AX is set to report result back to Windows +done: // restore registers as required for windows callback MOVQ 24(SP), R15 MOVQ 32(SP), R14 diff --git a/src/pkg/runtime/traceback_arm.c b/src/pkg/runtime/traceback_arm.c index d15244c2a..30f43d54c 100644 --- a/src/pkg/runtime/traceback_arm.c +++ b/src/pkg/runtime/traceback_arm.c @@ -128,9 +128,14 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, frame.lr = *(uintptr*)frame.sp; flr = runtime·findfunc(frame.lr); if(flr == nil) { - runtime·printf("runtime: unexpected return pc for %s called from %p\n", runtime·funcname(f), frame.lr); - if(callback != nil) + // This happens if you get a profiling interrupt at just the wrong time. + // In that context it is okay to stop early. + // But if callback is set, we're doing a garbage collection and must + // get everything, so crash loudly. + if(callback != nil) { + runtime·printf("runtime: unexpected return pc for %s called from %p\n", runtime·funcname(f), frame.lr); runtime·throw("unknown caller pc"); + } } } diff --git a/src/pkg/runtime/traceback_x86.c b/src/pkg/runtime/traceback_x86.c index 851504f52..7359cfcc9 100644 --- a/src/pkg/runtime/traceback_x86.c +++ b/src/pkg/runtime/traceback_x86.c @@ -214,7 +214,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, // the SP is two words lower than normal. sparg = frame.sp; if(wasnewproc) - sparg += 2*sizeof(uintreg); + sparg += 2*sizeof(uintptr); // Determine frame's 'continuation PC', where it can continue. // Normally this is the return address on the stack, but if sigpanic |