Fix ZipDecompressor windows 0x80 (file attribute normal)

Fixes #9236. On a rare occasion a zip file contains files with the 0x80 attribute.

From https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
A file that does not have other attributes set. This attribute is valid only when used alone.

Closes #15260.

PiperOrigin-RevId: 442825326
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/ZipDecompressor.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/ZipDecompressor.java
index 30f59f3..f2bf17c 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/ZipDecompressor.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/ZipDecompressor.java
@@ -51,10 +51,11 @@
   private static final int S_IFREG = 0100000;
   private static final int S_IFLNK = 0120000;
   private static final int EXECUTABLE_MASK = 0755;
-  @VisibleForTesting
-  static final int WINDOWS_DIRECTORY = 0x10;
-  @VisibleForTesting
-  static final int WINDOWS_FILE = 0x20;
+
+  // source: https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
+  @VisibleForTesting static final int WINDOWS_FILE_ATTRIBUTE_DIRECTORY = 0x10;
+  @VisibleForTesting static final int WINDOWS_FILE_ATTRIBUTE_ARCHIVE = 0x20;
+  @VisibleForTesting static final int WINDOWS_FILE_ATTRIBUTE_NORMAL = 0x80;
 
   /**
    * This unzips the zip file to directory {@link DecompressorDescriptor#repositoryPath()}, which by
@@ -186,10 +187,13 @@
     // https://github.com/miloyip/rapidjson/archive/v1.0.2.zip, it looks like executables end up
     // with "normal" (posix) permissions (oddly), so they'll be handled above.
     int windowsPermission = permissions & 0xff;
-    if ((windowsPermission & WINDOWS_DIRECTORY) == WINDOWS_DIRECTORY) {
+    if ((windowsPermission & WINDOWS_FILE_ATTRIBUTE_DIRECTORY)
+        == WINDOWS_FILE_ATTRIBUTE_DIRECTORY) {
       // Directory.
       return S_IFDIR | EXECUTABLE_MASK;
-    } else if (permissions == 0 || (windowsPermission & WINDOWS_FILE) == WINDOWS_FILE) {
+    } else if (permissions == 0
+        || (windowsPermission & WINDOWS_FILE_ATTRIBUTE_ARCHIVE) == WINDOWS_FILE_ATTRIBUTE_ARCHIVE
+        || (windowsPermission & WINDOWS_FILE_ATTRIBUTE_NORMAL) == WINDOWS_FILE_ATTRIBUTE_NORMAL) {
       // File.
       return S_IFREG | EXECUTABLE_MASK;
     }
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/ZipDecompressorTest.java b/src/test/java/com/google/devtools/build/lib/bazel/repository/ZipDecompressorTest.java
index 0ba47de..88936a1 100644
--- a/src/test/java/com/google/devtools/build/lib/bazel/repository/ZipDecompressorTest.java
+++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/ZipDecompressorTest.java
@@ -85,9 +85,14 @@
 
   @Test
   public void testWindowsPermissions() throws Exception {
-    int permissions = ZipDecompressor.getPermissions(ZipDecompressor.WINDOWS_DIRECTORY, "foo/bar");
+    int permissions =
+        ZipDecompressor.getPermissions(ZipDecompressor.WINDOWS_FILE_ATTRIBUTE_DIRECTORY, "foo/bar");
     assertThat(permissions).isEqualTo(DIRECTORY);
-    permissions = ZipDecompressor.getPermissions(ZipDecompressor.WINDOWS_FILE, "foo/bar");
+    permissions =
+        ZipDecompressor.getPermissions(ZipDecompressor.WINDOWS_FILE_ATTRIBUTE_ARCHIVE, "foo/bar");
+    assertThat(permissions).isEqualTo(EXECUTABLE);
+    permissions =
+        ZipDecompressor.getPermissions(ZipDecompressor.WINDOWS_FILE_ATTRIBUTE_NORMAL, "foo/bar");
     assertThat(permissions).isEqualTo(EXECUTABLE);
   }