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
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.

Comments

@MewX
Copy link

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

@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

@davecheney davecheney added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Oct 16, 2020
@MewX
Copy link
Author

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 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 commented Oct 16, 2020

🤣 Thanks Rob! I'll close this one.

@MewX MewX closed this as completed Oct 16, 2020
@golang golang locked and limited conversation to collaborators Oct 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

4 participants