Use typed ZIP entry checks in SSD import

ober

4356bb81f23e1989064c51cbd245c4b19ad91219

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index ef1ce46..2640318 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -1561,7 +1561,8 @@
       (kotlin-imports (java io File)
                       (java net URL)
                       (java nio file Files)
-                      (java nio file Path))
+                      (java nio file Path)
+                      (java util zip ZipEntry))
       (typed-library (com sfb ssdreview)
         (export make-RemoteConfig RemoteConfig?
                 RemoteConfig-apiUrl RemoteConfig-spkiSha256 RemoteConfig-bearerToken
@@ -1578,10 +1579,12 @@
                 remoteBearerTokenPresent remoteBearerTokenValid
                 remotePinPresent remotePinOrNull remotePinSha256Length
                 remoteRelativePathSafe
-                shouldCompareMoreCompleteTruth)
+                shouldCompareMoreCompleteTruth
+                zipEntryIsDirectory zipEntryDeclaresExcessiveSize)
         (type File)
         (type Path)
         (type URL)
+        (type ZipEntry)
         (type Int32)
         (extern (fileExistsRaw (file : File)) : Bool
           (kotlin-member-call exists))
@@ -1603,6 +1606,12 @@
           (kotlin-member-get port))
         (extern (urlDefaultPort (url : URL)) : Int32
           (kotlin-member-get defaultPort))
+        (extern (zipEntryIsDirectoryRaw (entry : ZipEntry)) : Bool
+          (kotlin-member-get isDirectory))
+        (extern (zipEntrySize (entry : ZipEntry)) : Int
+          (kotlin-member-get size))
+        (extern (zipEntryCompressedSize (entry : ZipEntry)) : Int
+          (kotlin-member-get compressedSize))
         (record RemoteConfig
           ((apiUrl : URL)
            (spkiSha256 : (Nullable Bytes))
@@ -1669,7 +1678,14 @@
                     (not (string-contains? relative "..")))))
         (def (shouldCompareMoreCompleteTruth (replaceIfMoreComplete : Bool)
                                              (destination : File)) : Bool
-          (and replaceIfMoreComplete (fileExists destination)))))
+          (and replaceIfMoreComplete (fileExists destination)))
+        (def (zipEntryIsDirectory (entry : ZipEntry)) : Bool
+          (zipEntryIsDirectoryRaw entry))
+        (def (zipEntryDeclaresExcessiveSize (entry : ZipEntry)
+                                            (entryLimit : Int)
+                                            (compressedLimit : Int)) : Bool
+          (or (> (zipEntrySize entry) entryLimit)
+              (> (zipEntryCompressedSize entry) compressedLimit)))))
 
     (typed-kotlin-file "com/sfb/ssdreview/JsonGeometry.kt"
       (kotlin-imports (org json JSONArray))
@@ -8333,8 +8349,8 @@
        "                    if (!safeZipEntryName(name)) {"
        "                        throw IllegalStateException(\"Unsafe ZIP entry\")"
        "                    }"
-       "                    if (!entry.isDirectory) {"
-       "                        if (entry.size > MAX_ZIP_ENTRY_BYTES || entry.compressedSize > MAX_REMOTE_ZIP_BYTES) {"
+       "                    if (!zipEntryIsDirectory(entry)) {"
+       "                        if (zipEntryDeclaresExcessiveSize(entry, MAX_ZIP_ENTRY_BYTES, MAX_REMOTE_ZIP_BYTES)) {"
        "                            throw IllegalStateException(\"ZIP entry declares excessive size\")"
        "                        }"
        "                        val stagedFile = File(stage, budget.entries.toString())"