diff --git a/shared/util/change-notes/2023-10-13-filepath-normalization.md b/shared/util/change-notes/2023-10-13-filepath-normalization.md index 6324634fd58..3ffdadc85b3 100644 --- a/shared/util/change-notes/2023-10-13-filepath-normalization.md +++ b/shared/util/change-notes/2023-10-13-filepath-normalization.md @@ -1,4 +1,4 @@ +--- category: feature --- -* Added `FilePath` API for normalizing filepaths. -``` \ No newline at end of file +* Added `FilePath` API for normalizing filepaths. \ No newline at end of file diff --git a/shared/util/codeql/util/FilePath.qll b/shared/util/codeql/util/FilePath.qll index b2906f5d4e0..c532f198d64 100644 --- a/shared/util/codeql/util/FilePath.qll +++ b/shared/util/codeql/util/FilePath.qll @@ -8,11 +8,13 @@ abstract class NormalizableFilepath extends string { bindingset[this] NormalizableFilepath() { any() } + /** Gets the `i`th path component of this string. */ private string getComponent(int i) { result = this.splitAt("/", i) } + /** Gets the number of path components of thi string. */ private int getNumComponents() { result = strictcount(int i | exists(this.getComponent(i))) } - /** count .. segments in prefix in normalization from index i */ + /** In the normalized path starting from component `i`, counts the number of `..` segments that path starts with. */ private int dotdotCountFrom(int i) { result = 0 and i = this.getNumComponents() or @@ -29,7 +31,7 @@ abstract class NormalizableFilepath extends string { ) } - /** count non-.. segments in postfix in normalization from index 0 to i-1 */ + /** In the normalized path up to (excluding) component `i`, counts the number of non-`..` segments that path ends with. */ private int segmentCountUntil(int i) { result = 0 and i = 0 or @@ -46,6 +48,7 @@ abstract class NormalizableFilepath extends string { ) } + /** Gets the `i`th component if that component should be included in the normalized path. */ private string part(int i) { result = this.getComponent(i) and result != "." and @@ -60,7 +63,13 @@ abstract class NormalizableFilepath extends string { ) } - /** Gets the normalized filepath for this string; traversing `/../` paths. */ + /** + * Gets the normalized filepath for this string. + * Normalizes `..` paths, `.` paths, and multiple `/`s as much as possible, but does not normalize case, resolve symlinks, or make relative paths absolute. + * Th normalized path will be absolute (begin with `/`) if and only if the original path is. + * The normalized path will not have a trailing `/`. + * Only `/` is treated as a path separator. + */ string getNormalizedPath() { exists(string norm | norm = concat(string s, int i | s = this.part(i) | s, "/" order by i) | if norm != ""