Ilya Zakharevich on Fri, 30 Aug 2024 02:54:45 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[PATCH 2.16.2-beta] compressed input


This patch
  • allows newer types of compression of input;
  • protects against poison pills in the decompression command line.

Enjoy,
Ilya

--- src/language/es.c~	2024-06-29 10:15:06.000000000 -0700
+++ src/language/es.c	2024-08-29 17:47:31.545426919 -0700
@@ -3869,27 +3869,49 @@ strftime_expand(const char *s, char *buf
 { strcpy(buf,s); }
 #endif
 
+typedef struct 
+{
+  char *ext;
+  char *cmd;  
+} decompress_tbl;
+decompress_tbl decompress[] = {
+#ifdef ZCAT
+  {".Z",  ZCAT},
+#ifdef GZCAT
+  {".gz", ZCAT},
+#endif	/* defined GZCAT */ 
+#endif	/* defined ZCAT */ 
+  {".bz2",  "bzip2 -dc"},
+  {".xz",      "xz -dc"},
+  {".zstd",  "zstd -dc"},
+  {".7z",     "7za -so e"},
+  {".zip",  "unzip -p"},
+  {NULL, NULL}
+};
+
 /* name is a malloc'ed (existing) filename. Accept it as new pari_infile
  * (unzip if needed). */
 static pariFILE *
 pari_get_infile(const char *name, FILE *file)
 {
-#ifdef ZCAT
+  decompress_tbl *t = decompress;
   long l = strlen(name);
-  const char *end = name + l-1;
+  const char *end = name + l;
+  while (t->ext) {
+    long ll = strlen(t->ext);
 
-  if (l > 2 && (!strncmp(end-1,".Z",2)
-#ifdef GNUZCAT
-             || !strncmp(end-2,".gz",3)
-#endif
-  ))
-  { /* compressed file (compress or gzip) */
-    char *cmd = stack_malloc(strlen(ZCAT) + l + 4);
-    sprintf(cmd,"%s \"%s\"",ZCAT,name);
-    fclose(file);
-    return try_pipe(cmd, mf_IN);
+    if (end >= name && !strncmp(end-ll, t->ext, ll))
+    { /* compressed file (compress or gzip etc.) */
+      char *cmd = stack_malloc(strlen(t->cmd) + l + 4), *badchrs = " \"`$";
+      while (*++badchrs)
+        if (strchr(name, *badchrs))
+	  pari_err(e_MISC, "Compressed input file name contains the unsupported character %c", *badchrs);
+      sprintf(cmd,"%s \"%s\"",t->cmd,name);
+      fclose(file);
+      return try_pipe(cmd, mf_IN);
+    }
+    t++;
   }
-#endif
   return newfile(file, name, mf_IN);
 }