瀏覽代碼

fileapi: Restrict reply object file path lengths

Fixes: #23389
Stefan Wüthrich 1 年之前
父節點
當前提交
1ae7497b6a

+ 22 - 1
Source/cmFileAPI.cxx

@@ -200,7 +200,28 @@ std::string cmFileAPI::WriteJsonFile(
   }
 
   // Compute the final name for the file.
-  fileName = prefix + "-" + computeSuffix(tmpFile) + ".json";
+  std::string suffix = computeSuffix(tmpFile);
+  std::string suffixWithExtension = cmStrCat("-", suffix, ".json");
+  fileName = cmStrCat(prefix, suffixWithExtension);
+
+  // Truncate the file name length
+  // eCryptFS has a maximal file name length recommendation of 140
+  size_t const maxFileNameLength = 140;
+  size_t const fileNameLength = fileName.size();
+  if (fileNameLength > maxFileNameLength) {
+    size_t const newHashLength = 20;
+    size_t const newSuffixLength =
+      suffixWithExtension.size() - suffix.size() + newHashLength;
+    size_t const overLength =
+      fileNameLength - maxFileNameLength + newSuffixLength;
+    size_t const startPos = fileNameLength - overLength;
+    std::string const toBeRemoved = fileName.substr(startPos, overLength);
+    suffix = cmCryptoHash(cmCryptoHash::AlgoSHA256)
+               .HashString(toBeRemoved)
+               .substr(0, newHashLength);
+    suffixWithExtension = cmStrCat("-", suffix, ".json");
+    fileName.replace(startPos, overLength, suffixWithExtension);
+  }
 
   // Create the destination.
   std::string file = this->APIv1 + "/reply";

+ 6 - 0
Tests/RunCMake/FileAPI/cmakeFiles-v1-check.py

@@ -75,6 +75,12 @@ def check_object_cmakeFiles(o):
             "isExternal": None,
             "isCMake": None,
         },
+        {
+            "path": "^dir/very-long/CMakeLists\\.txt$",
+            "isGenerated": None,
+            "isExternal": None,
+            "isCMake": None,
+        },
         {
             "path": "^dir/dirtest\\.cmake$",
             "isGenerated": None,

+ 3 - 0
Tests/RunCMake/FileAPI/codemodel-v2-check.py

@@ -94,6 +94,8 @@ def check_directory(c):
 
         assert is_string(actual["jsonFile"])
         filepath = os.path.join(reply_dir, actual["jsonFile"])
+        maximum_filename_length = 140
+        assert len(actual["jsonFile"]) <= maximum_filename_length
         with open(filepath) as f:
             d = json.load(f)
 
@@ -747,6 +749,7 @@ def gen_check_directories(c, g):
         read_codemodel_json_data("directories/object.json"),
         read_codemodel_json_data("directories/dir.json"),
         read_codemodel_json_data("directories/dir_dir.json"),
+        read_codemodel_json_data("directories/dir_very-long.json"),
         read_codemodel_json_data("directories/external.json"),
         read_codemodel_json_data("directories/fileset.json"),
         read_codemodel_json_data("directories/subdir.json"),

+ 2 - 1
Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json

@@ -3,7 +3,8 @@
     "build": "^dir$",
     "parentSource": "^\\.$",
     "childSources": [
-        "^dir/dir$"
+        "^dir/dir$",
+        "^dir/very-long$"
     ],
     "targetIds": null,
     "projectName": "codemodel-v2",

+ 11 - 0
Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_very-long.json

@@ -0,0 +1,11 @@
+{
+    "source": "^dir/very-long",
+    "build": "^dir/very-long-directory-name-in-order-to-test-that-the-fileapi-codemodel-v2-directory-object-is-placed-in-a-json-file-on-disk-with-a-shortened-name$",
+    "parentSource": "^dir$",
+    "childSources": null,
+    "targetIds": null,
+    "projectName": "codemodel-v2",
+    "minimumCMakeVersion": "3.13",
+    "hasInstallRule": null,
+    "installers": []
+}

+ 1 - 0
Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json

@@ -15,6 +15,7 @@
         "^\\.$",
         "^dir$",
         "^dir/dir$",
+        "^dir/very-long$",
         "^fileset$",
         "^subdir$"
     ],

+ 1 - 0
Tests/RunCMake/FileAPI/dir/CMakeLists.txt

@@ -1 +1,2 @@
 add_subdirectory(dir)
+add_subdirectory(very-long very-long-directory-name-in-order-to-test-that-the-fileapi-codemodel-v2-directory-object-is-placed-in-a-json-file-on-disk-with-a-shortened-name)

+ 0 - 0
Tests/RunCMake/FileAPI/dir/very-long/CMakeLists.txt