@@ -134,7 +134,50 @@ func BuildSSA(c *gin.Context) {
134134 c .JSON (http .StatusOK , out )
135135}
136136
137+ /*
138+ According to spec there are two cases we need to handle:
139+
140+ - Function declaration, in the form of 'func f() {...}' , see:
141+ https://golang.org/ref/spec#Function_declarations
142+
143+ - Function literal/anonymous function, in the form of
144+ 'myfunc := func() {...}' or 'go func() {...}', see:
145+ https://golang.org/ref/spec#Function_literals
146+
147+ As users can use some tricks like raw string to bypass our check, we
148+ only do check conservatively, which means it is mainly used for
149+ preventing misspell and wrong format.
150+
151+ All cases:
152+ // <i>,<j>,<k> means unique function index in the scope of outer function, see:
153+ https://github.com/golang/go/blob/84162b88324aa7993fe4a8580a2b65c6a7055f88/src/cmd/compile/internal/typecheck/func.go#L182
154+
155+ - func foo() // most common case
156+ - glob..func<i> // global function literal
157+ + glob..func<i>.<j>.<k>... // inner anonymous function
158+ - foo.func<i> // anonymous function inside function 'foo'
159+ + foo.func<i>.<j>.<k>...
160+ - (*T).foo() // method expression with explicit receiver, see
161+ https://golang.org/ref/spec#Method_expressions
162+
163+ Note that non-ascii letters are unsupported, as our intention is to dig
164+ into go ssa IR.
165+ */
137166func findSSAFunc (code , funcname string ) bool {
167+ // The dot character is not allowed to appear in function name.
168+ // See https://golang.org/ref/spec#Identifiers
169+ if strings .IndexByte (funcname , '.' ) != - 1 {
170+ if funcname [0 ] == '(' {
171+ methodReg := regexp .MustCompile (`^\([\w\*]+\)\.\w+$` )
172+ return methodReg .MatchString (funcname )
173+ } else if strings .HasPrefix (funcname , "glob" ) {
174+ globReg := regexp .MustCompile (`^glob\.\.func\d+(\.\d)*$` )
175+ return globReg .MatchString (funcname )
176+ } else {
177+ anonyReg := regexp .MustCompile (`^\w+\.func\d+(\.\d)*$` )
178+ return anonyReg .MatchString (funcname )
179+ }
180+ }
138181 // func Foo (
139182 re := regexp .MustCompile (fmt .Sprintf (`func[ \t]+%s[ \t]*\(` , funcname ))
140183 return re .FindString (code ) != ""
@@ -185,12 +228,23 @@ func initModules(path string) error {
185228}
186229
187230func buildSSA (funcname , gcflags , outf , buildf string , isTest bool ) error {
188- var cmd * exec.Cmd
231+ var (
232+ cmd * exec.Cmd
233+ buildDir string
234+ )
235+
236+ // Restrict the ssa.html target to the target ssa build folder.
237+ // See https://github.com/golang-design/ssaplayground/issues/9
238+ buildDir = filepath .Dir (buildf )
239+ outf = filepath .Base (outf )
240+ buildf = filepath .Base (buildf )
241+
189242 if ! isTest {
190243 cmd = exec .Command ("go" , "build" , "-mod=readonly" , fmt .Sprintf (`-gcflags=%s` , gcflags ), "-o" , outf , buildf )
191244 } else {
192245 cmd = exec .Command ("go" , "test" , "-mod=readonly" , fmt .Sprintf (`-gcflags=%s` , gcflags ), buildf )
193246 }
247+ cmd .Dir = buildDir
194248 cmd .Env = append (os .Environ (), fmt .Sprintf ("GOSSAFUNC=%s" , funcname ))
195249 cmd .Stderr = & bytes.Buffer {}
196250 err := cmd .Run ()
0 commit comments