Source file src/runtime/string.go

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package runtime
     6  
     7  import (
     8  	"internal/abi"
     9  	"internal/bytealg"
    10  	"internal/goarch"
    11  	"internal/goos"
    12  	"internal/runtime/math"
    13  	"internal/runtime/sys"
    14  	"internal/strconv"
    15  	"unsafe"
    16  )
    17  
    18  // These constants are known to the compiler (see cmd/compile/internal/walk).
    19  // tmpStringBufSize bounds the stack buffer for string results (concatenation
    20  // and []byte/[]rune->string). tmpRuneBufSize bounds the string->[]rune buffer;
    21  // it is kept smaller because rune buffers cost 4 bytes per element while
    22  // exceeding 32 runes is rare, so a larger size would grow frames for no gain.
    23  const (
    24  	tmpStringBufSize = 64
    25  	tmpRuneBufSize   = 32
    26  )
    27  
    28  type tmpBuf [tmpStringBufSize]byte
    29  
    30  // concatstrings implements a Go string concatenation x+y+z+...
    31  // The operands are passed in the slice a.
    32  // If buf != nil, the compiler has determined that the result does not
    33  // escape the calling function, so the string data can be stored in buf
    34  // if small enough.
    35  func concatstrings(buf *tmpBuf, a []string) string {
    36  	idx := 0
    37  	l := 0
    38  	count := 0
    39  	for i, x := range a {
    40  		n := len(x)
    41  		if n == 0 {
    42  			continue
    43  		}
    44  		if l+n < l {
    45  			throw("string concatenation too long")
    46  		}
    47  		l += n
    48  		count++
    49  		idx = i
    50  	}
    51  	if count == 0 {
    52  		return ""
    53  	}
    54  
    55  	// If there is just one string and either it is not on the stack
    56  	// or our result does not escape the calling frame (buf != nil),
    57  	// then we can return that string directly.
    58  	if count == 1 && (buf != nil || !stringDataOnStack(a[idx])) {
    59  		return a[idx]
    60  	}
    61  	s, b := rawstringtmp(buf, l)
    62  	for _, x := range a {
    63  		n := copy(b, x)
    64  		b = b[n:]
    65  	}
    66  	return s
    67  }
    68  
    69  // concatstring2 helps make the callsite smaller (compared to concatstrings),
    70  // and we think this is currently more valuable than omitting one call in the
    71  // chain, the same goes for concatstring{3,4,5}.
    72  func concatstring2(buf *tmpBuf, a0, a1 string) string {
    73  	return concatstrings(buf, []string{a0, a1})
    74  }
    75  
    76  func concatstring3(buf *tmpBuf, a0, a1, a2 string) string {
    77  	return concatstrings(buf, []string{a0, a1, a2})
    78  }
    79  
    80  func concatstring4(buf *tmpBuf, a0, a1, a2, a3 string) string {
    81  	return concatstrings(buf, []string{a0, a1, a2, a3})
    82  }
    83  
    84  func concatstring5(buf *tmpBuf, a0, a1, a2, a3, a4 string) string {
    85  	return concatstrings(buf, []string{a0, a1, a2, a3, a4})
    86  }
    87  
    88  // concatbytes implements a Go string concatenation x+y+z+... returning a slice
    89  // of bytes.
    90  // The operands are passed in the slice a.
    91  func concatbytes(buf *tmpBuf, a []string) []byte {
    92  	l := 0
    93  	for _, x := range a {
    94  		n := len(x)
    95  		if l+n < l {
    96  			throw("string concatenation too long")
    97  		}
    98  		l += n
    99  	}
   100  	if l == 0 {
   101  		// This is to match the return type of the non-optimized concatenation.
   102  		return []byte{}
   103  	}
   104  
   105  	var b []byte
   106  	if buf != nil && l <= len(buf) {
   107  		*buf = tmpBuf{}
   108  		b = buf[:l]
   109  	} else {
   110  		b = rawbyteslice(l)
   111  	}
   112  	offset := 0
   113  	for _, x := range a {
   114  		copy(b[offset:], x)
   115  		offset += len(x)
   116  	}
   117  
   118  	return b
   119  }
   120  
   121  // concatbyte2 helps make the callsite smaller (compared to concatbytes),
   122  // and we think this is currently more valuable than omitting one call in
   123  // the chain, the same goes for concatbyte{3,4,5}.
   124  func concatbyte2(buf *tmpBuf, a0, a1 string) []byte {
   125  	return concatbytes(buf, []string{a0, a1})
   126  }
   127  
   128  func concatbyte3(buf *tmpBuf, a0, a1, a2 string) []byte {
   129  	return concatbytes(buf, []string{a0, a1, a2})
   130  }
   131  
   132  func concatbyte4(buf *tmpBuf, a0, a1, a2, a3 string) []byte {
   133  	return concatbytes(buf, []string{a0, a1, a2, a3})
   134  }
   135  
   136  func concatbyte5(buf *tmpBuf, a0, a1, a2, a3, a4 string) []byte {
   137  	return concatbytes(buf, []string{a0, a1, a2, a3, a4})
   138  }
   139  
   140  // slicebytetostring converts a byte slice to a string.
   141  // It is inserted by the compiler into generated code.
   142  // ptr is a pointer to the first element of the slice;
   143  // n is the length of the slice.
   144  // Buf is a fixed-size buffer for the result,
   145  // it is not nil if the result does not escape.
   146  func slicebytetostring(buf *tmpBuf, ptr *byte, n int) string {
   147  	if n == 0 {
   148  		// Turns out to be a relatively common case.
   149  		// Consider that you want to parse out data between parens in "foo()bar",
   150  		// you find the indices and convert the subslice to string.
   151  		return ""
   152  	}
   153  	if raceenabled {
   154  		racereadrangepc(unsafe.Pointer(ptr),
   155  			uintptr(n),
   156  			sys.GetCallerPC(),
   157  			abi.FuncPCABIInternal(slicebytetostring))
   158  	}
   159  	if msanenabled {
   160  		msanread(unsafe.Pointer(ptr), uintptr(n))
   161  	}
   162  	if asanenabled {
   163  		asanread(unsafe.Pointer(ptr), uintptr(n))
   164  	}
   165  	if n == 1 {
   166  		p := unsafe.Pointer(&staticuint64s[*ptr])
   167  		if goarch.BigEndian {
   168  			p = add(p, 7)
   169  		}
   170  		return unsafe.String((*byte)(p), 1)
   171  	}
   172  
   173  	var p unsafe.Pointer
   174  	if buf != nil && n <= len(buf) {
   175  		p = unsafe.Pointer(buf)
   176  	} else {
   177  		p = mallocgc(uintptr(n), nil, false)
   178  	}
   179  	memmove(p, unsafe.Pointer(ptr), uintptr(n))
   180  	return unsafe.String((*byte)(p), n)
   181  }
   182  
   183  // stringDataOnStack reports whether the string's data is
   184  // stored on the current goroutine's stack.
   185  func stringDataOnStack(s string) bool {
   186  	ptr := uintptr(unsafe.Pointer(unsafe.StringData(s)))
   187  	stk := getg().stack
   188  	return stk.lo <= ptr && ptr < stk.hi
   189  }
   190  
   191  func rawstringtmp(buf *tmpBuf, l int) (s string, b []byte) {
   192  	if buf != nil && l <= len(buf) {
   193  		b = buf[:l]
   194  		s = slicebytetostringtmp(&b[0], len(b))
   195  	} else {
   196  		s, b = rawstring(l)
   197  	}
   198  	return
   199  }
   200  
   201  // slicebytetostringtmp returns a "string" referring to the actual []byte bytes.
   202  //
   203  // Callers need to ensure that the returned string will not be used after
   204  // the calling goroutine modifies the original slice or synchronizes with
   205  // another goroutine.
   206  //
   207  // The function is only called when instrumenting
   208  // and otherwise intrinsified by the compiler.
   209  //
   210  // Some internal compiler optimizations use this function.
   211  //   - Used for m[T1{... Tn{..., string(k), ...} ...}] and m[string(k)]
   212  //     where k is []byte, T1 to Tn is a nesting of struct and array literals.
   213  //   - Used for "<"+string(b)+">" concatenation where b is []byte.
   214  //   - Used for string(b)=="foo" comparison where b is []byte.
   215  func slicebytetostringtmp(ptr *byte, n int) string {
   216  	if raceenabled && n > 0 {
   217  		racereadrangepc(unsafe.Pointer(ptr),
   218  			uintptr(n),
   219  			sys.GetCallerPC(),
   220  			abi.FuncPCABIInternal(slicebytetostringtmp))
   221  	}
   222  	if msanenabled && n > 0 {
   223  		msanread(unsafe.Pointer(ptr), uintptr(n))
   224  	}
   225  	if asanenabled && n > 0 {
   226  		asanread(unsafe.Pointer(ptr), uintptr(n))
   227  	}
   228  	return unsafe.String(ptr, n)
   229  }
   230  
   231  func stringtoslicebyte(buf *tmpBuf, s string) []byte {
   232  	var b []byte
   233  	if buf != nil && len(s) <= len(buf) {
   234  		*buf = tmpBuf{}
   235  		b = buf[:len(s)]
   236  	} else {
   237  		b = rawbyteslice(len(s))
   238  	}
   239  	copy(b, s)
   240  	return b
   241  }
   242  
   243  func stringtoslicerune(buf *[tmpRuneBufSize]rune, s string) []rune {
   244  	// two passes.
   245  	// unlike slicerunetostring, no race because strings are immutable.
   246  	n := 0
   247  	for range s {
   248  		n++
   249  	}
   250  
   251  	var a []rune
   252  	if buf != nil && n <= len(buf) {
   253  		*buf = [tmpRuneBufSize]rune{}
   254  		a = buf[:n]
   255  	} else {
   256  		a = rawruneslice(n)
   257  	}
   258  
   259  	n = 0
   260  	for _, r := range s {
   261  		a[n] = r
   262  		n++
   263  	}
   264  	return a
   265  }
   266  
   267  func slicerunetostring(buf *tmpBuf, a []rune) string {
   268  	if raceenabled && len(a) > 0 {
   269  		racereadrangepc(unsafe.Pointer(&a[0]),
   270  			uintptr(len(a))*unsafe.Sizeof(a[0]),
   271  			sys.GetCallerPC(),
   272  			abi.FuncPCABIInternal(slicerunetostring))
   273  	}
   274  	if msanenabled && len(a) > 0 {
   275  		msanread(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0]))
   276  	}
   277  	if asanenabled && len(a) > 0 {
   278  		asanread(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0]))
   279  	}
   280  	var dum [4]byte
   281  	size1 := 0
   282  	for _, r := range a {
   283  		size1 += encoderune(dum[:], r)
   284  	}
   285  	s, b := rawstringtmp(buf, size1+3)
   286  	size2 := 0
   287  	for _, r := range a {
   288  		// check for race
   289  		if size2 >= size1 {
   290  			break
   291  		}
   292  		size2 += encoderune(b[size2:], r)
   293  	}
   294  	return s[:size2]
   295  }
   296  
   297  type stringStruct struct {
   298  	str unsafe.Pointer
   299  	len int
   300  }
   301  
   302  // Variant with *byte pointer type for DWARF debugging.
   303  type stringStructDWARF struct {
   304  	str *byte
   305  	len int
   306  }
   307  
   308  func stringStructOf(sp *string) *stringStruct {
   309  	return (*stringStruct)(unsafe.Pointer(sp))
   310  }
   311  
   312  func intstring(buf *[4]byte, v int64) (s string) {
   313  	var b []byte
   314  	if buf != nil {
   315  		b = buf[:]
   316  		s = slicebytetostringtmp(&b[0], len(b))
   317  	} else {
   318  		s, b = rawstring(4)
   319  	}
   320  	if int64(rune(v)) != v {
   321  		v = runeError
   322  	}
   323  	n := encoderune(b, rune(v))
   324  	return s[:n]
   325  }
   326  
   327  // rawstring allocates storage for a new string. The returned
   328  // string and byte slice both refer to the same storage.
   329  // The storage is not zeroed. Callers should use
   330  // b to set the string contents and then drop b.
   331  func rawstring(size int) (s string, b []byte) {
   332  	p := mallocgc(uintptr(size), nil, false)
   333  	return unsafe.String((*byte)(p), size), unsafe.Slice((*byte)(p), size)
   334  }
   335  
   336  // rawbyteslice allocates a new byte slice. The byte slice is not zeroed.
   337  func rawbyteslice(size int) (b []byte) {
   338  	cap := roundupsize(uintptr(size), true)
   339  	p := mallocgc(cap, nil, false)
   340  	if cap != uintptr(size) {
   341  		memclrNoHeapPointers(add(p, uintptr(size)), cap-uintptr(size))
   342  	}
   343  
   344  	*(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(cap)}
   345  	return
   346  }
   347  
   348  // rawruneslice allocates a new rune slice. The rune slice is not zeroed.
   349  func rawruneslice(size int) (b []rune) {
   350  	if uintptr(size) > maxAlloc/4 {
   351  		throw("out of memory")
   352  	}
   353  	mem := roundupsize(uintptr(size)*4, true)
   354  	p := mallocgc(mem, nil, false)
   355  	if mem != uintptr(size)*4 {
   356  		memclrNoHeapPointers(add(p, uintptr(size)*4), mem-uintptr(size)*4)
   357  	}
   358  
   359  	*(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(mem / 4)}
   360  	return
   361  }
   362  
   363  // used by cmd/cgo
   364  func gobytes(p *byte, n int) (b []byte) {
   365  	if n == 0 {
   366  		return make([]byte, 0)
   367  	}
   368  
   369  	if n < 0 || uintptr(n) > maxAlloc {
   370  		panic(errorString("gobytes: length out of range"))
   371  	}
   372  
   373  	bp := mallocgc(uintptr(n), nil, false)
   374  	memmove(bp, unsafe.Pointer(p), uintptr(n))
   375  
   376  	*(*slice)(unsafe.Pointer(&b)) = slice{bp, n, n}
   377  	return
   378  }
   379  
   380  // This is exported via linkname to assembly in syscall (for Plan9) and cgo.
   381  //
   382  //go:linkname gostring
   383  func gostring(p *byte) string {
   384  	l := findnull(p)
   385  	if l == 0 {
   386  		return ""
   387  	}
   388  	s, b := rawstring(l)
   389  	memmove(unsafe.Pointer(&b[0]), unsafe.Pointer(p), uintptr(l))
   390  	return s
   391  }
   392  
   393  // internal_syscall_gostring is a version of gostring for internal/syscall/unix.
   394  //
   395  //go:linkname internal_syscall_gostring internal/syscall/unix.gostring
   396  func internal_syscall_gostring(p *byte) string {
   397  	return gostring(p)
   398  }
   399  
   400  func gostringn(p *byte, l int) string {
   401  	if l == 0 {
   402  		return ""
   403  	}
   404  	s, b := rawstring(l)
   405  	memmove(unsafe.Pointer(&b[0]), unsafe.Pointer(p), uintptr(l))
   406  	return s
   407  }
   408  
   409  // parseByteCount parses a string that represents a count of bytes.
   410  //
   411  // s must match the following regular expression:
   412  //
   413  //	^[0-9]+(([KMGT]i)?B)?$
   414  //
   415  // In other words, an integer byte count with an optional unit
   416  // suffix. Acceptable suffixes include one of
   417  // - KiB, MiB, GiB, TiB which represent binary IEC/ISO 80000 units, or
   418  // - B, which just represents bytes.
   419  //
   420  // Returns an int64 because that's what its callers want and receive,
   421  // but the result is always non-negative.
   422  func parseByteCount(s string) (int64, bool) {
   423  	// The empty string is not valid.
   424  	if s == "" {
   425  		return 0, false
   426  	}
   427  	// Handle the easy non-suffix case.
   428  	last := s[len(s)-1]
   429  	if last >= '0' && last <= '9' {
   430  		n, err := strconv.ParseInt(s, 10, 64)
   431  		if err != nil || n < 0 {
   432  			return 0, false
   433  		}
   434  		return n, true
   435  	}
   436  	// Failing a trailing digit, this must always end in 'B'.
   437  	// Also at this point there must be at least one digit before
   438  	// that B.
   439  	if last != 'B' || len(s) < 2 {
   440  		return 0, false
   441  	}
   442  	// The one before that must always be a digit or 'i'.
   443  	if c := s[len(s)-2]; c >= '0' && c <= '9' {
   444  		// Trivial 'B' suffix.
   445  		n, err := strconv.ParseInt(s[:len(s)-1], 10, 64)
   446  		if err != nil || n < 0 {
   447  			return 0, false
   448  		}
   449  		return n, true
   450  	} else if c != 'i' {
   451  		return 0, false
   452  	}
   453  	// Finally, we need at least 4 characters now, for the unit
   454  	// prefix and at least one digit.
   455  	if len(s) < 4 {
   456  		return 0, false
   457  	}
   458  	power := 0
   459  	switch s[len(s)-3] {
   460  	case 'K':
   461  		power = 1
   462  	case 'M':
   463  		power = 2
   464  	case 'G':
   465  		power = 3
   466  	case 'T':
   467  		power = 4
   468  	default:
   469  		// Invalid suffix.
   470  		return 0, false
   471  	}
   472  	m := uint64(1)
   473  	for i := 0; i < power; i++ {
   474  		m *= 1024
   475  	}
   476  	n, err := strconv.ParseInt(s[:len(s)-3], 10, 64)
   477  	if err != nil || n < 0 {
   478  		return 0, false
   479  	}
   480  	un := uint64(n)
   481  	if un > math.MaxUint64/m {
   482  		// Overflow.
   483  		return 0, false
   484  	}
   485  	un *= m
   486  	if un > uint64(math.MaxInt64) {
   487  		// Overflow.
   488  		return 0, false
   489  	}
   490  	return int64(un), true
   491  }
   492  
   493  //go:nosplit
   494  func findnull(s *byte) int {
   495  	if s == nil {
   496  		return 0
   497  	}
   498  
   499  	// Avoid IndexByteString on Plan 9 because it uses SSE instructions
   500  	// on x86 machines, and those are classified as floating point instructions,
   501  	// which are illegal in a note handler.
   502  	if GOOS == "plan9" {
   503  		p := (*[maxAlloc/2 - 1]byte)(unsafe.Pointer(s))
   504  		l := 0
   505  		for p[l] != 0 {
   506  			l++
   507  		}
   508  		return l
   509  	}
   510  
   511  	// pageSize is the unit we scan at a time looking for NULL.
   512  	// It must be the minimum page size for any architecture Go
   513  	// runs on. It's okay (just a minor performance loss) if the
   514  	// actual system page size is larger than this value.
   515  	// For Android, we set the page size to the MTE size, as MTE
   516  	// might be enforced. See issue 59090.
   517  	const pageSize = 4096*(1-goos.IsAndroid) + 16*goos.IsAndroid
   518  
   519  	offset := 0
   520  	ptr := unsafe.Pointer(s)
   521  	// IndexByteString uses wide reads, so we need to be careful
   522  	// with page boundaries. Call IndexByteString on
   523  	// [ptr, endOfPage) interval.
   524  	safeLen := int(pageSize - uintptr(ptr)%pageSize)
   525  
   526  	for {
   527  		t := *(*string)(unsafe.Pointer(&stringStruct{ptr, safeLen}))
   528  		// Check one page at a time.
   529  		if i := bytealg.IndexByteString(t, 0); i != -1 {
   530  			return offset + i
   531  		}
   532  		// Move to next page
   533  		ptr = unsafe.Pointer(uintptr(ptr) + uintptr(safeLen))
   534  		offset += safeLen
   535  		safeLen = pageSize
   536  	}
   537  }
   538  
   539  func findnullw(s *uint16) int {
   540  	if s == nil {
   541  		return 0
   542  	}
   543  	p := (*[maxAlloc/2/2 - 1]uint16)(unsafe.Pointer(s))
   544  	l := 0
   545  	for p[l] != 0 {
   546  		l++
   547  	}
   548  	return l
   549  }
   550  
   551  //go:nosplit
   552  func gostringnocopy(str *byte) string {
   553  	ss := stringStruct{str: unsafe.Pointer(str), len: findnull(str)}
   554  	s := *(*string)(unsafe.Pointer(&ss))
   555  	return s
   556  }
   557  
   558  func gostringw(strw *uint16) string {
   559  	var buf [8]byte
   560  	str := (*[maxAlloc/2/2 - 1]uint16)(unsafe.Pointer(strw))
   561  	n1 := 0
   562  	for i := 0; str[i] != 0; i++ {
   563  		n1 += encoderune(buf[:], rune(str[i]))
   564  	}
   565  	s, b := rawstring(n1 + 4)
   566  	n2 := 0
   567  	for i := 0; str[i] != 0; i++ {
   568  		// check for race
   569  		if n2 >= n1 {
   570  			break
   571  		}
   572  		n2 += encoderune(b[n2:], rune(str[i]))
   573  	}
   574  	b[n2] = 0 // for luck
   575  	return s[:n2]
   576  }
   577  

View as plain text