diff --git a/cgi.go b/cgi.go index b41638762..6eba21549 100644 --- a/cgi.go +++ b/cgi.go @@ -9,6 +9,7 @@ import ( "net/http" "path/filepath" "strings" + "unsafe" ) var knownServerKeys = map[string]struct{}{ @@ -62,56 +63,56 @@ func addKnownVariablesToServer(thread *phpThread, request *http.Request, fc *Fra ra, raOK := fc.env["REMOTE_ADDR\x00"] if raOK { - registerTrustedVar(keys["REMOTE_ADDR\x00"], ra, trackVarsArray, thread) + registerTrustedVar(keys["REMOTE_ADDR\x00"], ra, trackVarsArray) } else { - registerTrustedVar(keys["REMOTE_ADDR\x00"], ip, trackVarsArray, thread) + registerTrustedVar(keys["REMOTE_ADDR\x00"], ip, trackVarsArray) } if rh, ok := fc.env["REMOTE_HOST\x00"]; ok { - registerTrustedVar(keys["REMOTE_HOST\x00"], rh, trackVarsArray, thread) // For speed, remote host lookups disabled + registerTrustedVar(keys["REMOTE_HOST\x00"], rh, trackVarsArray) // For speed, remote host lookups disabled } else { if raOK { - registerTrustedVar(keys["REMOTE_HOST\x00"], ra, trackVarsArray, thread) + registerTrustedVar(keys["REMOTE_HOST\x00"], ra, trackVarsArray) } else { - registerTrustedVar(keys["REMOTE_HOST\x00"], ip, trackVarsArray, thread) + registerTrustedVar(keys["REMOTE_HOST\x00"], ip, trackVarsArray) } } - registerTrustedVar(keys["REMOTE_PORT\x00"], port, trackVarsArray, thread) - registerTrustedVar(keys["DOCUMENT_ROOT\x00"], fc.documentRoot, trackVarsArray, thread) - registerTrustedVar(keys["PATH_INFO\x00"], fc.pathInfo, trackVarsArray, thread) - registerTrustedVar(keys["PHP_SELF\x00"], request.URL.Path, trackVarsArray, thread) - registerTrustedVar(keys["DOCUMENT_URI\x00"], fc.docURI, trackVarsArray, thread) - registerTrustedVar(keys["SCRIPT_FILENAME\x00"], fc.scriptFilename, trackVarsArray, thread) - registerTrustedVar(keys["SCRIPT_NAME\x00"], fc.scriptName, trackVarsArray, thread) + registerTrustedVar(keys["REMOTE_PORT\x00"], port, trackVarsArray) + registerTrustedVar(keys["DOCUMENT_ROOT\x00"], fc.documentRoot, trackVarsArray) + registerTrustedVar(keys["PATH_INFO\x00"], fc.pathInfo, trackVarsArray) + registerTrustedVar(keys["PHP_SELF\x00"], request.URL.Path, trackVarsArray) + registerTrustedVar(keys["DOCUMENT_URI\x00"], fc.docURI, trackVarsArray) + registerTrustedVar(keys["SCRIPT_FILENAME\x00"], fc.scriptFilename, trackVarsArray) + registerTrustedVar(keys["SCRIPT_NAME\x00"], fc.scriptName, trackVarsArray) var rs string if request.TLS == nil { rs = "http" - registerTrustedVar(keys["HTTPS\x00"], "", trackVarsArray, thread) - registerTrustedVar(keys["SSL_PROTOCOL\x00"], "", trackVarsArray, thread) + registerTrustedVar(keys["HTTPS\x00"], "", trackVarsArray) + registerTrustedVar(keys["SSL_PROTOCOL\x00"], "", trackVarsArray) } else { rs = "https" if h, ok := fc.env["HTTPS\x00"]; ok { - registerTrustedVar(keys["HTTPS\x00"], h, trackVarsArray, thread) + registerTrustedVar(keys["HTTPS\x00"], h, trackVarsArray) } else { - registerTrustedVar(keys["HTTPS\x00"], "on", trackVarsArray, thread) + registerTrustedVar(keys["HTTPS\x00"], "on", trackVarsArray) } // and pass the protocol details in a manner compatible with apache's mod_ssl // (which is why these have an SSL_ prefix and not TLS_). if pr, ok := fc.env["SSL_PROTOCOL\x00"]; ok { - registerTrustedVar(keys["SSL_PROTOCOL\x00"], pr, trackVarsArray, thread) + registerTrustedVar(keys["SSL_PROTOCOL\x00"], pr, trackVarsArray) } else { if v, ok := tlsProtocolStrings[request.TLS.Version]; ok { - registerTrustedVar(keys["SSL_PROTOCOL\x00"], v, trackVarsArray, thread) + registerTrustedVar(keys["SSL_PROTOCOL\x00"], v, trackVarsArray) } else { - registerTrustedVar(keys["SSL_PROTOCOL\x00"], "", trackVarsArray, thread) + registerTrustedVar(keys["SSL_PROTOCOL\x00"], "", trackVarsArray) } } } - registerTrustedVar(keys["REQUEST_SCHEME\x00"], rs, trackVarsArray, thread) + registerTrustedVar(keys["REQUEST_SCHEME\x00"], rs, trackVarsArray) reqHost, reqPort, _ := net.SplitHostPort(request.Host) if reqHost == "" { @@ -132,11 +133,11 @@ func addKnownVariablesToServer(thread *phpThread, request *http.Request, fc *Fra } } - registerTrustedVar(keys["SERVER_NAME\x00"], reqHost, trackVarsArray, thread) + registerTrustedVar(keys["SERVER_NAME\x00"], reqHost, trackVarsArray) if reqPort != "" { - registerTrustedVar(keys["SERVER_PORT\x00"], reqPort, trackVarsArray, thread) + registerTrustedVar(keys["SERVER_PORT\x00"], reqPort, trackVarsArray) } else { - registerTrustedVar(keys["SERVER_PORT\x00"], "", trackVarsArray, thread) + registerTrustedVar(keys["SERVER_PORT\x00"], "", trackVarsArray) } // Variables defined in CGI 1.1 spec @@ -144,15 +145,15 @@ func addKnownVariablesToServer(thread *phpThread, request *http.Request, fc *Fra // the parent environment from interfering. // These values can not be overridden - registerTrustedVar(keys["CONTENT_LENGTH\x00"], request.Header.Get("Content-Length"), trackVarsArray, thread) - registerTrustedVar(keys["GATEWAY_INTERFACE\x00"], "CGI/1.1", trackVarsArray, thread) - registerTrustedVar(keys["SERVER_PROTOCOL\x00"], request.Proto, trackVarsArray, thread) - registerTrustedVar(keys["SERVER_SOFTWARE\x00"], "FrankenPHP", trackVarsArray, thread) - registerTrustedVar(keys["HTTP_HOST\x00"], request.Host, trackVarsArray, thread) // added here, since not always part of headers + registerTrustedVar(keys["CONTENT_LENGTH\x00"], request.Header.Get("Content-Length"), trackVarsArray) + registerTrustedVar(keys["GATEWAY_INTERFACE\x00"], "CGI/1.1", trackVarsArray) + registerTrustedVar(keys["SERVER_PROTOCOL\x00"], request.Proto, trackVarsArray) + registerTrustedVar(keys["SERVER_SOFTWARE\x00"], "FrankenPHP", trackVarsArray) + registerTrustedVar(keys["HTTP_HOST\x00"], request.Host, trackVarsArray) // added here, since not always part of headers // These values are always empty but must be defined: - registerTrustedVar(keys["AUTH_TYPE\x00"], "", trackVarsArray, thread) - registerTrustedVar(keys["REMOTE_IDENT\x00"], "", trackVarsArray, thread) + registerTrustedVar(keys["AUTH_TYPE\x00"], "", trackVarsArray) + registerTrustedVar(keys["REMOTE_IDENT\x00"], "", trackVarsArray) // These values are already present in the SG(request_info), so we'll register them from there C.frankenphp_register_variables_from_request_info( @@ -166,11 +167,11 @@ func addKnownVariablesToServer(thread *phpThread, request *http.Request, fc *Fra ) } -func registerTrustedVar(key *C.zend_string, value string, trackVarsArray *C.zval, thread *phpThread) { - C.frankenphp_register_trusted_var(key, thread.pinString(value), C.int(len(value)), trackVarsArray) +func registerTrustedVar(key *C.zend_string, value string, trackVarsArray *C.zval) { + C.frankenphp_register_trusted_var(key, toUnsafeChar(value), C.int(len(value)), trackVarsArray) } -func addHeadersToServer(thread *phpThread, request *http.Request, fc *FrankenPHPContext, trackVarsArray *C.zval) { +func addHeadersToServer(request *http.Request, fc *FrankenPHPContext, trackVarsArray *C.zval) { for field, val := range request.Header { k, ok := headerKeyCache.Get(field) if !ok { @@ -183,13 +184,13 @@ func addHeadersToServer(thread *phpThread, request *http.Request, fc *FrankenPHP } v := strings.Join(val, ", ") - C.frankenphp_register_variable_safe(thread.pinString(k), thread.pinString(v), C.size_t(len(v)), trackVarsArray) + C.frankenphp_register_variable_safe(toUnsafeChar(k), toUnsafeChar(v), C.size_t(len(v)), trackVarsArray) } } -func addPreparedEnvToServer(thread *phpThread, fc *FrankenPHPContext, trackVarsArray *C.zval) { +func addPreparedEnvToServer(fc *FrankenPHPContext, trackVarsArray *C.zval) { for k, v := range fc.env { - C.frankenphp_register_variable_safe(thread.pinString(k), thread.pinString(v), C.size_t(len(v)), trackVarsArray) + C.frankenphp_register_variable_safe(toUnsafeChar(k), toUnsafeChar(v), C.size_t(len(v)), trackVarsArray) } fc.env = nil } @@ -201,7 +202,7 @@ func getKnownVariableKeys(thread *phpThread) map[string]*C.zend_string { threadServerKeys := make(map[string]*C.zend_string) for k := range knownServerKeys { keyWithoutNull := strings.Replace(k, "\x00", "", -1) - threadServerKeys[k] = C.frankenphp_init_persistent_string(thread.pinString(keyWithoutNull), C.size_t(len(keyWithoutNull))) + threadServerKeys[k] = C.frankenphp_init_persistent_string(toUnsafeChar(keyWithoutNull), C.size_t(len(keyWithoutNull))) } thread.knownVariableKeys = threadServerKeys return threadServerKeys @@ -214,8 +215,8 @@ func go_register_variables(threadIndex C.uintptr_t, trackVarsArray *C.zval) { fc := r.Context().Value(contextKey).(*FrankenPHPContext) addKnownVariablesToServer(thread, r, fc, trackVarsArray) - addHeadersToServer(thread, r, fc, trackVarsArray) - addPreparedEnvToServer(thread, fc, trackVarsArray) + addHeadersToServer(r, fc, trackVarsArray) + addPreparedEnvToServer(fc, trackVarsArray) } //export go_frankenphp_release_known_variable_keys @@ -289,3 +290,8 @@ func sanitizedPathJoin(root, reqPath string) string { } const separator = string(filepath.Separator) + +func toUnsafeChar(s string) *C.char { + sData := unsafe.StringData(s) + return (*C.char)(unsafe.Pointer(sData)) +}