[Bf-blender-cvs] [7687f3ed676] temp-asset-browser-catalogs-ui: Properly null-check the asset catalog tree before accessing for UI

Julian Eisel noreply at git.blender.org
Fri Sep 24 20:31:51 CEST 2021


Commit: 7687f3ed6768d75450f4a320c0c98392b25eec0b
Author: Julian Eisel
Date:   Fri Sep 24 20:15:45 2021 +0200
Branches: temp-asset-browser-catalogs-ui
https://developer.blender.org/rB7687f3ed6768d75450f4a320c0c98392b25eec0b

Properly null-check the asset catalog tree before accessing for UI

===================================================================

A	source/blender/blenlib/intern/path_util.cc
A	source/blender/blenlib/intern/storage.cc
M	source/blender/editors/space_file/asset_catalog_tree_view.cc

===================================================================

diff --git a/source/blender/blenlib/intern/path_util.cc b/source/blender/blenlib/intern/path_util.cc
new file mode 100644
index 00000000000..760e7910a77
--- /dev/null
+++ b/source/blender/blenlib/intern/path_util.cc
@@ -0,0 +1,2083 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ * various string, file, list operations.
+ */
+
+/** \file
+ * \ingroup bli
+ */
+
+#include <algorithm>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "DNA_listBase.h"
+
+#include "BLI_fileops.h"
+#include "BLI_fnmatch.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_string_utf8.h"
+#include "BLI_utildefines.h"
+#ifdef USE_CPP_FILESYSTEM
+#  include "BLI_filesystem.hh"
+#endif
+
+#ifdef WIN32
+#  include "utf_winfunc.h"
+#  include "utfconv.h"
+#  include <io.h>
+#  ifdef _WIN32_IE
+#    undef _WIN32_IE
+#  endif
+#  define _WIN32_IE 0x0501
+#  include "BLI_alloca.h"
+#  include "BLI_winstuff.h"
+#  include <shlobj.h>
+#  include <windows.h>
+#else
+#  include "unistd.h"
+#endif /* WIN32 */
+
+#include "MEM_guardedalloc.h"
+
+#ifdef USE_CPP_FILESYSTEM
+using namespace blender::bli;
+#endif
+
+/* Declarations */
+
+#ifdef WIN32
+
+/**
+ * Return true if the path is absolute ie starts with a drive specifier
+ * (eg A:\) or is a UNC path.
+ */
+static bool BLI_path_is_abs(const char *name);
+
+#endif /* WIN32 */
+
+// #define DEBUG_STRSIZE
+
+/* implementation */
+
+/**
+ * Looks for a sequence of decimal digits in string, preceding any filename extension,
+ * returning the integer value if found, or 0 if not.
+ *
+ * \param string: String to scan.
+ * \param head: Optional area to return copy of part of string prior to digits,
+ * or before dot if no digits.
+ * \param tail: Optional area to return copy of part of string following digits,
+ * or from dot if no digits.
+ * \param r_num_len: Optional to return number of digits found.
+ */
+int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort *r_num_len)
+{
+  uint nums = 0, nume = 0;
+  int i;
+  bool found_digit = false;
+  const char *const lslash = BLI_path_slash_rfind(string);
+  const uint string_len = strlen(string);
+  const uint lslash_len = lslash != NULL ? (int)(lslash - string) : 0;
+  uint name_end = string_len;
+
+  while (name_end > lslash_len && string[--name_end] != '.') {
+    /* name ends at dot if present */
+  }
+  if (name_end == lslash_len && string[name_end] != '.') {
+    name_end = string_len;
+  }
+
+  for (i = name_end - 1; i >= (int)lslash_len; i--) {
+    if (isdigit(string[i])) {
+      if (found_digit) {
+        nums = i;
+      }
+      else {
+        nume = i;
+        nums = i;
+        found_digit = true;
+      }
+    }
+    else {
+      if (found_digit) {
+        break;
+      }
+    }
+  }
+
+  if (found_digit) {
+    const long long int ret = strtoll(&(string[nums]), NULL, 10);
+    if (ret >= INT_MIN && ret <= INT_MAX) {
+      if (tail) {
+        strcpy(tail, &string[nume + 1]);
+      }
+      if (head) {
+        strcpy(head, string);
+        head[nums] = 0;
+      }
+      if (r_num_len) {
+        *r_num_len = nume - nums + 1;
+      }
+      return (int)ret;
+    }
+  }
+
+  if (tail) {
+    strcpy(tail, string + name_end);
+  }
+  if (head) {
+    /* name_end points to last character of head,
+     * make it +1 so null-terminator is nicely placed
+     */
+    BLI_strncpy(head, string, name_end + 1);
+  }
+  if (r_num_len) {
+    *r_num_len = 0;
+  }
+  return 0;
+}
+
+/**
+ * Returns in area pointed to by string a string of the form "<head><pic><tail>", where pic
+ * is formatted as numlen digits with leading zeroes.
+ */
+void BLI_path_sequence_encode(
+    char *string, const char *head, const char *tail, unsigned short numlen, int pic)
+{
+  sprintf(string, "%s%.*d%s", head, numlen, MAX2(0, pic), tail);
+}
+
+static int BLI_path_unc_prefix_len(const char *path); /* defined below in same file */
+
+/* ******************** string encoding ***************** */
+
+/**
+ * Remove redundant characters from \a path and optionally make absolute.
+ *
+ * \param relabase: The path this is relative to, or ignored when NULL.
+ * \param path: Can be any input, and this function converts it to a regular full path.
+ * Also removes garbage from directory paths, like `/../` or double slashes etc.
+ *
+ * \note \a path isn't protected for max string names...
+ */
+void BLI_path_normalize(const char *relabase, char *path)
+{
+  ptrdiff_t a;
+  char *start, *eind;
+  if (relabase) {
+    BLI_path_abs(path, relabase);
+  }
+  else {
+    if (path[0] == '/' && path[1] == '/') {
+      if (path[2] == '\0') {
+        return; /* path is "//" - can't clean it */
+      }
+      path = path + 2; /* leave the initial "//" untouched */
+    }
+  }
+
+  /* Note
+   *   memmove(start, eind, strlen(eind) + 1);
+   * is the same as
+   *   strcpy(start, eind);
+   * except strcpy should not be used because there is overlap,
+   * so use memmove's slightly more obscure syntax - Campbell
+   */
+
+#ifdef WIN32
+  while ((start = strstr(path, "\\..\\"))) {
+    eind = start + strlen("\\..\\") - 1;
+    a = start - path - 1;
+    while (a > 0) {
+      if (path[a] == '\\') {
+        break;
+      }
+      a--;
+    }
+    if (a < 0) {
+      break;
+    }
+    else {
+      memmove(path + a, eind, strlen(eind) + 1);
+    }
+  }
+
+  while ((start = strstr(path, "\\.\\"))) {
+    eind = start + strlen("\\.\\") - 1;
+    memmove(start, eind, strlen(eind) + 1);
+  }
+
+  /* remove two consecutive backslashes, but skip the UNC prefix,
+   * which needs to be preserved */
+  while ((start = strstr(path + BLI_path_unc_prefix_len(path), "\\\\"))) {
+    eind = start + strlen("\\\\") - 1;
+    memmove(start, eind, strlen(eind) + 1);
+  }
+#else
+  while ((start = strstr(path, "/../"))) {
+    a = start - path - 1;
+    if (a > 0) {
+      /* <prefix>/<parent>/../<postfix> => <prefix>/<postfix> */
+      eind = start + (4 - 1) /* strlen("/../") - 1 */; /* strip "/.." and keep last "/" */
+      while (a > 0 && path[a] != '/') {                /* find start of <parent> */
+        a--;
+      }
+      memmove(path + a, eind, strlen(eind) + 1);
+    }
+    else {
+      /* Support for odd paths: eg `/../home/me` --> `/home/me`
+       * this is a valid path in blender but we can't handle this the usual way below
+       * simply strip this prefix then evaluate the path as usual.
+       * Python's `os.path.normpath()` does this. */
+
+      /* NOTE: previous version of following call used an offset of 3 instead of 4,
+       * which meant that the `/../home/me` example actually became `home/me`.
+       * Using offset of 3 gives behavior consistent with the aforementioned
+       * Python routine. */
+      memmove(path, path + 3, strlen(path + 3) + 1);
+    }
+  }
+
+  while ((start = strstr(path, "/./"))) {
+    eind = start + (3 - 1) /* strlen("/./") - 1 */;
+    memmove(start, eind, strlen(eind) + 1);
+  }
+
+  while ((start = strstr(path, "//"))) {
+    eind = start + (2 - 1) /* strlen("//") - 1 */;
+    memmove(start, eind, strlen(eind) + 1);
+  }
+#endif
+}
+
+/**
+ * Cleanup filepath ensuring a trailing slash.
+ */
+void BLI_path_normalize_dir(const char *relabase, char *dir)
+{
+  /* Would just create an unexpected "/" path, just early exit entirely. */
+  if (dir[0] == '\0') {
+    return;
+  }
+
+  BLI_path_normalize(relabase, dir);
+  BLI_path_slash_ensure(dir);
+}
+
+/**
+ * Make given name safe to be used in paths.
+ *
+ * \return true if \a fname was changed, false otherwise.
+ *
+ * For now, simply replaces reserved chars (as listed in
+ * https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words )
+ * by underscores ('_').
+ *
+ * \note Space case ' ' is a bit of an edge case here - in theory it is allowed,
+ * but again can be an issue in some cases, so we simply replace it by an underscore too
+ * (good practice anyway).
+ * REMOVED based on popular demand (see T45900).
+ * Percent '%' char is a bit same case - not recommended to use it,
+ * but supported by all decent file-systems/operating-systems around.
+ *
+ * \note On Windows, it also ensures there is no '.' (dot char) at the end of the file,
+ * this can lead to issues.
+ *
+ * \note On Windows, it also checks for forbidden names
+ * (see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx ).
+ */
+bool BLI_filename_make_safe(char *fname)
+{
+  const char *invalid =
+      "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+      "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+      "/\\?*:|\"<>";
+  char *fn;
+  bool changed = false;
+
+  if (*fname == '\0') {
+    return changed;
+  }
+
+  for (fn = fname; *fn && (fn = strpbrk(fn, invalid)); fn++) {
+    *fn = '_';
+    changed = true;
+  }
+
+  /* Forbid only dots. */
+  for (fn = fname; *fn == '.'; fn++) {
+    /* pass */
+  }
+  if (*fn == '\0') {
+    *fname = '_';
+    changed = true;
+  }
+
+#ifdef WIN32
+  {
+    const size_t len = strlen(fname);
+    const char *invalid_names[] = {
+        "con",  "prn",  "aux",  "null", "com1", "com2", "com3", "com4",
+        "com5", "com6", "com7", "com8", "com9", "lpt1", "lpt2", "lpt3",
+        "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", NULL,
+    };
+    char *lower_fname = BLI_strdup(fname);
+    const char **iname;
+
+    /* Forbid trailing dot (trailing space has already been replaced above). */
+    if (f

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list