github.com/lzhfromustc/gofuzz@v0.0.0-20211116160056-151b3108bbd1/runtime/syscall_windows_test.go (about)

     1  // Copyright 2010 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_test
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"internal/syscall/windows/sysdll"
    11  	"internal/testenv"
    12  	"io"
    13  	"math"
    14  	"os"
    15  	"os/exec"
    16  	"path/filepath"
    17  	"reflect"
    18  	"runtime"
    19  	"strconv"
    20  	"strings"
    21  	"syscall"
    22  	"testing"
    23  	"unsafe"
    24  )
    25  
    26  type DLL struct {
    27  	*syscall.DLL
    28  	t *testing.T
    29  }
    30  
    31  func GetDLL(t *testing.T, name string) *DLL {
    32  	d, e := syscall.LoadDLL(name)
    33  	if e != nil {
    34  		t.Fatal(e)
    35  	}
    36  	return &DLL{DLL: d, t: t}
    37  }
    38  
    39  func (d *DLL) Proc(name string) *syscall.Proc {
    40  	p, e := d.FindProc(name)
    41  	if e != nil {
    42  		d.t.Fatal(e)
    43  	}
    44  	return p
    45  }
    46  
    47  func TestStdCall(t *testing.T) {
    48  	type Rect struct {
    49  		left, top, right, bottom int32
    50  	}
    51  	res := Rect{}
    52  	expected := Rect{1, 1, 40, 60}
    53  	a, _, _ := GetDLL(t, "user32.dll").Proc("UnionRect").Call(
    54  		uintptr(unsafe.Pointer(&res)),
    55  		uintptr(unsafe.Pointer(&Rect{10, 1, 14, 60})),
    56  		uintptr(unsafe.Pointer(&Rect{1, 2, 40, 50})))
    57  	if a != 1 || res.left != expected.left ||
    58  		res.top != expected.top ||
    59  		res.right != expected.right ||
    60  		res.bottom != expected.bottom {
    61  		t.Error("stdcall USER32.UnionRect returns", a, "res=", res)
    62  	}
    63  }
    64  
    65  func Test64BitReturnStdCall(t *testing.T) {
    66  
    67  	const (
    68  		VER_BUILDNUMBER      = 0x0000004
    69  		VER_MAJORVERSION     = 0x0000002
    70  		VER_MINORVERSION     = 0x0000001
    71  		VER_PLATFORMID       = 0x0000008
    72  		VER_PRODUCT_TYPE     = 0x0000080
    73  		VER_SERVICEPACKMAJOR = 0x0000020
    74  		VER_SERVICEPACKMINOR = 0x0000010
    75  		VER_SUITENAME        = 0x0000040
    76  
    77  		VER_EQUAL         = 1
    78  		VER_GREATER       = 2
    79  		VER_GREATER_EQUAL = 3
    80  		VER_LESS          = 4
    81  		VER_LESS_EQUAL    = 5
    82  
    83  		ERROR_OLD_WIN_VERSION syscall.Errno = 1150
    84  	)
    85  
    86  	type OSVersionInfoEx struct {
    87  		OSVersionInfoSize uint32
    88  		MajorVersion      uint32
    89  		MinorVersion      uint32
    90  		BuildNumber       uint32
    91  		PlatformId        uint32
    92  		CSDVersion        [128]uint16
    93  		ServicePackMajor  uint16
    94  		ServicePackMinor  uint16
    95  		SuiteMask         uint16
    96  		ProductType       byte
    97  		Reserve           byte
    98  	}
    99  
   100  	d := GetDLL(t, "kernel32.dll")
   101  
   102  	var m1, m2 uintptr
   103  	VerSetConditionMask := d.Proc("VerSetConditionMask")
   104  	m1, m2, _ = VerSetConditionMask.Call(m1, m2, VER_MAJORVERSION, VER_GREATER_EQUAL)
   105  	m1, m2, _ = VerSetConditionMask.Call(m1, m2, VER_MINORVERSION, VER_GREATER_EQUAL)
   106  	m1, m2, _ = VerSetConditionMask.Call(m1, m2, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL)
   107  	m1, m2, _ = VerSetConditionMask.Call(m1, m2, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL)
   108  
   109  	vi := OSVersionInfoEx{
   110  		MajorVersion:     5,
   111  		MinorVersion:     1,
   112  		ServicePackMajor: 2,
   113  		ServicePackMinor: 0,
   114  	}
   115  	vi.OSVersionInfoSize = uint32(unsafe.Sizeof(vi))
   116  	r, _, e2 := d.Proc("VerifyVersionInfoW").Call(
   117  		uintptr(unsafe.Pointer(&vi)),
   118  		VER_MAJORVERSION|VER_MINORVERSION|VER_SERVICEPACKMAJOR|VER_SERVICEPACKMINOR,
   119  		m1, m2)
   120  	if r == 0 && e2 != ERROR_OLD_WIN_VERSION {
   121  		t.Errorf("VerifyVersionInfo failed: %s", e2)
   122  	}
   123  }
   124  
   125  func TestCDecl(t *testing.T) {
   126  	var buf [50]byte
   127  	fmtp, _ := syscall.BytePtrFromString("%d %d %d")
   128  	a, _, _ := GetDLL(t, "user32.dll").Proc("wsprintfA").Call(
   129  		uintptr(unsafe.Pointer(&buf[0])),
   130  		uintptr(unsafe.Pointer(fmtp)),
   131  		1000, 2000, 3000)
   132  	if string(buf[:a]) != "1000 2000 3000" {
   133  		t.Error("cdecl USER32.wsprintfA returns", a, "buf=", buf[:a])
   134  	}
   135  }
   136  
   137  func TestEnumWindows(t *testing.T) {
   138  	d := GetDLL(t, "user32.dll")
   139  	isWindows := d.Proc("IsWindow")
   140  	counter := 0
   141  	cb := syscall.NewCallback(func(hwnd syscall.Handle, lparam uintptr) uintptr {
   142  		if lparam != 888 {
   143  			t.Error("lparam was not passed to callback")
   144  		}
   145  		b, _, _ := isWindows.Call(uintptr(hwnd))
   146  		if b == 0 {
   147  			t.Error("USER32.IsWindow returns FALSE")
   148  		}
   149  		counter++
   150  		return 1 // continue enumeration
   151  	})
   152  	a, _, _ := d.Proc("EnumWindows").Call(cb, 888)
   153  	if a == 0 {
   154  		t.Error("USER32.EnumWindows returns FALSE")
   155  	}
   156  	if counter == 0 {
   157  		t.Error("Callback has been never called or your have no windows")
   158  	}
   159  }
   160  
   161  func callback(timeFormatString unsafe.Pointer, lparam uintptr) uintptr {
   162  	(*(*func())(unsafe.Pointer(&lparam)))()
   163  	return 0 // stop enumeration
   164  }
   165  
   166  // nestedCall calls into Windows, back into Go, and finally to f.
   167  func nestedCall(t *testing.T, f func()) {
   168  	c := syscall.NewCallback(callback)
   169  	d := GetDLL(t, "kernel32.dll")
   170  	defer d.Release()
   171  	const LOCALE_NAME_USER_DEFAULT = 0
   172  	d.Proc("EnumTimeFormatsEx").Call(c, LOCALE_NAME_USER_DEFAULT, 0, uintptr(*(*unsafe.Pointer)(unsafe.Pointer(&f))))
   173  }
   174  
   175  func TestCallback(t *testing.T) {
   176  	var x = false
   177  	nestedCall(t, func() { x = true })
   178  	if !x {
   179  		t.Fatal("nestedCall did not call func")
   180  	}
   181  }
   182  
   183  func TestCallbackGC(t *testing.T) {
   184  	nestedCall(t, runtime.GC)
   185  }
   186  
   187  func TestCallbackPanicLocked(t *testing.T) {
   188  	runtime.LockOSThread()
   189  	defer runtime.UnlockOSThread()
   190  
   191  	if !runtime.LockedOSThread() {
   192  		t.Fatal("runtime.LockOSThread didn't")
   193  	}
   194  	defer func() {
   195  		s := recover()
   196  		if s == nil {
   197  			t.Fatal("did not panic")
   198  		}
   199  		if s.(string) != "callback panic" {
   200  			t.Fatal("wrong panic:", s)
   201  		}
   202  		if !runtime.LockedOSThread() {
   203  			t.Fatal("lost lock on OS thread after panic")
   204  		}
   205  	}()
   206  	nestedCall(t, func() { panic("callback panic") })
   207  	panic("nestedCall returned")
   208  }
   209  
   210  func TestCallbackPanic(t *testing.T) {
   211  	// Make sure panic during callback unwinds properly.
   212  	if runtime.LockedOSThread() {
   213  		t.Fatal("locked OS thread on entry to TestCallbackPanic")
   214  	}
   215  	defer func() {
   216  		s := recover()
   217  		if s == nil {
   218  			t.Fatal("did not panic")
   219  		}
   220  		if s.(string) != "callback panic" {
   221  			t.Fatal("wrong panic:", s)
   222  		}
   223  		if runtime.LockedOSThread() {
   224  			t.Fatal("locked OS thread on exit from TestCallbackPanic")
   225  		}
   226  	}()
   227  	nestedCall(t, func() { panic("callback panic") })
   228  	panic("nestedCall returned")
   229  }
   230  
   231  func TestCallbackPanicLoop(t *testing.T) {
   232  	// Make sure we don't blow out m->g0 stack.
   233  	for i := 0; i < 100000; i++ {
   234  		TestCallbackPanic(t)
   235  	}
   236  }
   237  
   238  func TestBlockingCallback(t *testing.T) {
   239  	c := make(chan int)
   240  	go func() {
   241  		for i := 0; i < 10; i++ {
   242  			c <- <-c
   243  		}
   244  	}()
   245  	nestedCall(t, func() {
   246  		for i := 0; i < 10; i++ {
   247  			c <- i
   248  			if j := <-c; j != i {
   249  				t.Errorf("out of sync %d != %d", j, i)
   250  			}
   251  		}
   252  	})
   253  }
   254  
   255  func TestCallbackInAnotherThread(t *testing.T) {
   256  	d := GetDLL(t, "kernel32.dll")
   257  
   258  	f := func(p uintptr) uintptr {
   259  		return p
   260  	}
   261  	r, _, err := d.Proc("CreateThread").Call(0, 0, syscall.NewCallback(f), 123, 0, 0)
   262  	if r == 0 {
   263  		t.Fatalf("CreateThread failed: %v", err)
   264  	}
   265  	h := syscall.Handle(r)
   266  	defer syscall.CloseHandle(h)
   267  
   268  	switch s, err := syscall.WaitForSingleObject(h, 100); s {
   269  	case syscall.WAIT_OBJECT_0:
   270  		break
   271  	case syscall.WAIT_TIMEOUT:
   272  		t.Fatal("timeout waiting for thread to exit")
   273  	case syscall.WAIT_FAILED:
   274  		t.Fatalf("WaitForSingleObject failed: %v", err)
   275  	default:
   276  		t.Fatalf("WaitForSingleObject returns unexpected value %v", s)
   277  	}
   278  
   279  	var ec uint32
   280  	r, _, err = d.Proc("GetExitCodeThread").Call(uintptr(h), uintptr(unsafe.Pointer(&ec)))
   281  	if r == 0 {
   282  		t.Fatalf("GetExitCodeThread failed: %v", err)
   283  	}
   284  	if ec != 123 {
   285  		t.Fatalf("expected 123, but got %d", ec)
   286  	}
   287  }
   288  
   289  type cbFunc struct {
   290  	goFunc interface{}
   291  }
   292  
   293  func (f cbFunc) cName(cdecl bool) string {
   294  	name := "stdcall"
   295  	if cdecl {
   296  		name = "cdecl"
   297  	}
   298  	t := reflect.TypeOf(f.goFunc)
   299  	for i := 0; i < t.NumIn(); i++ {
   300  		name += "_" + t.In(i).Name()
   301  	}
   302  	return name
   303  }
   304  
   305  func (f cbFunc) cSrc(w io.Writer, cdecl bool) {
   306  	// Construct a C function that takes a callback with
   307  	// f.goFunc's signature, and calls it with integers 1..N.
   308  	funcname := f.cName(cdecl)
   309  	attr := "__stdcall"
   310  	if cdecl {
   311  		attr = "__cdecl"
   312  	}
   313  	typename := "t" + funcname
   314  	t := reflect.TypeOf(f.goFunc)
   315  	cTypes := make([]string, t.NumIn())
   316  	cArgs := make([]string, t.NumIn())
   317  	for i := range cTypes {
   318  		// We included stdint.h, so this works for all sized
   319  		// integer types, and uint8Pair_t.
   320  		cTypes[i] = t.In(i).Name() + "_t"
   321  		if t.In(i).Name() == "uint8Pair" {
   322  			cArgs[i] = fmt.Sprintf("(uint8Pair_t){%d,1}", i)
   323  		} else {
   324  			cArgs[i] = fmt.Sprintf("%d", i+1)
   325  		}
   326  	}
   327  	fmt.Fprintf(w, `
   328  typedef uintptr_t %s (*%s)(%s);
   329  uintptr_t %s(%s f) {
   330  	return f(%s);
   331  }
   332  	`, attr, typename, strings.Join(cTypes, ","), funcname, typename, strings.Join(cArgs, ","))
   333  }
   334  
   335  func (f cbFunc) testOne(t *testing.T, dll *syscall.DLL, cdecl bool, cb uintptr) {
   336  	r1, _, _ := dll.MustFindProc(f.cName(cdecl)).Call(cb)
   337  
   338  	want := 0
   339  	for i := 0; i < reflect.TypeOf(f.goFunc).NumIn(); i++ {
   340  		want += i + 1
   341  	}
   342  	if int(r1) != want {
   343  		t.Errorf("wanted result %d; got %d", want, r1)
   344  	}
   345  }
   346  
   347  type uint8Pair struct{ x, y uint8 }
   348  
   349  var cbFuncs = []cbFunc{
   350  	{func(i1, i2 uintptr) uintptr {
   351  		return i1 + i2
   352  	}},
   353  	{func(i1, i2, i3 uintptr) uintptr {
   354  		return i1 + i2 + i3
   355  	}},
   356  	{func(i1, i2, i3, i4 uintptr) uintptr {
   357  		return i1 + i2 + i3 + i4
   358  	}},
   359  	{func(i1, i2, i3, i4, i5 uintptr) uintptr {
   360  		return i1 + i2 + i3 + i4 + i5
   361  	}},
   362  	{func(i1, i2, i3, i4, i5, i6 uintptr) uintptr {
   363  		return i1 + i2 + i3 + i4 + i5 + i6
   364  	}},
   365  	{func(i1, i2, i3, i4, i5, i6, i7 uintptr) uintptr {
   366  		return i1 + i2 + i3 + i4 + i5 + i6 + i7
   367  	}},
   368  	{func(i1, i2, i3, i4, i5, i6, i7, i8 uintptr) uintptr {
   369  		return i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8
   370  	}},
   371  	{func(i1, i2, i3, i4, i5, i6, i7, i8, i9 uintptr) uintptr {
   372  		return i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9
   373  	}},
   374  
   375  	// Non-uintptr parameters.
   376  	{func(i1, i2, i3, i4, i5, i6, i7, i8, i9 uint8) uintptr {
   377  		return uintptr(i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9)
   378  	}},
   379  	{func(i1, i2, i3, i4, i5, i6, i7, i8, i9 uint16) uintptr {
   380  		return uintptr(i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9)
   381  	}},
   382  	{func(i1, i2, i3, i4, i5, i6, i7, i8, i9 int8) uintptr {
   383  		return uintptr(i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9)
   384  	}},
   385  	{func(i1 int8, i2 int16, i3 int32, i4, i5 uintptr) uintptr {
   386  		return uintptr(i1) + uintptr(i2) + uintptr(i3) + i4 + i5
   387  	}},
   388  	{func(i1, i2, i3, i4, i5 uint8Pair) uintptr {
   389  		return uintptr(i1.x + i1.y + i2.x + i2.y + i3.x + i3.y + i4.x + i4.y + i5.x + i5.y)
   390  	}},
   391  }
   392  
   393  type cbDLL struct {
   394  	name      string
   395  	buildArgs func(out, src string) []string
   396  }
   397  
   398  func (d *cbDLL) makeSrc(t *testing.T, path string) {
   399  	f, err := os.Create(path)
   400  	if err != nil {
   401  		t.Fatalf("failed to create source file: %v", err)
   402  	}
   403  	defer f.Close()
   404  
   405  	fmt.Fprint(f, `
   406  #include <stdint.h>
   407  typedef struct { uint8_t x, y; } uint8Pair_t;
   408  `)
   409  	for _, cbf := range cbFuncs {
   410  		cbf.cSrc(f, false)
   411  		cbf.cSrc(f, true)
   412  	}
   413  }
   414  
   415  func (d *cbDLL) build(t *testing.T, dir string) string {
   416  	srcname := d.name + ".c"
   417  	d.makeSrc(t, filepath.Join(dir, srcname))
   418  	outname := d.name + ".dll"
   419  	args := d.buildArgs(outname, srcname)
   420  	cmd := exec.Command(args[0], args[1:]...)
   421  	cmd.Dir = dir
   422  	out, err := cmd.CombinedOutput()
   423  	if err != nil {
   424  		t.Fatalf("failed to build dll: %v - %v", err, string(out))
   425  	}
   426  	return filepath.Join(dir, outname)
   427  }
   428  
   429  var cbDLLs = []cbDLL{
   430  	{
   431  		"test",
   432  		func(out, src string) []string {
   433  			return []string{"gcc", "-shared", "-s", "-Werror", "-o", out, src}
   434  		},
   435  	},
   436  	{
   437  		"testO2",
   438  		func(out, src string) []string {
   439  			return []string{"gcc", "-shared", "-s", "-Werror", "-o", out, "-O2", src}
   440  		},
   441  	},
   442  }
   443  
   444  func TestStdcallAndCDeclCallbacks(t *testing.T) {
   445  	if _, err := exec.LookPath("gcc"); err != nil {
   446  		t.Skip("skipping test: gcc is missing")
   447  	}
   448  	tmp, err := os.MkdirTemp("", "TestCDeclCallback")
   449  	if err != nil {
   450  		t.Fatal("TempDir failed: ", err)
   451  	}
   452  	defer os.RemoveAll(tmp)
   453  
   454  	for _, dll := range cbDLLs {
   455  		t.Run(dll.name, func(t *testing.T) {
   456  			dllPath := dll.build(t, tmp)
   457  			dll := syscall.MustLoadDLL(dllPath)
   458  			defer dll.Release()
   459  			for _, cbf := range cbFuncs {
   460  				t.Run(cbf.cName(false), func(t *testing.T) {
   461  					stdcall := syscall.NewCallback(cbf.goFunc)
   462  					cbf.testOne(t, dll, false, stdcall)
   463  				})
   464  				t.Run(cbf.cName(true), func(t *testing.T) {
   465  					cdecl := syscall.NewCallbackCDecl(cbf.goFunc)
   466  					cbf.testOne(t, dll, true, cdecl)
   467  				})
   468  			}
   469  		})
   470  	}
   471  }
   472  
   473  func TestRegisterClass(t *testing.T) {
   474  	kernel32 := GetDLL(t, "kernel32.dll")
   475  	user32 := GetDLL(t, "user32.dll")
   476  	mh, _, _ := kernel32.Proc("GetModuleHandleW").Call(0)
   477  	cb := syscall.NewCallback(func(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintptr) {
   478  		t.Fatal("callback should never get called")
   479  		return 0
   480  	})
   481  	type Wndclassex struct {
   482  		Size       uint32
   483  		Style      uint32
   484  		WndProc    uintptr
   485  		ClsExtra   int32
   486  		WndExtra   int32
   487  		Instance   syscall.Handle
   488  		Icon       syscall.Handle
   489  		Cursor     syscall.Handle
   490  		Background syscall.Handle
   491  		MenuName   *uint16
   492  		ClassName  *uint16
   493  		IconSm     syscall.Handle
   494  	}
   495  	name := syscall.StringToUTF16Ptr("test_window")
   496  	wc := Wndclassex{
   497  		WndProc:   cb,
   498  		Instance:  syscall.Handle(mh),
   499  		ClassName: name,
   500  	}
   501  	wc.Size = uint32(unsafe.Sizeof(wc))
   502  	a, _, err := user32.Proc("RegisterClassExW").Call(uintptr(unsafe.Pointer(&wc)))
   503  	if a == 0 {
   504  		t.Fatalf("RegisterClassEx failed: %v", err)
   505  	}
   506  	r, _, err := user32.Proc("UnregisterClassW").Call(uintptr(unsafe.Pointer(name)), 0)
   507  	if r == 0 {
   508  		t.Fatalf("UnregisterClass failed: %v", err)
   509  	}
   510  }
   511  
   512  func TestOutputDebugString(t *testing.T) {
   513  	d := GetDLL(t, "kernel32.dll")
   514  	p := syscall.StringToUTF16Ptr("testing OutputDebugString")
   515  	d.Proc("OutputDebugStringW").Call(uintptr(unsafe.Pointer(p)))
   516  }
   517  
   518  func TestRaiseException(t *testing.T) {
   519  	o := runTestProg(t, "testprog", "RaiseException")
   520  	if strings.Contains(o, "RaiseException should not return") {
   521  		t.Fatalf("RaiseException did not crash program: %v", o)
   522  	}
   523  	if !strings.Contains(o, "Exception 0xbad") {
   524  		t.Fatalf("No stack trace: %v", o)
   525  	}
   526  }
   527  
   528  func TestZeroDivisionException(t *testing.T) {
   529  	o := runTestProg(t, "testprog", "ZeroDivisionException")
   530  	if !strings.Contains(o, "panic: runtime error: integer divide by zero") {
   531  		t.Fatalf("No stack trace: %v", o)
   532  	}
   533  }
   534  
   535  func TestWERDialogue(t *testing.T) {
   536  	if os.Getenv("TESTING_WER_DIALOGUE") == "1" {
   537  		defer os.Exit(0)
   538  
   539  		*runtime.TestingWER = true
   540  		const EXCEPTION_NONCONTINUABLE = 1
   541  		mod := syscall.MustLoadDLL("kernel32.dll")
   542  		proc := mod.MustFindProc("RaiseException")
   543  		proc.Call(0xbad, EXCEPTION_NONCONTINUABLE, 0, 0)
   544  		println("RaiseException should not return")
   545  		return
   546  	}
   547  	cmd := exec.Command(os.Args[0], "-test.run=TestWERDialogue")
   548  	cmd.Env = []string{"TESTING_WER_DIALOGUE=1"}
   549  	// Child process should not open WER dialogue, but return immediately instead.
   550  	cmd.CombinedOutput()
   551  }
   552  
   553  func TestWindowsStackMemory(t *testing.T) {
   554  	o := runTestProg(t, "testprog", "StackMemory")
   555  	stackUsage, err := strconv.Atoi(o)
   556  	if err != nil {
   557  		t.Fatalf("Failed to read stack usage: %v", err)
   558  	}
   559  	if expected, got := 100<<10, stackUsage; got > expected {
   560  		t.Fatalf("expected < %d bytes of memory per thread, got %d", expected, got)
   561  	}
   562  }
   563  
   564  var used byte
   565  
   566  func use(buf []byte) {
   567  	for _, c := range buf {
   568  		used += c
   569  	}
   570  }
   571  
   572  func forceStackCopy() (r int) {
   573  	var f func(int) int
   574  	f = func(i int) int {
   575  		var buf [256]byte
   576  		use(buf[:])
   577  		if i == 0 {
   578  			return 0
   579  		}
   580  		return i + f(i-1)
   581  	}
   582  	r = f(128)
   583  	return
   584  }
   585  
   586  func TestReturnAfterStackGrowInCallback(t *testing.T) {
   587  	if _, err := exec.LookPath("gcc"); err != nil {
   588  		t.Skip("skipping test: gcc is missing")
   589  	}
   590  
   591  	const src = `
   592  #include <stdint.h>
   593  #include <windows.h>
   594  
   595  typedef uintptr_t __stdcall (*callback)(uintptr_t);
   596  
   597  uintptr_t cfunc(callback f, uintptr_t n) {
   598     uintptr_t r;
   599     r = f(n);
   600     SetLastError(333);
   601     return r;
   602  }
   603  `
   604  	tmpdir, err := os.MkdirTemp("", "TestReturnAfterStackGrowInCallback")
   605  	if err != nil {
   606  		t.Fatal("TempDir failed: ", err)
   607  	}
   608  	defer os.RemoveAll(tmpdir)
   609  
   610  	srcname := "mydll.c"
   611  	err = os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
   612  	if err != nil {
   613  		t.Fatal(err)
   614  	}
   615  	outname := "mydll.dll"
   616  	cmd := exec.Command("gcc", "-shared", "-s", "-Werror", "-o", outname, srcname)
   617  	cmd.Dir = tmpdir
   618  	out, err := cmd.CombinedOutput()
   619  	if err != nil {
   620  		t.Fatalf("failed to build dll: %v - %v", err, string(out))
   621  	}
   622  	dllpath := filepath.Join(tmpdir, outname)
   623  
   624  	dll := syscall.MustLoadDLL(dllpath)
   625  	defer dll.Release()
   626  
   627  	proc := dll.MustFindProc("cfunc")
   628  
   629  	cb := syscall.NewCallback(func(n uintptr) uintptr {
   630  		forceStackCopy()
   631  		return n
   632  	})
   633  
   634  	// Use a new goroutine so that we get a small stack.
   635  	type result struct {
   636  		r   uintptr
   637  		err syscall.Errno
   638  	}
   639  	want := result{
   640  		// Make it large enough to test issue #29331.
   641  		r:   (^uintptr(0)) >> 24,
   642  		err: 333,
   643  	}
   644  	c := make(chan result)
   645  	go func() {
   646  		r, _, err := proc.Call(cb, want.r)
   647  		c <- result{r, err.(syscall.Errno)}
   648  	}()
   649  	if got := <-c; got != want {
   650  		t.Errorf("got %d want %d", got, want)
   651  	}
   652  }
   653  
   654  func TestFloatArgs(t *testing.T) {
   655  	if _, err := exec.LookPath("gcc"); err != nil {
   656  		t.Skip("skipping test: gcc is missing")
   657  	}
   658  	if runtime.GOARCH != "amd64" {
   659  		t.Skipf("skipping test: GOARCH=%s", runtime.GOARCH)
   660  	}
   661  
   662  	const src = `
   663  #include <stdint.h>
   664  #include <windows.h>
   665  
   666  uintptr_t cfunc(uintptr_t a, double b, float c, double d) {
   667  	if (a == 1 && b == 2.2 && c == 3.3f && d == 4.4e44) {
   668  		return 1;
   669  	}
   670  	return 0;
   671  }
   672  `
   673  	tmpdir, err := os.MkdirTemp("", "TestFloatArgs")
   674  	if err != nil {
   675  		t.Fatal("TempDir failed: ", err)
   676  	}
   677  	defer os.RemoveAll(tmpdir)
   678  
   679  	srcname := "mydll.c"
   680  	err = os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
   681  	if err != nil {
   682  		t.Fatal(err)
   683  	}
   684  	outname := "mydll.dll"
   685  	cmd := exec.Command("gcc", "-shared", "-s", "-Werror", "-o", outname, srcname)
   686  	cmd.Dir = tmpdir
   687  	out, err := cmd.CombinedOutput()
   688  	if err != nil {
   689  		t.Fatalf("failed to build dll: %v - %v", err, string(out))
   690  	}
   691  	dllpath := filepath.Join(tmpdir, outname)
   692  
   693  	dll := syscall.MustLoadDLL(dllpath)
   694  	defer dll.Release()
   695  
   696  	proc := dll.MustFindProc("cfunc")
   697  
   698  	r, _, err := proc.Call(
   699  		1,
   700  		uintptr(math.Float64bits(2.2)),
   701  		uintptr(math.Float32bits(3.3)),
   702  		uintptr(math.Float64bits(4.4e44)),
   703  	)
   704  	if r != 1 {
   705  		t.Errorf("got %d want 1 (err=%v)", r, err)
   706  	}
   707  }
   708  
   709  func TestFloatReturn(t *testing.T) {
   710  	if _, err := exec.LookPath("gcc"); err != nil {
   711  		t.Skip("skipping test: gcc is missing")
   712  	}
   713  	if runtime.GOARCH != "amd64" {
   714  		t.Skipf("skipping test: GOARCH=%s", runtime.GOARCH)
   715  	}
   716  
   717  	const src = `
   718  #include <stdint.h>
   719  #include <windows.h>
   720  
   721  float cfuncFloat(uintptr_t a, double b, float c, double d) {
   722  	if (a == 1 && b == 2.2 && c == 3.3f && d == 4.4e44) {
   723  		return 1.5f;
   724  	}
   725  	return 0;
   726  }
   727  
   728  double cfuncDouble(uintptr_t a, double b, float c, double d) {
   729  	if (a == 1 && b == 2.2 && c == 3.3f && d == 4.4e44) {
   730  		return 2.5;
   731  	}
   732  	return 0;
   733  }
   734  `
   735  	tmpdir, err := os.MkdirTemp("", "TestFloatReturn")
   736  	if err != nil {
   737  		t.Fatal("TempDir failed: ", err)
   738  	}
   739  	defer os.RemoveAll(tmpdir)
   740  
   741  	srcname := "mydll.c"
   742  	err = os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
   743  	if err != nil {
   744  		t.Fatal(err)
   745  	}
   746  	outname := "mydll.dll"
   747  	cmd := exec.Command("gcc", "-shared", "-s", "-Werror", "-o", outname, srcname)
   748  	cmd.Dir = tmpdir
   749  	out, err := cmd.CombinedOutput()
   750  	if err != nil {
   751  		t.Fatalf("failed to build dll: %v - %v", err, string(out))
   752  	}
   753  	dllpath := filepath.Join(tmpdir, outname)
   754  
   755  	dll := syscall.MustLoadDLL(dllpath)
   756  	defer dll.Release()
   757  
   758  	proc := dll.MustFindProc("cfuncFloat")
   759  
   760  	_, r, err := proc.Call(
   761  		1,
   762  		uintptr(math.Float64bits(2.2)),
   763  		uintptr(math.Float32bits(3.3)),
   764  		uintptr(math.Float64bits(4.4e44)),
   765  	)
   766  	fr := math.Float32frombits(uint32(r))
   767  	if fr != 1.5 {
   768  		t.Errorf("got %f want 1.5 (err=%v)", fr, err)
   769  	}
   770  
   771  	proc = dll.MustFindProc("cfuncDouble")
   772  
   773  	_, r, err = proc.Call(
   774  		1,
   775  		uintptr(math.Float64bits(2.2)),
   776  		uintptr(math.Float32bits(3.3)),
   777  		uintptr(math.Float64bits(4.4e44)),
   778  	)
   779  	dr := math.Float64frombits(uint64(r))
   780  	if dr != 2.5 {
   781  		t.Errorf("got %f want 2.5 (err=%v)", dr, err)
   782  	}
   783  }
   784  
   785  func TestTimeBeginPeriod(t *testing.T) {
   786  	const TIMERR_NOERROR = 0
   787  	if *runtime.TimeBeginPeriodRetValue != TIMERR_NOERROR {
   788  		t.Fatalf("timeBeginPeriod failed: it returned %d", *runtime.TimeBeginPeriodRetValue)
   789  	}
   790  }
   791  
   792  // removeOneCPU removes one (any) cpu from affinity mask.
   793  // It returns new affinity mask.
   794  func removeOneCPU(mask uintptr) (uintptr, error) {
   795  	if mask == 0 {
   796  		return 0, fmt.Errorf("cpu affinity mask is empty")
   797  	}
   798  	maskbits := int(unsafe.Sizeof(mask) * 8)
   799  	for i := 0; i < maskbits; i++ {
   800  		newmask := mask & ^(1 << uint(i))
   801  		if newmask != mask {
   802  			return newmask, nil
   803  		}
   804  
   805  	}
   806  	panic("not reached")
   807  }
   808  
   809  func resumeChildThread(kernel32 *syscall.DLL, childpid int) error {
   810  	_OpenThread := kernel32.MustFindProc("OpenThread")
   811  	_ResumeThread := kernel32.MustFindProc("ResumeThread")
   812  	_Thread32First := kernel32.MustFindProc("Thread32First")
   813  	_Thread32Next := kernel32.MustFindProc("Thread32Next")
   814  
   815  	snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPTHREAD, 0)
   816  	if err != nil {
   817  		return err
   818  	}
   819  	defer syscall.CloseHandle(snapshot)
   820  
   821  	const _THREAD_SUSPEND_RESUME = 0x0002
   822  
   823  	type ThreadEntry32 struct {
   824  		Size           uint32
   825  		tUsage         uint32
   826  		ThreadID       uint32
   827  		OwnerProcessID uint32
   828  		BasePri        int32
   829  		DeltaPri       int32
   830  		Flags          uint32
   831  	}
   832  
   833  	var te ThreadEntry32
   834  	te.Size = uint32(unsafe.Sizeof(te))
   835  	ret, _, err := _Thread32First.Call(uintptr(snapshot), uintptr(unsafe.Pointer(&te)))
   836  	if ret == 0 {
   837  		return err
   838  	}
   839  	for te.OwnerProcessID != uint32(childpid) {
   840  		ret, _, err = _Thread32Next.Call(uintptr(snapshot), uintptr(unsafe.Pointer(&te)))
   841  		if ret == 0 {
   842  			return err
   843  		}
   844  	}
   845  	h, _, err := _OpenThread.Call(_THREAD_SUSPEND_RESUME, 1, uintptr(te.ThreadID))
   846  	if h == 0 {
   847  		return err
   848  	}
   849  	defer syscall.Close(syscall.Handle(h))
   850  
   851  	ret, _, err = _ResumeThread.Call(h)
   852  	if ret == 0xffffffff {
   853  		return err
   854  	}
   855  	return nil
   856  }
   857  
   858  func TestNumCPU(t *testing.T) {
   859  	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
   860  		// in child process
   861  		fmt.Fprintf(os.Stderr, "%d", runtime.NumCPU())
   862  		os.Exit(0)
   863  	}
   864  
   865  	switch n := runtime.NumberOfProcessors(); {
   866  	case n < 1:
   867  		t.Fatalf("system cannot have %d cpu(s)", n)
   868  	case n == 1:
   869  		if runtime.NumCPU() != 1 {
   870  			t.Fatalf("runtime.NumCPU() returns %d on single cpu system", runtime.NumCPU())
   871  		}
   872  		return
   873  	}
   874  
   875  	const (
   876  		_CREATE_SUSPENDED   = 0x00000004
   877  		_PROCESS_ALL_ACCESS = syscall.STANDARD_RIGHTS_REQUIRED | syscall.SYNCHRONIZE | 0xfff
   878  	)
   879  
   880  	kernel32 := syscall.MustLoadDLL("kernel32.dll")
   881  	_GetProcessAffinityMask := kernel32.MustFindProc("GetProcessAffinityMask")
   882  	_SetProcessAffinityMask := kernel32.MustFindProc("SetProcessAffinityMask")
   883  
   884  	cmd := exec.Command(os.Args[0], "-test.run=TestNumCPU")
   885  	cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1")
   886  	var buf bytes.Buffer
   887  	cmd.Stdout = &buf
   888  	cmd.Stderr = &buf
   889  	cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: _CREATE_SUSPENDED}
   890  	err := cmd.Start()
   891  	if err != nil {
   892  		t.Fatal(err)
   893  	}
   894  	defer func() {
   895  		err = cmd.Wait()
   896  		childOutput := string(buf.Bytes())
   897  		if err != nil {
   898  			t.Fatalf("child failed: %v: %v", err, childOutput)
   899  		}
   900  		// removeOneCPU should have decreased child cpu count by 1
   901  		want := fmt.Sprintf("%d", runtime.NumCPU()-1)
   902  		if childOutput != want {
   903  			t.Fatalf("child output: want %q, got %q", want, childOutput)
   904  		}
   905  	}()
   906  
   907  	defer func() {
   908  		err = resumeChildThread(kernel32, cmd.Process.Pid)
   909  		if err != nil {
   910  			t.Fatal(err)
   911  		}
   912  	}()
   913  
   914  	ph, err := syscall.OpenProcess(_PROCESS_ALL_ACCESS, false, uint32(cmd.Process.Pid))
   915  	if err != nil {
   916  		t.Fatal(err)
   917  	}
   918  	defer syscall.CloseHandle(ph)
   919  
   920  	var mask, sysmask uintptr
   921  	ret, _, err := _GetProcessAffinityMask.Call(uintptr(ph), uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask)))
   922  	if ret == 0 {
   923  		t.Fatal(err)
   924  	}
   925  
   926  	newmask, err := removeOneCPU(mask)
   927  	if err != nil {
   928  		t.Fatal(err)
   929  	}
   930  
   931  	ret, _, err = _SetProcessAffinityMask.Call(uintptr(ph), newmask)
   932  	if ret == 0 {
   933  		t.Fatal(err)
   934  	}
   935  	ret, _, err = _GetProcessAffinityMask.Call(uintptr(ph), uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask)))
   936  	if ret == 0 {
   937  		t.Fatal(err)
   938  	}
   939  	if newmask != mask {
   940  		t.Fatalf("SetProcessAffinityMask didn't set newmask of 0x%x. Current mask is 0x%x.", newmask, mask)
   941  	}
   942  }
   943  
   944  // See Issue 14959
   945  func TestDLLPreloadMitigation(t *testing.T) {
   946  	if _, err := exec.LookPath("gcc"); err != nil {
   947  		t.Skip("skipping test: gcc is missing")
   948  	}
   949  
   950  	tmpdir, err := os.MkdirTemp("", "TestDLLPreloadMitigation")
   951  	if err != nil {
   952  		t.Fatal("TempDir failed: ", err)
   953  	}
   954  	defer func() {
   955  		err := os.RemoveAll(tmpdir)
   956  		if err != nil {
   957  			t.Error(err)
   958  		}
   959  	}()
   960  
   961  	dir0, err := os.Getwd()
   962  	if err != nil {
   963  		t.Fatal(err)
   964  	}
   965  	defer os.Chdir(dir0)
   966  
   967  	const src = `
   968  #include <stdint.h>
   969  #include <windows.h>
   970  
   971  uintptr_t cfunc(void) {
   972     SetLastError(123);
   973     return 0;
   974  }
   975  `
   976  	srcname := "nojack.c"
   977  	err = os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
   978  	if err != nil {
   979  		t.Fatal(err)
   980  	}
   981  	name := "nojack.dll"
   982  	cmd := exec.Command("gcc", "-shared", "-s", "-Werror", "-o", name, srcname)
   983  	cmd.Dir = tmpdir
   984  	out, err := cmd.CombinedOutput()
   985  	if err != nil {
   986  		t.Fatalf("failed to build dll: %v - %v", err, string(out))
   987  	}
   988  	dllpath := filepath.Join(tmpdir, name)
   989  
   990  	dll := syscall.MustLoadDLL(dllpath)
   991  	dll.MustFindProc("cfunc")
   992  	dll.Release()
   993  
   994  	// Get into the directory with the DLL we'll load by base name
   995  	// ("nojack.dll") Think of this as the user double-clicking an
   996  	// installer from their Downloads directory where a browser
   997  	// silently downloaded some malicious DLLs.
   998  	os.Chdir(tmpdir)
   999  
  1000  	// First before we can load a DLL from the current directory,
  1001  	// loading it only as "nojack.dll", without an absolute path.
  1002  	delete(sysdll.IsSystemDLL, name) // in case test was run repeatedly
  1003  	dll, err = syscall.LoadDLL(name)
  1004  	if err != nil {
  1005  		t.Fatalf("failed to load %s by base name before sysdll registration: %v", name, err)
  1006  	}
  1007  	dll.Release()
  1008  
  1009  	// And now verify that if we register it as a system32-only
  1010  	// DLL, the implicit loading from the current directory no
  1011  	// longer works.
  1012  	sysdll.IsSystemDLL[name] = true
  1013  	dll, err = syscall.LoadDLL(name)
  1014  	if err == nil {
  1015  		dll.Release()
  1016  		if wantLoadLibraryEx() {
  1017  			t.Fatalf("Bad: insecure load of DLL by base name %q before sysdll registration: %v", name, err)
  1018  		}
  1019  		t.Skip("insecure load of DLL, but expected")
  1020  	}
  1021  }
  1022  
  1023  // Test that C code called via a DLL can use large Windows thread
  1024  // stacks and call back in to Go without crashing. See issue #20975.
  1025  //
  1026  // See also TestBigStackCallbackCgo.
  1027  func TestBigStackCallbackSyscall(t *testing.T) {
  1028  	if _, err := exec.LookPath("gcc"); err != nil {
  1029  		t.Skip("skipping test: gcc is missing")
  1030  	}
  1031  
  1032  	srcname, err := filepath.Abs("testdata/testprogcgo/bigstack_windows.c")
  1033  	if err != nil {
  1034  		t.Fatal("Abs failed: ", err)
  1035  	}
  1036  
  1037  	tmpdir, err := os.MkdirTemp("", "TestBigStackCallback")
  1038  	if err != nil {
  1039  		t.Fatal("TempDir failed: ", err)
  1040  	}
  1041  	defer os.RemoveAll(tmpdir)
  1042  
  1043  	outname := "mydll.dll"
  1044  	cmd := exec.Command("gcc", "-shared", "-s", "-Werror", "-o", outname, srcname)
  1045  	cmd.Dir = tmpdir
  1046  	out, err := cmd.CombinedOutput()
  1047  	if err != nil {
  1048  		t.Fatalf("failed to build dll: %v - %v", err, string(out))
  1049  	}
  1050  	dllpath := filepath.Join(tmpdir, outname)
  1051  
  1052  	dll := syscall.MustLoadDLL(dllpath)
  1053  	defer dll.Release()
  1054  
  1055  	var ok bool
  1056  	proc := dll.MustFindProc("bigStack")
  1057  	cb := syscall.NewCallback(func() uintptr {
  1058  		// Do something interesting to force stack checks.
  1059  		forceStackCopy()
  1060  		ok = true
  1061  		return 0
  1062  	})
  1063  	proc.Call(cb)
  1064  	if !ok {
  1065  		t.Fatalf("callback not called")
  1066  	}
  1067  }
  1068  
  1069  // wantLoadLibraryEx reports whether we expect LoadLibraryEx to work for tests.
  1070  func wantLoadLibraryEx() bool {
  1071  	return testenv.Builder() == "windows-amd64-gce" || testenv.Builder() == "windows-386-gce"
  1072  }
  1073  
  1074  func TestLoadLibraryEx(t *testing.T) {
  1075  	use, have, flags := runtime.LoadLibraryExStatus()
  1076  	if use {
  1077  		return // success.
  1078  	}
  1079  	if wantLoadLibraryEx() {
  1080  		t.Fatalf("Expected LoadLibraryEx+flags to be available. (LoadLibraryEx=%v; flags=%v)",
  1081  			have, flags)
  1082  	}
  1083  	t.Skipf("LoadLibraryEx not usable, but not expected. (LoadLibraryEx=%v; flags=%v)",
  1084  		have, flags)
  1085  }
  1086  
  1087  var (
  1088  	modwinmm    = syscall.NewLazyDLL("winmm.dll")
  1089  	modkernel32 = syscall.NewLazyDLL("kernel32.dll")
  1090  
  1091  	procCreateEvent = modkernel32.NewProc("CreateEventW")
  1092  	procSetEvent    = modkernel32.NewProc("SetEvent")
  1093  )
  1094  
  1095  func createEvent() (syscall.Handle, error) {
  1096  	r0, _, e0 := syscall.Syscall6(procCreateEvent.Addr(), 4, 0, 0, 0, 0, 0, 0)
  1097  	if r0 == 0 {
  1098  		return 0, syscall.Errno(e0)
  1099  	}
  1100  	return syscall.Handle(r0), nil
  1101  }
  1102  
  1103  func setEvent(h syscall.Handle) error {
  1104  	r0, _, e0 := syscall.Syscall(procSetEvent.Addr(), 1, uintptr(h), 0, 0)
  1105  	if r0 == 0 {
  1106  		return syscall.Errno(e0)
  1107  	}
  1108  	return nil
  1109  }
  1110  
  1111  func BenchmarkChanToSyscallPing(b *testing.B) {
  1112  	n := b.N
  1113  	ch := make(chan int)
  1114  	event, err := createEvent()
  1115  	if err != nil {
  1116  		b.Fatal(err)
  1117  	}
  1118  	go func() {
  1119  		for i := 0; i < n; i++ {
  1120  			syscall.WaitForSingleObject(event, syscall.INFINITE)
  1121  			ch <- 1
  1122  		}
  1123  	}()
  1124  	for i := 0; i < n; i++ {
  1125  		err := setEvent(event)
  1126  		if err != nil {
  1127  			b.Fatal(err)
  1128  		}
  1129  		<-ch
  1130  	}
  1131  }
  1132  
  1133  func BenchmarkSyscallToSyscallPing(b *testing.B) {
  1134  	n := b.N
  1135  	event1, err := createEvent()
  1136  	if err != nil {
  1137  		b.Fatal(err)
  1138  	}
  1139  	event2, err := createEvent()
  1140  	if err != nil {
  1141  		b.Fatal(err)
  1142  	}
  1143  	go func() {
  1144  		for i := 0; i < n; i++ {
  1145  			syscall.WaitForSingleObject(event1, syscall.INFINITE)
  1146  			if err := setEvent(event2); err != nil {
  1147  				b.Errorf("Set event failed: %v", err)
  1148  				return
  1149  			}
  1150  		}
  1151  	}()
  1152  	for i := 0; i < n; i++ {
  1153  		if err := setEvent(event1); err != nil {
  1154  			b.Fatal(err)
  1155  		}
  1156  		if b.Failed() {
  1157  			break
  1158  		}
  1159  		syscall.WaitForSingleObject(event2, syscall.INFINITE)
  1160  	}
  1161  }
  1162  
  1163  func BenchmarkChanToChanPing(b *testing.B) {
  1164  	n := b.N
  1165  	ch1 := make(chan int)
  1166  	ch2 := make(chan int)
  1167  	go func() {
  1168  		for i := 0; i < n; i++ {
  1169  			<-ch1
  1170  			ch2 <- 1
  1171  		}
  1172  	}()
  1173  	for i := 0; i < n; i++ {
  1174  		ch1 <- 1
  1175  		<-ch2
  1176  	}
  1177  }
  1178  
  1179  func BenchmarkOsYield(b *testing.B) {
  1180  	for i := 0; i < b.N; i++ {
  1181  		runtime.OsYield()
  1182  	}
  1183  }
  1184  
  1185  func BenchmarkRunningGoProgram(b *testing.B) {
  1186  	tmpdir, err := os.MkdirTemp("", "BenchmarkRunningGoProgram")
  1187  	if err != nil {
  1188  		b.Fatal(err)
  1189  	}
  1190  	defer os.RemoveAll(tmpdir)
  1191  
  1192  	src := filepath.Join(tmpdir, "main.go")
  1193  	err = os.WriteFile(src, []byte(benchmarkRunningGoProgram), 0666)
  1194  	if err != nil {
  1195  		b.Fatal(err)
  1196  	}
  1197  
  1198  	exe := filepath.Join(tmpdir, "main.exe")
  1199  	cmd := exec.Command(testenv.GoToolPath(b), "build", "-o", exe, src)
  1200  	cmd.Dir = tmpdir
  1201  	out, err := cmd.CombinedOutput()
  1202  	if err != nil {
  1203  		b.Fatalf("building main.exe failed: %v\n%s", err, out)
  1204  	}
  1205  
  1206  	b.ResetTimer()
  1207  	for i := 0; i < b.N; i++ {
  1208  		cmd := exec.Command(exe)
  1209  		out, err := cmd.CombinedOutput()
  1210  		if err != nil {
  1211  			b.Fatalf("running main.exe failed: %v\n%s", err, out)
  1212  		}
  1213  	}
  1214  }
  1215  
  1216  const benchmarkRunningGoProgram = `
  1217  package main
  1218  
  1219  import _ "os" // average Go program will use "os" package, do the same here
  1220  
  1221  func main() {
  1222  }
  1223  `