Source file src/cmd/go/internal/work/security_test.go

     1  // Copyright 2018 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 work
     6  
     7  import (
     8  	"os"
     9  	"strings"
    10  	"testing"
    11  )
    12  
    13  var goodCompilerFlags = [][]string{
    14  	{"-DFOO"},
    15  	{"-Dfoo=bar"},
    16  	{"-Ufoo"},
    17  	{"-Ufoo1"},
    18  	{"-F/Qt"},
    19  	{"-F", "/Qt"},
    20  	{"-I/"},
    21  	{"-I/etc/passwd"},
    22  	{"-I."},
    23  	{"-O"},
    24  	{"-O2"},
    25  	{"-Osmall"},
    26  	{"-W"},
    27  	{"-Wall"},
    28  	{"-Wp,-Dfoo=bar"},
    29  	{"-Wp,-Ufoo"},
    30  	{"-Wp,-Dfoo1"},
    31  	{"-Wp,-Ufoo1"},
    32  	{"-flto"},
    33  	{"-fobjc-arc"},
    34  	{"-fno-objc-arc"},
    35  	{"-fomit-frame-pointer"},
    36  	{"-fno-omit-frame-pointer"},
    37  	{"-fpic"},
    38  	{"-fno-pic"},
    39  	{"-fPIC"},
    40  	{"-fno-PIC"},
    41  	{"-fpie"},
    42  	{"-fno-pie"},
    43  	{"-fPIE"},
    44  	{"-fno-PIE"},
    45  	{"-fsplit-stack"},
    46  	{"-fno-split-stack"},
    47  	{"-fstack-xxx"},
    48  	{"-fno-stack-xxx"},
    49  	{"-fsanitize=hands"},
    50  	{"-ftls-model=local-dynamic"},
    51  	{"-g"},
    52  	{"-ggdb"},
    53  	{"-mabi=lp64d"},
    54  	{"-march=souza"},
    55  	{"-mcmodel=medium"},
    56  	{"-mcpu=123"},
    57  	{"-mfpu=123"},
    58  	{"-mtls-dialect=gnu"},
    59  	{"-mtls-dialect=gnu2"},
    60  	{"-mtls-dialect=trad"},
    61  	{"-mtls-dialect=desc"},
    62  	{"-mtls-dialect=xyz"},
    63  	{"-msimd=lasx"},
    64  	{"-msimd=xyz"},
    65  	{"-mdouble-float"},
    66  	{"-mrelax"},
    67  	{"-mstrict-align"},
    68  	{"-mlsx"},
    69  	{"-mlasx"},
    70  	{"-mfrecipe"},
    71  	{"-mlam-bh"},
    72  	{"-mlamcas"},
    73  	{"-mld-seq-sa"},
    74  	{"-mno-relax"},
    75  	{"-mno-strict-align"},
    76  	{"-mno-lsx"},
    77  	{"-mno-lasx"},
    78  	{"-mno-frecipe"},
    79  	{"-mno-lam-bh"},
    80  	{"-mno-lamcas"},
    81  	{"-mno-ld-seq-sa"},
    82  	{"-mlarge-data-threshold=16"},
    83  	{"-mtune=happybirthday"},
    84  	{"-mstack-overflow"},
    85  	{"-mno-stack-overflow"},
    86  	{"-mmacosx-version"},
    87  	{"-mnop-fun-dllimport"},
    88  	{"-pthread"},
    89  	{"-std=c99"},
    90  	{"-xc"},
    91  	{"-D", "FOO"},
    92  	{"-D", "foo=bar"},
    93  	{"-I", "."},
    94  	{"-I", "/etc/passwd"},
    95  	{"-I", "世界"},
    96  	{"-I", "=/usr/include/libxml2"},
    97  	{"-I", "dir"},
    98  	{"-I", "$SYSROOT/dir"},
    99  	{"-isystem", "/usr/include/mozjs-68"},
   100  	{"-include", "/usr/include/mozjs-68/RequiredDefines.h"},
   101  	{"-framework", "Chocolate"},
   102  	{"-x", "c"},
   103  	{"-v"},
   104  }
   105  
   106  var badCompilerFlags = [][]string{
   107  	{"-D@X"},
   108  	{"-D-X"},
   109  	{"-Ufoo=bar"},
   110  	{"-F@dir"},
   111  	{"-F-dir"},
   112  	{"-I@dir"},
   113  	{"-I-dir"},
   114  	{"-O@1"},
   115  	{"-Wa,-foo"},
   116  	{"-W@foo"},
   117  	{"-Wp,-DX,-D@X"},
   118  	{"-Wp,-UX,-U@X"},
   119  	{"-g@gdb"},
   120  	{"-g-gdb"},
   121  	{"-march=@dawn"},
   122  	{"-march=-dawn"},
   123  	{"-mcmodel=@model"},
   124  	{"-mfpu=@0"},
   125  	{"-mfpu=-0"},
   126  	{"-mlarge-data-threshold=@12"},
   127  	{"-mtls-dialect=@gnu"},
   128  	{"-mtls-dialect=-gnu"},
   129  	{"-msimd=@none"},
   130  	{"-msimd=-none"},
   131  	{"-std=@c99"},
   132  	{"-std=-c99"},
   133  	{"-x@c"},
   134  	{"-x-c"},
   135  	{"-D", "@foo"},
   136  	{"-D", "-foo"},
   137  	{"-I", "@foo"},
   138  	{"-I", "-foo"},
   139  	{"-I", "=@obj"},
   140  	{"-include", "@foo"},
   141  	{"-framework", "-Caffeine"},
   142  	{"-framework", "@Home"},
   143  	{"-x", "--c"},
   144  	{"-x", "@obj"},
   145  }
   146  
   147  func TestCheckCompilerFlags(t *testing.T) {
   148  	for _, f := range goodCompilerFlags {
   149  		if err := checkCompilerFlags("test", "test", f); err != nil {
   150  			t.Errorf("unexpected error for %q: %v", f, err)
   151  		}
   152  	}
   153  	for _, f := range badCompilerFlags {
   154  		if err := checkCompilerFlags("test", "test", f); err == nil {
   155  			t.Errorf("missing error for %q", f)
   156  		}
   157  	}
   158  }
   159  
   160  var goodLinkerFlags = [][]string{
   161  	{"-Fbar"},
   162  	{"-lbar"},
   163  	{"-Lbar"},
   164  	{"-fpic"},
   165  	{"-fno-pic"},
   166  	{"-fPIC"},
   167  	{"-fno-PIC"},
   168  	{"-fpie"},
   169  	{"-fno-pie"},
   170  	{"-fPIE"},
   171  	{"-fno-PIE"},
   172  	{"-fsanitize=hands"},
   173  	{"-g"},
   174  	{"-ggdb"},
   175  	{"-march=souza"},
   176  	{"-mcpu=123"},
   177  	{"-mfpu=123"},
   178  	{"-mtune=happybirthday"},
   179  	{"-pic"},
   180  	{"-pthread"},
   181  	{"-Wl,--hash-style=both"},
   182  	{"-Wl,-rpath,foo"},
   183  	{"-Wl,-rpath,$ORIGIN/foo"},
   184  	{"-Wl,-R", "/foo"},
   185  	{"-Wl,-R", "foo"},
   186  	{"-Wl,-R,foo"},
   187  	{"-Wl,--just-symbols=foo"},
   188  	{"-Wl,--just-symbols,foo"},
   189  	{"-Wl,--warn-error"},
   190  	{"-Wl,--no-warn-error"},
   191  	{"foo.so"},
   192  	{"_世界.dll"},
   193  	{"./x.o"},
   194  	{"libcgosotest.dylib"},
   195  	{"-F", "framework"},
   196  	{"-l", "."},
   197  	{"-l", "/etc/passwd"},
   198  	{"-l", "世界"},
   199  	{"-L", "framework"},
   200  	{"-framework", "Chocolate"},
   201  	{"-v"},
   202  	{"-Wl,-sectcreate,__TEXT,__info_plist,${SRCDIR}/Info.plist"},
   203  	{"-Wl,-framework", "-Wl,Chocolate"},
   204  	{"-Wl,-framework,Chocolate"},
   205  	{"-Wl,-unresolved-symbols=ignore-all"},
   206  	{"-Wl,-z,relro"},
   207  	{"-Wl,-z,relro,-z,now"},
   208  	{"-Wl,-z,now"},
   209  	{"-Wl,-z,noexecstack"},
   210  	{"libcgotbdtest.tbd"},
   211  	{"./libcgotbdtest.tbd"},
   212  	{"-Wl,--push-state"},
   213  	{"-Wl,--pop-state"},
   214  	{"-Wl,--push-state,--as-needed"},
   215  	{"-Wl,--push-state,--no-as-needed,-Bstatic"},
   216  	{"-Wl,--just-symbols,."},
   217  	{"-Wl,-framework,."},
   218  	{"-Wl,-rpath,."},
   219  	{"-Wl,-rpath-link,."},
   220  	{"-Wl,-sectcreate,.,.,."},
   221  	{"-Wl,-syslibroot,."},
   222  	{"-Wl,-undefined,."},
   223  }
   224  
   225  var badLinkerFlags = [][]string{
   226  	{"-DFOO"},
   227  	{"-Dfoo=bar"},
   228  	{"-W"},
   229  	{"-Wall"},
   230  	{"-fobjc-arc"},
   231  	{"-fno-objc-arc"},
   232  	{"-fomit-frame-pointer"},
   233  	{"-fno-omit-frame-pointer"},
   234  	{"-fsplit-stack"},
   235  	{"-fno-split-stack"},
   236  	{"-fstack-xxx"},
   237  	{"-fno-stack-xxx"},
   238  	{"-mstack-overflow"},
   239  	{"-mno-stack-overflow"},
   240  	{"-mnop-fun-dllimport"},
   241  	{"-std=c99"},
   242  	{"-xc"},
   243  	{"-D", "FOO"},
   244  	{"-D", "foo=bar"},
   245  	{"-I", "FOO"},
   246  	{"-L", "@foo"},
   247  	{"-L", "-foo"},
   248  	{"-x", "c"},
   249  	{"-D@X"},
   250  	{"-D-X"},
   251  	{"-I@dir"},
   252  	{"-I-dir"},
   253  	{"-O@1"},
   254  	{"-Wa,-foo"},
   255  	{"-W@foo"},
   256  	{"-g@gdb"},
   257  	{"-g-gdb"},
   258  	{"-march=@dawn"},
   259  	{"-march=-dawn"},
   260  	{"-std=@c99"},
   261  	{"-std=-c99"},
   262  	{"-x@c"},
   263  	{"-x-c"},
   264  	{"-D", "@foo"},
   265  	{"-D", "-foo"},
   266  	{"-I", "@foo"},
   267  	{"-I", "-foo"},
   268  	{"-l", "@foo"},
   269  	{"-l", "-foo"},
   270  	{"-framework", "-Caffeine"},
   271  	{"-framework", "@Home"},
   272  	{"-Wl,-framework,-Caffeine"},
   273  	{"-Wl,-framework", "-Wl,@Home"},
   274  	{"-Wl,-framework", "@Home"},
   275  	{"-Wl,-framework,Chocolate,@Home"},
   276  	{"-Wl,--hash-style=foo"},
   277  	{"-x", "--c"},
   278  	{"-x", "@obj"},
   279  	{"-Wl,-rpath,@foo"},
   280  	{"-Wl,-R,foo,bar"},
   281  	{"-Wl,-R,@foo"},
   282  	{"-Wl,--just-symbols,@foo"},
   283  	{"../x.o"},
   284  	{"-Wl,-R,"},
   285  	{"-Wl,-O"},
   286  	{"-Wl,-e="},
   287  	{"-Wl,-e,"},
   288  	{"-Wl,-R,-flag"},
   289  	{"-Wl,--push-state,"},
   290  	{"-Wl,--push-state,@foo"},
   291  	{"-fplugin=./-Wl,--push-state,-R.so"},
   292  	{"./-Wl,--push-state,-R.c"},
   293  }
   294  
   295  func TestCheckLinkerFlags(t *testing.T) {
   296  	for _, f := range goodLinkerFlags {
   297  		if err := checkLinkerFlags("test", "test", f); err != nil {
   298  			t.Errorf("unexpected error for %q: %v", f, err)
   299  		}
   300  	}
   301  	for _, f := range badLinkerFlags {
   302  		if err := checkLinkerFlags("test", "test", f); err == nil {
   303  			t.Errorf("missing error for %q", f)
   304  		}
   305  	}
   306  }
   307  
   308  func TestCheckFlagAllowDisallow(t *testing.T) {
   309  	if err := checkCompilerFlags("TEST", "test", []string{"-disallow"}); err == nil {
   310  		t.Fatalf("missing error for -disallow")
   311  	}
   312  	os.Setenv("CGO_TEST_ALLOW", "-disallo")
   313  	if err := checkCompilerFlags("TEST", "test", []string{"-disallow"}); err == nil {
   314  		t.Fatalf("missing error for -disallow with CGO_TEST_ALLOW=-disallo")
   315  	}
   316  	os.Setenv("CGO_TEST_ALLOW", "-disallow")
   317  	if err := checkCompilerFlags("TEST", "test", []string{"-disallow"}); err != nil {
   318  		t.Fatalf("unexpected error for -disallow with CGO_TEST_ALLOW=-disallow: %v", err)
   319  	}
   320  	os.Unsetenv("CGO_TEST_ALLOW")
   321  
   322  	if err := checkCompilerFlags("TEST", "test", []string{"-Wall"}); err != nil {
   323  		t.Fatalf("unexpected error for -Wall: %v", err)
   324  	}
   325  	os.Setenv("CGO_TEST_DISALLOW", "-Wall")
   326  	if err := checkCompilerFlags("TEST", "test", []string{"-Wall"}); err == nil {
   327  		t.Fatalf("missing error for -Wall with CGO_TEST_DISALLOW=-Wall")
   328  	}
   329  	os.Setenv("CGO_TEST_ALLOW", "-Wall") // disallow wins
   330  	if err := checkCompilerFlags("TEST", "test", []string{"-Wall"}); err == nil {
   331  		t.Fatalf("missing error for -Wall with CGO_TEST_DISALLOW=-Wall and CGO_TEST_ALLOW=-Wall")
   332  	}
   333  
   334  	os.Setenv("CGO_TEST_ALLOW", "-fplugin.*")
   335  	os.Setenv("CGO_TEST_DISALLOW", "-fplugin=lint.so")
   336  	if err := checkCompilerFlags("TEST", "test", []string{"-fplugin=faster.so"}); err != nil {
   337  		t.Fatalf("unexpected error for -fplugin=faster.so: %v", err)
   338  	}
   339  	if err := checkCompilerFlags("TEST", "test", []string{"-fplugin=lint.so"}); err == nil {
   340  		t.Fatalf("missing error for -fplugin=lint.so: %v", err)
   341  	}
   342  }
   343  
   344  func TestCheckCompilerFlagsForInternalLink(t *testing.T) {
   345  	// Any "bad" compiler flag should trigger external linking.
   346  	for _, f := range badCompilerFlags {
   347  		if err := checkCompilerFlagsForInternalLink("test", "test", f); err == nil {
   348  			t.Errorf("missing error for %q", f)
   349  		}
   350  	}
   351  
   352  	// All "good" compiler flags should not trigger external linking,
   353  	// except for anything that begins with "-flto".
   354  	for _, f := range goodCompilerFlags {
   355  		foundLTO := false
   356  		for _, s := range f {
   357  			if strings.Contains(s, "-flto") {
   358  				foundLTO = true
   359  			}
   360  		}
   361  		if err := checkCompilerFlagsForInternalLink("test", "test", f); err != nil {
   362  			// expect error for -flto
   363  			if !foundLTO {
   364  				t.Errorf("unexpected error for %q: %v", f, err)
   365  			}
   366  		} else {
   367  			// expect no error for everything else
   368  			if foundLTO {
   369  				t.Errorf("missing error for %q: %v", f, err)
   370  			}
   371  		}
   372  	}
   373  }
   374  

View as plain text