Skip to content

Instantly share code, notes, and snippets.

@suzuki-shunsuke
Created November 15, 2023 06:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save suzuki-shunsuke/912e1da11ee3ebd38d6d9cf53d66b31d to your computer and use it in GitHub Desktop.
Save suzuki-shunsuke/912e1da11ee3ebd38d6d9cf53d66b31d to your computer and use it in GitHub Desktop.
When I tried to download AWS CLI and calculate the checksum with Go, I faced a weird issue. https://github.com/aquaproj/aqua/issues/2467
package main
import (
"errors"
"fmt"
"io"
"log"
"net/http"
"github.com/codingsince1985/checksum"
)
func main() {
if err := core(); err != nil {
log.Fatal(err)
}
}
func core() error {
rc, err := download("http://awscli.amazonaws.com/AWSCLIV2-2.13.35.pkg")
if err != nil {
return err
}
defer rc.Close()
s, err := checksum.SHA256sumReader(rc)
if err != nil {
return err
}
fmt.Println(s) // The value is changed every time
return nil
}
func download(u string) (io.ReadCloser, error) {
client := http.DefaultClient
req, err := http.NewRequest(http.MethodGet, u, nil)
if err != nil {
return nil, fmt.Errorf("create a http request: %w", err)
}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("send http request: %w", err)
}
if resp.StatusCode >= http.StatusBadRequest {
return resp.Body, errors.New("status code >= 400")
}
log.Println("status code:", resp.StatusCode) // 200
return resp.Body, nil
}
package main
import (
"errors"
"fmt"
"io"
"log"
"net/http"
"os"
"github.com/codingsince1985/checksum"
)
func main() {
if err := core(); err != nil {
log.Fatal(err)
}
}
func core() error {
rc, err := download("http://awscli.amazonaws.com/AWSCLIV2-2.13.35.pkg")
if err != nil {
return err
}
defer rc.Close()
f, err := os.CreateTemp("", "")
if err != nil {
return err
}
defer func() {
f.Close()
if err := os.Remove(f.Name()); err != nil {
log.Println(err)
}
}()
if _, err := io.Copy(f, rc); err != nil {
return err
}
s, err := checksum.SHA256sumReader(f)
if err != nil {
return err
}
fmt.Println(s) // The value is unchanged but wrong.
return nil
}
func download(u string) (io.ReadCloser, error) {
client := http.DefaultClient
req, err := http.NewRequest(http.MethodGet, u, nil)
if err != nil {
return nil, fmt.Errorf("create a http request: %w", err)
}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("send http request: %w", err)
}
if resp.StatusCode >= http.StatusBadRequest {
return resp.Body, errors.New("status code >= 400")
}
log.Println("status code:", resp.StatusCode)
return resp.Body, nil
}
package main
import (
"errors"
"fmt"
"io"
"log"
"net/http"
"os"
"github.com/codingsince1985/checksum"
)
func main() {
if err := core(); err != nil {
log.Fatal(err)
}
}
func core() error {
path, err := downloadAndCopy()
if err != nil {
return err
}
defer func() {
if err := os.Remove(path); err != nil {
log.Println(err)
}
}()
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()
s, err := checksum.SHA256sumReader(f)
if err != nil {
return err
}
fmt.Println(s)
return nil
}
func downloadAndCopy() (string, error) {
rc, err := download("http://awscli.amazonaws.com/AWSCLIV2-2.13.35.pkg")
if err != nil {
return "", err
}
defer rc.Close()
f, err := os.CreateTemp("", "")
if err != nil {
return "", err
}
defer func() {
f.Close()
}()
if _, err := io.Copy(f, rc); err != nil {
return "", err
}
return f.Name(), nil
}
func download(u string) (io.ReadCloser, error) {
client := http.DefaultClient
req, err := http.NewRequest(http.MethodGet, u, nil)
if err != nil {
return nil, fmt.Errorf("create a http request: %w", err)
}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("send http request: %w", err)
}
if resp.StatusCode >= http.StatusBadRequest {
return resp.Body, errors.New("status code >= 400")
}
log.Println("status code:", resp.StatusCode)
return resp.Body, nil
}
@suzuki-shunsuke
Copy link
Author

suzuki-shunsuke commented Nov 15, 2023

bug1.go

The result is changed every time.

$ go run bug1.go
2023/11/15 15:20:47 status code: 200
6a6f6ea93ac898f8a42c1ad32a610ac20c699dce6f49dbc36160e9ad61040dfd

$ go run bug1.go
2023/11/15 15:20:50 status code: 200
6a28ce96226289451be891e58b3afacc320c4be12cd429dc694867b38c3bc8e8

bug2.go

The result is unchanged but is wrong.

$ go run bug2.go
2023/11/15 15:21:53 status code: 200
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

$ go run bug2.go
2023/11/15 15:21:55 status code: 200
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

good1.go

The result is correct

$ go run good1.go 
2023/11/15 15:22:52 status code: 200
36d16a6156150b3940cd7e750fbd7b9c529ee93c8e0eb594283f19a197de5c42

$ go run good1.go
2023/11/15 15:22:56 status code: 200
36d16a6156150b3940cd7e750fbd7b9c529ee93c8e0eb594283f19a197de5c42

Information

$ go version
go version go1.21.4 darwin/arm64

go.mod

module foo

go 1.21.4

require github.com/codingsince1985/checksum v1.3.0

require (
	golang.org/x/crypto v0.6.0 // indirect
	golang.org/x/sys v0.5.0 // indirect
)

I tried some URLs, but I couldn't reproduce the issue with URL other than the URL of AWS CLI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment