From d149f14b6b9282ac17ca3c4000c3033ee3eaeae8 Mon Sep 17 00:00:00 2001 From: Pavel Forkert Date: Tue, 13 Dec 2016 10:49:37 +0200 Subject: [PATCH] Properly lock jws.nonces (#319) Before read access to `nonces` field in jws structure (in `Nonces` method) was not synchronized and we were still able to get `slice bounds out of range` panic when trying to "pop" value in `Nonces` method. The race can be actually observed by running `Nonce` method multiple times in separate goroutines with th precondition is `len(jws.nonces) == 1`. --- acme/jws.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/acme/jws.go b/acme/jws.go index f70513e3..80296081 100644 --- a/acme/jws.go +++ b/acme/jws.go @@ -44,6 +44,8 @@ func (j *jws) post(url string, content []byte) (*http.Response, error) { return nil, err } + j.Lock() + defer j.Unlock() j.getNonceFromResponse(resp) return resp, err @@ -77,8 +79,6 @@ func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) { } func (j *jws) getNonceFromResponse(resp *http.Response) error { - j.Lock() - defer j.Unlock() nonce := resp.Header.Get("Replay-Nonce") if nonce == "" { return fmt.Errorf("Server did not respond with a proper nonce header.") @@ -98,6 +98,8 @@ func (j *jws) getNonce() error { } func (j *jws) Nonce() (string, error) { + j.Lock() + defer j.Unlock() nonce := "" if len(j.nonces) == 0 { err := j.getNonce() @@ -108,8 +110,6 @@ func (j *jws) Nonce() (string, error) { if len(j.nonces) == 0 { return "", fmt.Errorf("Can't get nonce") } - j.Lock() - defer j.Unlock() nonce, j.nonces = j.nonces[len(j.nonces)-1], j.nonces[:len(j.nonces)-1] return nonce, nil }