eal: add strscpy function
authorGaetan Rivet <gaetan.rivet@6wind.com>
Tue, 11 Sep 2018 15:00:49 +0000 (17:00 +0200)
committerThomas Monjalon <thomas@monjalon.net>
Wed, 19 Sep 2018 09:38:19 +0000 (11:38 +0200)
The strncpy function has long been deemed unsafe for use,
in favor of strlcpy or snprintf.

While snprintf is standard and strlcpy is still largely available,
they both have issues regarding error checking and performance.

Both will force reading the source buffer past the requested size
if the input is not a proper c-string, and will return the expected
number of bytes copied, meaning that error checking needs to verify
that the number of bytes copied is not superior to the destination
size.

This contributes to awkward code flow, unclear error checking and
potential issues with malformed input.

The function strscpy has been discussed for some time already and
has been made available in the linux kernel[1].

Propose this new function as a safe alternative.

[1]: http://git.kernel.org/linus/30c44659f4a3

Signed-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>
Acked-by: Juhamatti Kuusisaari <juhamatti.kuusisaari@coriant.com>
Acked-by: Ferruh Yigit <ferruh.yigit@intel.com>
lib/librte_eal/common/eal_common_string_fns.c
lib/librte_eal/common/include/rte_string_fns.h
lib/librte_eal/rte_eal_version.map

index 6ac5f82..60c5dd6 100644 (file)
@@ -38,3 +38,29 @@ einval_error:
        errno = EINVAL;
        return -1;
 }
+
+/* Copy src string into dst.
+ *
+ * Return negative value and NUL-terminate if dst is too short,
+ * Otherwise return number of bytes copied.
+ */
+ssize_t
+rte_strscpy(char *dst, const char *src, size_t dsize)
+{
+       size_t nleft = dsize;
+       size_t res = 0;
+
+       /* Copy as many bytes as will fit. */
+       while (nleft != 0) {
+               dst[res] = src[res];
+               if (src[res] == '\0')
+                       return res;
+               res++;
+               nleft--;
+       }
+
+       /* Not enough room in dst, set NUL and return error. */
+       if (res != 0)
+               dst[res - 1] = '\0';
+       return -E2BIG;
+}
index 97597a1..ecd141b 100644 (file)
@@ -76,6 +76,29 @@ rte_strlcpy(char *dst, const char *src, size_t size)
 #endif /* RTE_USE_LIBBSD */
 #endif /* BSDAPP */
 
+/**
+ * Copy string src to buffer dst of size dsize.
+ * At most dsize-1 chars will be copied.
+ * Always NUL-terminates, unless (dsize == 0).
+ * Returns number of bytes copied (terminating NUL-byte excluded) on success ;
+ * negative errno on error.
+ *
+ * @param dst
+ *   The destination string.
+ *
+ * @param src
+ *   The input string to be copied.
+ *
+ * @param dsize
+ *   Length in bytes of the destination buffer.
+ *
+ * @return
+ *   The number of bytes copied on success
+ *   -E2BIG if the destination buffer is too small.
+ */
+ssize_t
+rte_strscpy(char *dst, const char *src, size_t dsize);
+
 #ifdef __cplusplus
 }
 #endif
index 344a43d..2031d7b 100644 (file)
@@ -262,6 +262,13 @@ DPDK_18.08 {
 
 } DPDK_18.05;
 
+DPDK_18.11 {
+       global:
+
+       rte_strscpy;
+
+} DPDK_18.08;
+
 EXPERIMENTAL {
        global: