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

archive/tar: eats file data #11170

Closed
dvyukov opened this issue Jun 11, 2015 · 4 comments
Closed

archive/tar: eats file data #11170

dvyukov opened this issue Jun 11, 2015 · 4 comments
Milestone

Comments

@dvyukov
Copy link
Member

dvyukov commented Jun 11, 2015

The following program fails with the panic:

package main

import (
    "archive/tar"
    "bytes"
    "fmt"
    "io"
    "io/ioutil"
)

func main() {
    data := []byte("aaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "0100640\x000374534\x000011" +
        "610\x0000000000007\x001253" +
        "1145371\x00010572\x0000\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ust" +
        "ar  \x00dvyukov\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00eng" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000000000")

    t := tar.NewReader(bytes.NewReader(data))
    var headers []*tar.Header
    var contents [][]byte
    for {
        hdr, err := t.Next()
        if err == io.EOF {
            break
        }
        if err != nil {
            return
        }
        fdata, err := ioutil.ReadAll(t)
        if err != nil {
            return
        }
        hdr1 := *hdr
        headers = append(headers, &hdr1)
        contents = append(contents, fdata)
    }
    buf := new(bytes.Buffer)
    w := tar.NewWriter(buf)
    for i, hdr := range headers {
        err := w.WriteHeader(hdr)
        if err != nil {
            panic(err)
        }
        _, err = w.Write(contents[i])
        if err != nil {
            panic(err)
        }
    }
    err := w.Close()
    if err != nil {
        panic(err)
    }
    t1 := tar.NewReader(buf)
    for i := 0; ; i++ {
        _, err := t1.Next()
        if err == io.EOF {
            break
        }
        if err != nil {
            panic(err)
        }
        fdata, err := ioutil.ReadAll(t)
        if err != nil {
            panic(err)
        }
        if !bytes.Equal(fdata, contents[i]) {
            fmt.Printf("got : %q\n", fdata)
            fmt.Printf("want: %q\n", contents[i])
            panic("data differs")
        }
    }
}
got : ""
want: "0000000"
panic: data differs

That is, file data is lost after packing/unpacking.

go version devel +b0532a9 Mon Jun 8 05:13:15 2015 +0000 linux/amd64

@ianlancetaylor ianlancetaylor added this to the Go1.6 milestone Jun 11, 2015
@dadkins
Copy link

dadkins commented Aug 31, 2015

There is a type in this test program. Replace

fdata, err := ioutil.ReadAll(t)

with

fdata, err := ioutil.ReadAll(t1)

and the test passes.

If there is any issue here, it's that the second call to ioutil.ReadAll(t) succeeds and returns 512 bytes. How is that possible? Did the underlying Reader somehow reset?

@dadkins
Copy link

dadkins commented Aug 31, 2015

s/type/typo/

And I was wrong in my initial comment. The second call to ioutil.RealAll(t) returns [], nil as expected at EOF.

There is no bug here.

@dvyukov
Copy link
Member Author

dvyukov commented Sep 1, 2015

@dadkins thanks for looking at this! Yeah, it should be s/t/t1/, I've fixed my test. Closing.

@dvyukov dvyukov closed this as completed Sep 1, 2015
@dvyukov
Copy link
Member Author

dvyukov commented Sep 1, 2015

@dadkins this allowed me to move forward:
#12434
#12435
#12436
:)

@golang golang locked and limited conversation to collaborators Sep 4, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants