Blob Blame History Raw
From ce207ac7cd523109e2478ce831a9034e0ecd2a94 Mon Sep 17 00:00:00 2001
From: Jakub Filak <jfilak@redhat.com>
Date: Thu, 23 Apr 2015 13:21:41 +0200
Subject: [PATCH] lib: add a function checking file names

Move the code from ABRT and extend it a bit:
* allow only 64 characters
* allow '.' in names (vmcore_dmesg.txt)
* forbid '/'
* forbid "."
* forbid ".."

Related: #1214451

Signed-off-by: Jakub Filak <jfilak@redhat.com>
---
 src/include/internal_libreport.h |  6 ++++++
 src/lib/concat_path_file.c       | 25 ++++++++++++++++++++++
 tests/dump_dir.at                | 46 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+)

diff --git a/src/include/internal_libreport.h b/src/include/internal_libreport.h
index e66ca96..a4303de 100644
--- a/src/include/internal_libreport.h
+++ b/src/include/internal_libreport.h
@@ -131,6 +131,12 @@ char *concat_path_file(const char *path, const char *filename);
 #define concat_path_basename libreport_concat_path_basename
 char *concat_path_basename(const char *path, const char *filename);
 
+/* Allows all printable characters except '/',
+ * the string must not exceed 64 characters of length
+ * and must not equal neither "." nor ".." (these strings may appear in the string) */
+#define str_is_correct_filename libreport_str_is_correct_filename
+bool str_is_correct_filename(const char *str);
+
 /* A-la fgets, but malloced and of unlimited size */
 #define xmalloc_fgets libreport_xmalloc_fgets
 char *xmalloc_fgets(FILE *file);
diff --git a/src/lib/concat_path_file.c b/src/lib/concat_path_file.c
index 39ae07a..24e4cbd 100644
--- a/src/lib/concat_path_file.c
+++ b/src/lib/concat_path_file.c
@@ -57,3 +57,28 @@ char *concat_path_basename(const char *path, const char *filename)
     free(abspath);
     return name;
 }
+
+bool str_is_correct_filename(const char *str)
+{
+#define NOT_PRINTABLE(c) (c < ' ' || c == 0x7f)
+
+    if (NOT_PRINTABLE(*str) || *str == '/' || *str == '\0')
+        return false;
+    ++str;
+
+    if (NOT_PRINTABLE(*str) || *str =='/' || (*str == '\0' && *(str-1) == '.'))
+        return false;
+    ++str;
+
+    if (NOT_PRINTABLE(*str) || *str =='/' || (*str == '\0' && *(str-1) == '.' && *(str-2) == '.'))
+        return false;
+    ++str;
+
+    for (unsigned i = 0; *str != '\0' && i < 61; ++str, ++i)
+        if (NOT_PRINTABLE(*str) || *str == '/')
+            return false;
+
+    return *str == '\0';
+
+#undef NOT_PRINTABLE
+}
diff --git a/tests/dump_dir.at b/tests/dump_dir.at
index efec63f..19584d1 100644
--- a/tests/dump_dir.at
+++ b/tests/dump_dir.at
@@ -49,3 +49,49 @@ int main(int argc, char **argv)
     return 0;
 }
 ]])
+
+## ----------------------- ##
+## str_is_correct_filename ##
+## ----------------------- ##
+
+AT_TESTFUN([str_is_correct_filename],
+[[
+#include "internal_libreport.h"
+#include <assert.h>
+#
+int main(void)
+{
+    g_verbose = 3;
+
+    assert(str_is_correct_filename("") == false);
+    assert(str_is_correct_filename("/") == false);
+    assert(str_is_correct_filename("//") == false);
+    assert(str_is_correct_filename(".") == false);
+    assert(str_is_correct_filename(".") == false);
+    assert(str_is_correct_filename("..") == false);
+    assert(str_is_correct_filename("..") == false);
+    assert(str_is_correct_filename("/.") == false);
+    assert(str_is_correct_filename("//.") == false);
+    assert(str_is_correct_filename("./") == false);
+    assert(str_is_correct_filename(".//") == false);
+    assert(str_is_correct_filename("/./") == false);
+    assert(str_is_correct_filename("/..") == false);
+    assert(str_is_correct_filename("//..") == false);
+    assert(str_is_correct_filename("../") == false);
+    assert(str_is_correct_filename("..//") == false);
+    assert(str_is_correct_filename("/../") == false);
+    assert(str_is_correct_filename("/.././") == false);
+
+    assert(str_is_correct_filename("looks-good-but-evil/") == false);
+    assert(str_is_correct_filename("looks-good-but-evil/../../") == false);
+
+    assert(str_is_correct_filename(".meta-data") == true);
+    assert(str_is_correct_filename("..meta-meta-data") == true);
+    assert(str_is_correct_filename("meta-..-data") == true);
+
+    assert(str_is_correct_filename("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890+-") == true);
+    assert(str_is_correct_filename("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890+-=") == false);
+
+    return 0;
+}
+]])
-- 
2.1.0