Skip to content

archive/zip: FileHeader.SetMode: character files encoded as regular files #36301

Description

@masiulaniec
package main

import (
        "archive/zip"
        "log"
        "os"
)

const charDeviceFile = "/dev/null"

func main() {
        fi, err := os.Stat(charDeviceFile)
        if err != nil {
                panic(err)
        }
        fh, err := zip.FileInfoHeader(fi)
        if err != nil {
                panic(err)
        }
        if isChar(fi) != isChar(fh.FileInfo()) {
                log.Printf("file mode inconsistent after zip.FileInfoHeader: got %q, want %q", fh.FileInfo().Mode(), fi.Mode())
        }
}

func isChar(fi os.FileInfo) bool { return fi.Mode() & os.ModeCharDevice != 0 }

This reproducer program fails unexpectedly with the error:

file mode inconsistent after zip.FileInfoHeader: got "-rw-rw-rw-", want "Dcrw-rw-rw-"

The data loss is due to a logically impossible bit match in fileModeToUnixMode. The fix:

--- src/archive/zip/struct.go   2019-12-29 02:26:54.000000000 +0100
+++ src/archive/zip/struct.go   2019-12-29 02:27:05.000000000 +0100
@@ -337,12 +337,10 @@
                m = s_IFIFO
        case os.ModeSocket:
                m = s_IFSOCK
+       case os.ModeDevice | os.ModeCharDevice:
+               m = s_IFCHR
        case os.ModeDevice:
-               if mode&os.ModeCharDevice != 0 {
-                       m = s_IFCHR
-               } else {
-                       m = s_IFBLK
-               }
+               m = s_IFBLK
        }
        if mode&os.ModeSetuid != 0 {
                m |= s_ISUID

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions