]> granicus.if.org Git - graphviz/commitdiff
cgraph: add a 'strndup' allocation wrapper
authorMatthew Fernandez <matthew.fernandez@gmail.com>
Fri, 18 Mar 2022 15:18:41 +0000 (08:18 -0700)
committerMatthew Fernandez <matthew.fernandez@gmail.com>
Thu, 24 Mar 2022 15:36:53 +0000 (08:36 -0700)
lib/cgraph/alloc.h

index 2148dedc8c52b376304d71f0571e0b32b0703286..153b40f8cdb2f0fdd525a3f610d9db2bf7e597b6 100644 (file)
@@ -77,3 +77,42 @@ static inline char *gv_strdup(const char *original) {
 
   return copy;
 }
+
+static inline char *gv_strndup(const char *original, size_t length) {
+
+  char *copy;
+
+// non-Cygwin Windows environments do not provide strndup
+#if defined(_MSC_VER) || defined(__MINGW32__)
+
+  // does the string end before the given length?
+  {
+    const char *end = memchr(original, '\0', length);
+    if (end != NULL) {
+      length = (size_t)(end - original);
+    }
+  }
+
+  // will our calculation to include the NUL byte below overflow?
+  if (UNLIKELY(SIZE_MAX - length < 1)) {
+    fprintf(stderr, "integer overflow in strndup calculation\n");
+    graphviz_exit(EXIT_FAILURE);
+  }
+
+  copy = gv_alloc(length + 1);
+  memcpy(copy, original, length);
+
+  // `gv_alloc` has already zeroed the backing memory, so no need to manually
+  // add a NUL terminator
+
+#else
+  copy = strndup(original, length);
+#endif
+
+  if (UNLIKELY(copy == NULL)) {
+    fprintf(stderr, "out of memory\n");
+    graphviz_exit(EXIT_FAILURE);
+  }
+
+  return copy;
+}