diff options
Diffstat (limited to 'libgo/runtime')
-rw-r--r-- | libgo/runtime/chan.c | 20 | ||||
-rw-r--r-- | libgo/runtime/cpuprof.c | 14 | ||||
-rw-r--r-- | libgo/runtime/go-append.c | 3 | ||||
-rw-r--r-- | libgo/runtime/go-int-to-string.c | 9 | ||||
-rw-r--r-- | libgo/runtime/go-make-slice.c | 2 | ||||
-rw-r--r-- | libgo/runtime/go-rune.c | 8 | ||||
-rw-r--r-- | libgo/runtime/go-type-complex.c | 14 | ||||
-rw-r--r-- | libgo/runtime/go-type-float.c | 14 | ||||
-rw-r--r-- | libgo/runtime/malloc.h | 9 | ||||
-rw-r--r-- | libgo/runtime/print.c | 9 | ||||
-rw-r--r-- | libgo/runtime/runtime.c | 6 |
11 files changed, 88 insertions, 20 deletions
diff --git a/libgo/runtime/chan.c b/libgo/runtime/chan.c index c8ee10e8c88..1e389a218de 100644 --- a/libgo/runtime/chan.c +++ b/libgo/runtime/chan.c @@ -3,6 +3,8 @@ // license that can be found in the LICENSE file. #include "runtime.h" +#include "arch.h" +#include "malloc.h" #include "go-type.h" #define NOSELGEN 1 @@ -85,10 +87,10 @@ runtime_makechan_c(ChanType *t, int64 hint) Hchan *c; int32 n; const Type *elem; - + elem = t->__element_type; - if(hint < 0 || (int32)hint != hint || (elem->__size > 0 && (uintptr)hint > ((uintptr)-1) / elem->__size)) + if(hint < 0 || (int32)hint != hint || (elem->__size > 0 && (uintptr)hint > MaxMem / elem->__size)) runtime_panicstring("makechan: size out of range"); n = sizeof(*c); @@ -189,7 +191,7 @@ runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres) sg = dequeue(&c->recvq); if(sg != nil) { runtime_unlock(c); - + gp = sg->g; gp->param = sg; if(sg->elem != nil) @@ -528,7 +530,7 @@ runtime_selectnbrecv(ChanType *t, byte *v, Hchan *c) runtime_chanrecv(t, c, v, &selected, nil); return selected; -} +} // func selectnbrecv2(elem *any, ok *bool, c chan any) bool // @@ -560,7 +562,7 @@ runtime_selectnbrecv2(ChanType *t, byte *v, _Bool *received, Hchan *c) if(received != nil) *received = r; return selected; -} +} // For reflect: // func chansend(c chan, val iword, nb bool) (selected bool) @@ -576,7 +578,7 @@ reflect_chansend(ChanType *t, Hchan *c, uintptr val, _Bool nb) bool selected; bool *sp; byte *vp; - + if(nb) { selected = false; sp = (bool*)&selected; @@ -695,7 +697,7 @@ runtime_selectsend(Select *sel, Hchan *c, void *elem, int index) // nil cases do not compete if(c == nil) return; - + selectsend(sel, c, index, elem); } @@ -704,7 +706,7 @@ selectsend(Select *sel, Hchan *c, int index, void *elem) { int32 i; Scase *cas; - + i = sel->ncase; if(i >= sel->tcase) runtime_throw("selectsend: too many cases"); @@ -975,7 +977,7 @@ loop: case CaseRecv: enqueue(&c->recvq, sg); break; - + case CaseSend: enqueue(&c->sendq, sg); break; diff --git a/libgo/runtime/cpuprof.c b/libgo/runtime/cpuprof.c index 252948d6659..9bf5d11e687 100644 --- a/libgo/runtime/cpuprof.c +++ b/libgo/runtime/cpuprof.c @@ -105,6 +105,7 @@ struct Profile { uint32 wtoggle; bool wholding; // holding & need to release a log half bool flushing; // flushing hash table - profile is over + bool eod_sent; // special end-of-data record sent; => flushing }; static Lock lk; @@ -115,6 +116,8 @@ static void add(Profile*, uintptr*, int32); static bool evict(Profile*, Entry*); static bool flushlog(Profile*); +static uintptr eod[3] = {0, 1, 0}; + // LostProfileData is a no-op function used in profiles // to mark the number of profiling stack traces that were // discarded due to slow data writers. @@ -168,6 +171,7 @@ runtime_SetCPUProfileRate(int32 hz) prof->wholding = false; prof->wtoggle = 0; prof->flushing = false; + prof->eod_sent = false; runtime_noteclear(&prof->wait); runtime_setcpuprofilerate(tick, hz); @@ -414,6 +418,16 @@ breakflush: } // Made it through the table without finding anything to log. + if(!p->eod_sent) { + // We may not have space to append this to the partial log buf, + // so we always return a new slice for the end-of-data marker. + p->eod_sent = true; + ret.array = (byte*)eod; + ret.len = sizeof eod; + ret.cap = ret.len; + return ret; + } + // Finally done. Clean up and return nil. p->flushing = false; if(!runtime_cas(&p->handoff, p->handoff, 0)) diff --git a/libgo/runtime/go-append.c b/libgo/runtime/go-append.c index 3a0c7781126..dac4c902c15 100644 --- a/libgo/runtime/go-append.c +++ b/libgo/runtime/go-append.c @@ -54,6 +54,9 @@ __go_append (struct __go_open_array a, void *bvalues, uintptr_t bcount, while (m < count); } + if ((uintptr) m > MaxMem / element_size) + runtime_panicstring ("growslice: cap out of range"); + n = __go_alloc (m * element_size); __builtin_memcpy (n, a.__values, a.__count * element_size); diff --git a/libgo/runtime/go-int-to-string.c b/libgo/runtime/go-int-to-string.c index e9645bf98fe..17a5fcb04c0 100644 --- a/libgo/runtime/go-int-to-string.c +++ b/libgo/runtime/go-int-to-string.c @@ -17,6 +17,11 @@ __go_int_to_string (int v) unsigned char *retdata; struct __go_string ret; + /* A negative value is not valid UTF-8; turn it into the replacement + character. */ + if (v < 0) + v = 0xfffd; + if (v <= 0x7f) { buf[0] = v; @@ -34,6 +39,10 @@ __go_int_to_string (int v) "replacement character". */ if (v > 0x10ffff) v = 0xfffd; + /* If the value is a surrogate pair, which is invalid in UTF-8, + turn it into the replacement character. */ + if (v >= 0xd800 && v < 0xe000) + v = 0xfffd; if (v <= 0xffff) { diff --git a/libgo/runtime/go-make-slice.c b/libgo/runtime/go-make-slice.c index 42b412c772b..822c9b68f0a 100644 --- a/libgo/runtime/go-make-slice.c +++ b/libgo/runtime/go-make-slice.c @@ -37,7 +37,7 @@ __go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len, if (cap < len || (uintptr_t) icap != cap || (std->__element_type->__size > 0 - && cap > (uintptr_t) -1U / std->__element_type->__size)) + && cap > MaxMem / std->__element_type->__size)) runtime_panicstring ("makeslice: cap out of range"); ret.__count = ilen; diff --git a/libgo/runtime/go-rune.c b/libgo/runtime/go-rune.c index 7e31eb8d622..acdecb02467 100644 --- a/libgo/runtime/go-rune.c +++ b/libgo/runtime/go-rune.c @@ -53,6 +53,14 @@ __go_get_rune (const unsigned char *str, size_t len, int *rune) *rune = (((c & 0xf) << 12) + ((c1 & 0x3f) << 6) + (c2 & 0x3f)); + + if (*rune >= 0xd800 && *rune < 0xe000) + { + /* Invalid surrogate half; return replace character. */ + *rune = 0xfffd; + return 1; + } + return 3; } diff --git a/libgo/runtime/go-type-complex.c b/libgo/runtime/go-type-complex.c index f923c867d99..106024f5c88 100644 --- a/libgo/runtime/go-type-complex.c +++ b/libgo/runtime/go-type-complex.c @@ -32,10 +32,14 @@ __go_type_hash_complex (const void *vkey, uintptr_t key_size) cf = ucf.cf; cfr = __builtin_crealf (cf); cfi = __builtin_cimagf (cf); - if (__builtin_isinff (cfr) || __builtin_isinff (cfi) - || __builtin_isnanf (cfr) || __builtin_isnanf (cfi)) + if (__builtin_isinff (cfr) || __builtin_isinff (cfi)) return 0; + /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it + random so that not all NaNs wind up in the same place. */ + if (__builtin_isnanf (cfr) || __builtin_isnanf (cfi)) + return runtime_fastrand1 (); + /* Avoid negative zero. */ if (cfr == 0 && cfi == 0) return 0; @@ -62,10 +66,12 @@ __go_type_hash_complex (const void *vkey, uintptr_t key_size) cd = ucd.cd; cdr = __builtin_crealf (cd); cdi = __builtin_cimagf (cd); - if (__builtin_isinf (cdr) || __builtin_isinf (cdi) - || __builtin_isnan (cdr) || __builtin_isnan (cdi)) + if (__builtin_isinf (cdr) || __builtin_isinf (cdi)) return 0; + if (__builtin_isnan (cdr) || __builtin_isnan (cdi)) + return runtime_fastrand1 (); + /* Avoid negative zero. */ if (cdr == 0 && cdi == 0) return 0; diff --git a/libgo/runtime/go-type-float.c b/libgo/runtime/go-type-float.c index cc6e247e531..e1c03e42843 100644 --- a/libgo/runtime/go-type-float.c +++ b/libgo/runtime/go-type-float.c @@ -29,8 +29,14 @@ __go_type_hash_float (const void *vkey, uintptr_t key_size) __builtin_memcpy (uf.a, vkey, 4); f = uf.f; - if (__builtin_isinff (f) || __builtin_isnanf (f) || f == 0) + if (__builtin_isinff (f) || f == 0) return 0; + + /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it + random so that not all NaNs wind up in the same place. */ + if (__builtin_isnanf (f)) + return runtime_fastrand1 (); + return (uintptr_t) uf.si; } else if (key_size == 8) @@ -45,8 +51,12 @@ __go_type_hash_float (const void *vkey, uintptr_t key_size) __builtin_memcpy (ud.a, vkey, 8); d = ud.d; - if (__builtin_isinf (d) || __builtin_isnan (d) || d == 0) + if (__builtin_isinf (d) || d == 0) return 0; + + if (__builtin_isnan (d)) + return runtime_fastrand1 (); + return (uintptr_t) ud.di; } else diff --git a/libgo/runtime/malloc.h b/libgo/runtime/malloc.h index 16bb449f128..96cb609367f 100644 --- a/libgo/runtime/malloc.h +++ b/libgo/runtime/malloc.h @@ -128,6 +128,15 @@ enum MaxGcproc = 4, }; +// Maximum memory allocation size, a hint for callers. +// This must be a #define instead of an enum because it +// is so large. +#if __SIZEOF_POINTER__ == 8 +#define MaxMem (16ULL<<30) /* 16 GB */ +#else +#define MaxMem ((uintptr)-1) +#endif + // A generic linked list of blocks. (Typically the block is bigger than sizeof(MLink).) struct MLink { diff --git a/libgo/runtime/print.c b/libgo/runtime/print.c index c24304e2487..fcf57ea4144 100644 --- a/libgo/runtime/print.c +++ b/libgo/runtime/print.c @@ -17,13 +17,16 @@ gwrite(const void *v, int32 n) G* g = runtime_g(); if(g == nil || g->writebuf == nil) { - runtime_write(2, v, n); + // Avoid -D_FORTIFY_SOURCE problems. + int rv __attribute__((unused)); + + rv = runtime_write(2, v, n); return; } - + if(g->writenbuf == 0) return; - + if(n > g->writenbuf) n = g->writenbuf; runtime_memmove(g->writebuf, v, n); diff --git a/libgo/runtime/runtime.c b/libgo/runtime/runtime.c index 72875fd53f7..e0a7925aed1 100644 --- a/libgo/runtime/runtime.c +++ b/libgo/runtime/runtime.c @@ -106,11 +106,15 @@ static byte** argv; extern Slice os_Args asm ("os.Args"); extern Slice syscall_Envs asm ("syscall.Envs"); +void (*runtime_sysargs)(int32, uint8**); + void runtime_args(int32 c, byte **v) { argc = c; argv = v; + if(runtime_sysargs != nil) + runtime_sysargs(c, v); } void @@ -234,7 +238,7 @@ runtime_showframe(const unsigned char *s) if(traceback < 0) traceback = runtime_gotraceback(); - return traceback > 1 || (__builtin_strchr((const char*)s, '.') != nil && __builtin_memcmp(s, "runtime.", 7) != 0); + return traceback > 1 || (s != nil && __builtin_strchr((const char*)s, '.') != nil && __builtin_memcmp(s, "runtime.", 7) != 0); } bool |