Go http panic serving - http

I got this panic:
C:\Users\loow\Desktop\USBWebserver v8.5\duplicate_submissions>go run server.go
2015/10/23 13:00:39 http: panic serving [::1]:63867: runtime error: invalid memo
ry address or nil pointer dereference
goroutine 5 [running]:
net/http.(*conn).serve.func1(0xc0820a1810, 0x3b55b8, 0xc082024040)
c:/go/src/net/http/server.go:1287 +0xbc
main.login(0x2990058, 0xc0820d4000, 0xc0820be1c0)
C:/Users/loow/Desktop/USBWebserver v8.5/duplicate_submissions/server.go:
27 +0x5a5
net/http.HandlerFunc.ServeHTTP(0x8326a8, 0x2990058, 0xc0820d4000, 0xc0820be1c0)
c:/go/src/net/http/server.go:1422 +0x41
net/http.(*ServeMux).ServeHTTP(0xc082062360, 0x2990058, 0xc0820d4000, 0xc0820be1
c0)
c:/go/src/net/http/server.go:1699 +0x184
net/http.serverHandler.ServeHTTP(0xc08200c360, 0x2990058, 0xc0820d4000, 0xc0820b
e1c0)
c:/go/src/net/http/server.go:1862 +0x1a5
net/http.(*conn).serve(0xc0820a1810)
c:/go/src/net/http/server.go:1361 +0xbf5
created by net/http.(*Server).Serve
c:/go/src/net/http/server.go:1910 +0x3fd
2015/10/23 13:00:39 http: panic serving [::1]:63868: runtime error: invalid memo
ry address or nil pointer dereference
goroutine 33 [running]:
net/http.(*conn).serve.func1(0xc082114000, 0x3b55b8, 0xc082112000)
c:/go/src/net/http/server.go:1287 +0xbc
main.login(0x2990058, 0xc0821140b0, 0xc0821200e0)
C:/Users/loow/Desktop/USBWebserver v8.5/duplicate_submissions/server.go:
27 +0x5a5
net/http.HandlerFunc.ServeHTTP(0x8326a8, 0x2990058, 0xc0821140b0, 0xc0821200e0)
c:/go/src/net/http/server.go:1422 +0x41
net/http.(*ServeMux).ServeHTTP(0xc082062360, 0x2990058, 0xc0821140b0, 0xc0821200
e0)
c:/go/src/net/http/server.go:1699 +0x184
net/http.serverHandler.ServeHTTP(0xc08200c360, 0x2990058, 0xc0821140b0, 0xc08212
00e0)
c:/go/src/net/http/server.go:1862 +0x1a5
net/http.(*conn).serve(0xc082114000)
c:/go/src/net/http/server.go:1361 +0xbf5
created by net/http.(*Server).Serve
c:/go/src/net/http/server.go:1910 +0x3fd
exit status 2
Whit this code:
package main
import(
"fmt"
"net/http"
"html/template"
"log"
"time"
"crypto/md5"
"io"
"strconv"
)
func loginForm(w http.ResponseWriter, r *http.Request){
}
func login(w http.ResponseWriter, r *http.Request){
fmt.Println(r.Method)
if r.Method == "GET"{
cruTime := time.Now().Unix()
h := md5.New()
io.WriteString(h,strconv.FormatInt(cruTime,10))
token := fmt.Sprintf("%x", h.Sum(nil))
fmt.Println(token)
t, err := template.ParseFiles("templates/index.gtpl")
fmt.Println(err.Error())
err = t.Execute(w, token)
fmt.Println(err.Error())
} else{
r.ParseForm()
token := r.Form.Get("token")
if token != ""{
fmt.Println(token)
} else{
fmt.Println("There is no token")
}
fmt.Println("username length: ", len(r.Form["username"][0]))
fmt.Println("username: ", template.HTMLEscapeString(r.Form.Get("username")))
fmt.Println("password: ", template.HTMLEscapeString(r.Form.Get("password")))
template.HTMLEscape(w, []byte(r.Form.Get("username")))
}
}
func main(){
http.HandleFunc("/", loginForm)
http.HandleFunc("/login", login)
err := http.ListenAndServe(":9090", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
I cant fix it, I tried everything what I found in the stackoverflow. What is the problem? There is no error, and the panic said that the problem in t, err := template.ParseFiles("templates/index.gtpl")..
There is the template file:
<input type="checkbox" name="interest" value="football">Football
<input type="checkbox" name="interest" value="basketball">Basketball
<input type="checkbox" name="interest" value="tennis">Tennis
Username: <input type="text" name="username">
Password: <input type="password" name="password">
<input type="hidden" name="token" value="{{.}}">
<input type="submit" value="Login">

The panic stacktrace gives you this info :
2015/10/23 13:00:39 http: panic serving [::1]:63868: runtime error: invalid memory address or nil pointer dereference goroutine 33 [running]:
It means you're trying to access something that does not exist (nil pointer).
Then the first line that comes from your file is this one :
v8.5/duplicate_submissions/server.go:27
Which is there :
26: t, err := template.ParseFiles("templates/index.gtpl")
27: fmt.Println(err.Error())
28: err = t.Execute(w, token)
It means err is nil.
Solution
If you get the error, you cannot continue the process. That's the reason why you cannot just print out the error. In order to stop gracefully the process, you need to return an HTTP status code and then return. For the case above, you can return a code 500 (internal server error).
t, err := template.ParseFiles("templates/index.gtpl")
if err != nil {
fmt.Println(err) // Ugly debug output
w.WriteHeader(http.StatusInternalServerError) // Proper HTTP response
return
}
That has to be done for a template.ParseFiles and t.Execute too.
By the way, that is called the "comma ok" pattern

Related

Downloading with POST function a file with golang gingonic

this is my function:
func downloadDoc(c *gin.Context) {
var fileToSearch service.ApDocumentsMedia
if err := c.BindJSON(&fileToSearch); err != nil {
c.AbortWithStatusJSON(http.StatusUnprocessableEntity, "is not binding!")
return
}
var file service.ApDocumentsMedia
if err := db.Where("uuid = ?", fileToSearch.Uuid).First(&file); err.RowsAffected <= 0 {
c.IndentedJSON(http.StatusNotFound, "Document not founded!")
return
}
c.Header("Content-Description", "File Transfer")
c.Header("Content-Transfer-Encoding", "binary")
c.Header("Content-Disposition", "attachment; filename="+strconv.Quote(file.Path))
c.Header("Content-Type", "application/octet-stream; charset=utf-8")
c.File(file.Path)
c.IndentedJSON(http.StatusOK, "File inviato")
}
but then when I go to call the function (using the frontend) it gives me this error:
http: panic serving 127.0.0.1:50138: http: wrote more than the declared Content-Length
goroutine 24 [running]:
net/http.(*conn).serve.func1()
/home/stage01/sdk/go1.18.3/src/net/http/server.go:1825 +0xbf
panic({0xac00e0, 0xc000020ab0})
/home/stage01/sdk/go1.18.3/src/runtime/panic.go:844 +0x258
github.com/gin-gonic/gin.(*Context).Render(0xc0000b2900, 0xc8, {0xc8d318, 0xc000245950})
/home/stage01/go/pkg/mod/github.com/gin-gonic/gin#v1.8.1/context.go:911 +0x112
github.com/gin-gonic/gin.(*Context).IndentedJSON(...)
/home/stage01/go/pkg/mod/github.com/gin-gonic/gin#v1.8.1/context.go:928
main.downloadDoc(0xc0000b2900)
/home/stage01/Scrivania/minia_git/docmanagement-alexperrucci/api/main.go:74 +0x36d
github.com/gin-gonic/gin.(*Context).Next(...)
/home/stage01/go/pkg/mod/github.com/gin-gonic/gin#v1.8.1/context.go:173
github.com/gin-gonic/gin.(*Engine).handleHTTPRequest(0xc000449520, 0xc0000b2900)
/home/stage01/go/pkg/mod/github.com/gin-gonic/gin#v1.8.1/gin.go:616 +0x671
github.com/gin-gonic/gin.(*Engine).ServeHTTP(0xc000449520, {0xc8f430?, 0xc0004ee620}, 0xc0000b2700)
/home/stage01/go/pkg/mod/github.com/gin-gonic/gin#v1.8.1/gin.go:572 +0x1dd
net/http.serverHandler.ServeHTTP({0xc8c968?}, {0xc8f430, 0xc0004ee620}, 0xc0000b2700)
/home/stage01/sdk/go1.18.3/src/net/http/server.go:2916 +0x43b
net/http.(*conn).serve(0xc00054b360, {0xc8ff38, 0xc00028f290})
/home/stage01/sdk/go1.18.3/src/net/http/server.go:1966 +0x5d7
created by net/http.(*Server).Serve
/home/stage01/sdk/go1.18.3/src/net/http/server.go:3071 +0x4db
This problem is given to me when once I click on the button that makes the post call (with the uuid of the file) it gives me this error and I don't understand why, would anyone know how to help me?

Why does printing the error from net.Interfaces crash my program?

I'm trying to get a list of system interfaces on my machine, I'm using the net package, which is defined here.
I have this tiny little snippet of code, which crashes when trying to print out the error, and I can't figure out why the error is sigsev'ing on me. It's supposed to return an error, or nil right?
I've ran this code with sudo, root and under a regular user account thinking it might be a permissions thing for the network interface, but it persists amongst all user levels.
package main
import (
"net"
"fmt"
)
func main() {
var err error
var interfaces []net.Interface
var ifString []string
interfaces, err = net.Interfaces()
fmt.Printf("%v",interfaces)
if err != nil {
for _, v := range interfaces {
ifString = append(ifString, v.Name)
}
} else {
fmt.Printf(err.Error())
ifString = append(ifString, "unable to get system interfaces")
}
}
Program output is as follows when running go build and executing it:
[{1 65536 lo up|loopback} {2 1500 eno1 b8:cc:3c:8e:d4:d3 up|broadcast|multicast} {9 1500 tun0 up|pointtopoint|multicast}]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x4a5269]
goroutine 1 [running]:
main.main()
/home/andrew/interface/borked.go:20 +0x269
You are receiving a nil pointer dereference because that's exactly what you're doing.
Given the following if statement in your code:
if err != nil {
for _, v := range interfaces {
ifString = append(ifString, v.Name)
}
} else {
fmt.Printf(err.Error())
...
}
The else is reached when err is nil. Yet you are attempting to access a field in it: err.Error(), dereferencing a nil pointer.
You need to invert your if statement, it's the wrong way around.

panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation firebase.google.com/go.(*App).Database

I am trying to implement firebase with golang and have been successful so far. My code works fine when I run it locally and I can see the data in the firebase database. But when I deploy the code on GKE(GCP), it doesn't work and throws the following error. I am a beginner in goalng . Please help me fix this. What am I doing wrong? Please comment if you need more information
panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0xd9ed72] goroutine 13154 [running]: firebase.google.com/go.(*App).Database(0x0, 0x12586c0, 0xc0000a6010, 0xc00153db98, 0x1, 0x1) /go/pkg/mod/firebase.google.com/go#v3.4.0+incompatible/firebase.go:85 +0x22 tracer.(*Storage).Publish(0xc0007140a0, 0x12586c0, 0xc0000a6010, 0xc0008442e0, 0x20, 0xc0016accf0, 0x10, 0xc0015a5ef0, 0xc0019c6c40, 0x3, ...) /project/pkg/tracer/storage.go:116 +0x642
tracer.(*Storage).Publish-fm(0x12586c0, 0xc0000a6010, 0xc0008442e0, 0x20, 0xc0016accf0, 0x10, 0xc0015a5ef0, 0xc0019c6c40, 0x3, 0x4, ...) /project/main.go:540 +0xd1 tracer.(*Factory).publishFunc.func1(0xc0007140c0, 0xc0008442e0, 0x20, 0xc0016accf0, 0x10, 0xc0015a5ef0, 0xc0019c6c40, 0x3, 0x4, 0xc0008442e0, ...) /project/pkg/tracer/bag.go:255 +0x102 created by tracer.(*Factory).publishFunc /project/pkg/tracer/bag.go:253 +0xf8
main.go
opt := option.WithCredentialsFile("./firebase.json")
conf := &firebase.Config{DatabaseURL: "https://xxx.xx.xx.com//"}
app, err := firebase.NewApp(context.Background(), conf, opt)
firego, err := app.Database(context.Background())
if err != nil{
log.Fatal(err)
}
ref := firego.NewRef("xxx-" + "dev")
usersRef := ref.Child(t)
k := make(map[string]string)
k["x_callID"] = content.ID
k["end_time"] = t2
k["user_id"] = content.UserID
err = usersRef.Set(context.Background(), k)
if err != nil {
log.Fatalln("Error setting value:", err)
}
Never ignore any error. Print error of this line. This might be the root cause.
app, err := firebase.NewApp(context.Background(), conf, opt)
If firebase.NewApp() fail, it will return error and app will be nil. As you are trying to access app.Database() on next line, you will get that panic since app is nil.

http.Server Serve method hangs when calling Shutdown immediately

I have an issue with Go's http.Server, which I'm embedding in a struct that is supposed to control the server startup and shutdown. The struct looks like this:
type HTTPListen struct {
Consumers []pipeline.Consumer
Cfg HTTPListenConfig
Srv *http.Server
Logger log.Logger
wg *sync.WaitGroup
mu sync.Mutex
state State
}
The issue is that in my test code, I call my struct's Start() method (which in turn runs the Serve() method on the http.Server), check a few vars, and then call Stop(), whitch Shutdown()s the server and then waits for the http.Server to exit (return err from the Serve() method).
Now, for some reason, the Serve() method seems to just hang on the WaitGroup.Wait(), when I try to shutdown the server immediately after starting. When I add a short pause (tried 100ms), or when running the tests with the race detector, It works just fine.
Not sure if it matters, but there are no incoming requests between calling Serve() and Shutdown().
EDIT: link to a playground minimal example. If you comment out the time.Sleep call, the program hangs.
Here is the relevant code for the two methods:
func (h *HTTPListen) Start() error {
h.Logger.Log("msg", "starting HTTPListen input")
addr := h.Cfg.ListenAddr
ln, err := net.Listen("tcp", addr)
if err != nil {
h.Logger.Log("msg", "failed to create listener on tcp/"+addr+": "+err.Error())
h.setState(StateFailed)
return err
}
h.wg.Add(1)
go func() {
defer h.wg.Done()
err := h.Srv.Serve(ln)
h.Logger.Log("msg", "HTTP server stopped: "+err.Error())
}()
h.setState(StateStarted)
h.Logger.Log("msg", "HTTPListen input started")
return nil
}
Stop method:
func (h *HTTPListen) Stop() error {
h.Logger.Log("msg", "stopping HTTPListen input")
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
if err := h.Srv.Shutdown(ctx); err != nil {
h.Logger.Log("msg", "HTTP server shutdown deadline expired")
}
h.wg.Wait()
h.setState(StateStopped)
h.Logger.Log("msg", "HTTPListen input stopped")
return nil
}
Log output:
kwz#cyclone ~/s/stblogd> go test -v ./pkg/pipeline/input/ -run TestHTTPListen_StartStop
=== RUN TestHTTPListen_StartStop
msg="starting HTTPListen input"
msg="HTTPListen input started"
msg="stopping HTTPListen input"
... hangs indefinitely
Log output when running tests with the race detector:
kwz#cyclone ~/s/stblogd> go test -race -v ./pkg/pipeline/input/ -run TestHTTPListen_StartStop
=== RUN TestHTTPListen_StartStop
msg="starting HTTPListen input"
msg="HTTPListen input started"
msg="stopping HTTPListen input"
msg="HTTP server stopped: http: Server closed"
msg="HTTPListen input stopped"
--- PASS: TestHTTPListen_StartStop (0.00s)
PASS
ok stblogd/pkg/pipeline/input 1.007s
I'm tempted to just slap a short delay on the test and call it a day, but I would like to know why it behaves like this.
This is a known issue, see this thread:
https://github.com/golang/go/issues/20239
Hopefully they will fix it soon but for now it sounds like adding a short delay in your test is the simplest solution - it probably doesn't come up in real world use much because you won't trigger a shutdown so soon after starting.

Why does the Go function EncryptOAEP in the crypto/rsa library require a random io.Reader?

I'm writing a file server that encrypts data on the client side, sends the data over TCP, and decrypts it on server side using asymmetric RSA-OAEP encryption. There are two main functions I have been trying to use, which take the following arguments per the documentation:
EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err error)
DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error)
Each requires a random io.Reader, and the test file uses rand.Reader from crypto/rand. However, whenever I encrypt a message with rand.Reader on the client side, the message never is decrypted properly on the server side which has a separate instance of rand.Reader.
What is the purpose of the random io.Reader?
How can I ensure that the encrypted message is transferred and decrypted properly by the server? Would I also need to transfer some information about the rand.Reader used by the client as well to the server for the message to be properly decrypted?
Using rsa_test.go as a base I managed to create a small end to end decryption program.
From the informations you provided is hard to tell where the error is, but I hope reading this program you can find the bug yourself. Probably you don't need to provide a Reader in the DecryptOAEP.
http://play.golang.org/p/7VVCHJOB7R
package main
import (
"bytes"
"crypto/rsa"
"crypto/sha1"
"log"
"math/big"
)
func main() {
sha1 := sha1.New()
n := new(big.Int)
d := new(big.Int)
rsa_modulus := "a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb"
rsa_d := "53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1"
n.SetString(rsa_modulus, 16)
d.SetString(rsa_d, 16)
public := rsa.PublicKey{n, 65537}
d.SetString(rsa_d, 16)
private := new(rsa.PrivateKey)
private.PublicKey = public
private.D = d
seed := []byte{0x18, 0xb7, 0x76, 0xea, 0x21, 0x06, 0x9d, 0x69,
0x77, 0x6a, 0x33, 0xe9, 0x6b, 0xad, 0x48, 0xe1, 0xdd,
0xa0, 0xa5, 0xef,
}
randomSource := bytes.NewReader(seed)
in := []byte("Hello World")
encrypted, err := rsa.EncryptOAEP(sha1, randomSource, &public, in, nil)
if err != nil {
log.Println("error: %s", err)
}
plain, err := rsa.DecryptOAEP(sha1, nil, private, encrypted, nil)
if err != nil {
log.Println("error: %s", err)
}
log.Println(string(plain))
}

Resources