Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Three reader.ReadLine() calls in a row will cause first read result being overwritten #42006

Closed
MewX opened this issue Oct 16, 2020 · 4 comments
Closed

Comments

@MewX
Copy link

@MewX MewX commented Oct 16, 2020

What version of Go are you using (go version)?

I tried 1.13 first, then I found 1.15.2 still had the problem.

$ go version
go version go1.15.2 linux/amd64

Does this issue reproduce with the latest release?

Yes!

What operating system and processor architecture are you using (go env)?

WSL 2.0 Ubuntu 20.04.

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/mewx/.cache/go-build"
GOENV="/home/mewx/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/mewx/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/mewx/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/lib/go-1.15"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go-1.15/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build022791119=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Minimal reproduciable code:

Minimal.go

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
)

func main() {
	ln := 1
	reader := bufio.NewReader(os.Stdin)
	for true {
		// Read first line and make a copy
		line1, _, err := reader.ReadLine()
		copyOfLine1 := make([]byte, len(line1))
		copy(copyOfLine1, line1)
		print(ln, line1)
		if err != nil {
			break
		}
		line2, _, _ := reader.ReadLine()
		print(ln+1, line2)

		// Problem here - after reading the second line, the line1 is modified??
		if bytes.Compare(line1, copyOfLine1) != 0 {
			fmt.Printf("NOT EQUAL - line1: %s; copy: %s\n", string(line1), string(copyOfLine1))
		}

		// Must read a 3rd line.
		// Removing this section will not produce the problem.
		line3, _, _ := reader.ReadLine()
		print(ln+2, line3)
		ln += 3
	}
}

func print(ln int, slice []byte) {
	fmt.Printf("%d: %s\n", ln, string(slice))
}

input.txt

See below:
input.txt

Commands to run

$ go run Minimal.go < input.txt > output.txt

What did you expect to see?

No lines with NOT EQUAL printed out.

What did you see instead?

NOT EQUAL is printed out, which indicated the first line has been modified somehow.

The output from my device:
output.txt

Note: sometimes it's the line2 or line3 being overwritten.

@davecheney
Copy link
Contributor

@davecheney davecheney commented Oct 16, 2020

@MewX thank you for raising this issue, before we can invesitigate you must correct the error handling in your program. Please make the following change;

  • after each call to reader.ReadLine() please immediately check the err value and exit the loop.

once you've done that, please update your code sample and reverify that the problem continues to occur.

Thank you

@MewX
Copy link
Author

@MewX MewX commented Oct 16, 2020

@davecheney

Modified the code to this:

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
)

func main() {
	ln := 1
	reader := bufio.NewReader(os.Stdin)
	for true {
		// Read first line and make a copy
		line1, _, err1 := reader.ReadLine()
		if err1 != nil {
			break
		}
		// Make a copy.
		copyOfLine1 := make([]byte, len(line1))
		copy(copyOfLine1, line1)
		print(ln, line1)

		// Second line.
		line2, _, err2 := reader.ReadLine()
		if err2 != nil {
			break
		}
		print(ln+1, line2)

		// Problem here - after reading the second line, the line1 is modified??
		if bytes.Compare(line1, copyOfLine1) != 0 {
			fmt.Printf("NOT EQUAL - line1: %s; copy: %s\n", string(line1), string(copyOfLine1))
		}

		// Must read a 3rd line.
		line3, _, err3 := reader.ReadLine()
		if err3 != nil {
			break
		}
		print(ln+2, line3)
		ln += 3
	}
}

func print(ln int, slice []byte) {
	fmt.Printf("%d: %s\n", ln, string(slice))
}

There's one byte difference actually:

output2.txt

image

P.S. The last only in A was just a line number.

This updated version output the right result for L1024.

The comment#1 code even generated the wrong output 233 -> 234 (sounded like another bug?).

@robpike
Copy link
Contributor

@robpike robpike commented Oct 16, 2020

Working as intended. As the documentation says, "The returned buffer is only valid until the next call to ReadLine."

@MewX
Copy link
Author

@MewX MewX commented Oct 16, 2020

🤣 Thanks Rob! I'll close this one.

@MewX MewX closed this Oct 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.