[ding-libs] Make path_concat return empty string on ENOBUFS

Stephen Gallagher sgallagh at fedoraproject.org
Fri Mar 16 12:32:14 UTC 2012


commit 4e0c978e54054de441e8c126c63f6218cf97ea91
Author: Stephen Gallagher <sgallagh at redhat.com>
Date:   Fri Mar 16 08:32:11 2012 -0400

    Make path_concat return empty string on ENOBUFS

 ...path_concat-should-return-empty-string-on.patch |  153 ++++++++++++++++++++
 ding-libs.spec                                     |    7 +-
 2 files changed, 159 insertions(+), 1 deletions(-)
---
diff --git a/0003-path_utils-path_concat-should-return-empty-string-on.patch b/0003-path_utils-path_concat-should-return-empty-string-on.patch
new file mode 100644
index 0000000..ddb5f5c
--- /dev/null
+++ b/0003-path_utils-path_concat-should-return-empty-string-on.patch
@@ -0,0 +1,153 @@
+From c4fdad249bf62d61856d26f97849e61351a356d5 Mon Sep 17 00:00:00 2001
+From: Stephen Gallagher <sgallagh at redhat.com>
+Date: Wed, 7 Mar 2012 09:29:46 -0500
+Subject: [PATCH] path_utils: path_concat should return empty string on
+ ENOBUFS
+
+Also clean up the code a bit and add more comments
+---
+ path_utils/path_utils.c    |   48 ++++++++++++++++++++++++++++++++++---------
+ path_utils/path_utils.h    |    3 +-
+ path_utils/path_utils_ut.c |   19 +++++++++++++---
+ 3 files changed, 55 insertions(+), 15 deletions(-)
+
+diff --git a/path_utils/path_utils.c b/path_utils/path_utils.c
+index 25ca4267fc0d7d9f3483646c2aef22fcdef1eb24..0a758c5bfd09ef5708e9f68d3aecc0733607e3d8 100644
+--- a/path_utils/path_utils.c
++++ b/path_utils/path_utils.c
+@@ -192,6 +192,7 @@ bool is_absolute_path(const char *path)
+ 
+ int path_concat(char *path, size_t path_size, const char *head, const char *tail)
+ {
++    int ret;
+     const char *p, *src;
+     char *dst, *dst_end;
+ 
+@@ -201,13 +202,27 @@ int path_concat(char *path, size_t path_size, const char *head, const char *tail
+     dst_end = path + path_size - 1;             /* -1 allows for NULL terminator */
+ 
+     if (head && *head) {
+-        for (p = head; *p; p++);                /* walk to end of head */
+-        for (p--; p > head && *p == '/'; p--); /* skip any trailing slashes in head */
+-        if ((p - head) > path_size-1) return ENOBUFS;
+-        for (src = head; src <= p && dst < dst_end;) *dst++ = *src++; /* copy head */
++        /* walk to end of head */
++        for (p = head; *p; p++);
++
++        /* skip any trailing slashes in head */
++        for (p--; p > head && *p == '/'; p--);
++
++        /* If the length of head exceeds the buffer size, fail */
++        if ((p - head) > path_size-1) {
++            ret = ENOBUFS;
++            goto fail;
++        }
++
++        /* Copy head into path */
++        for (src = head; src <= p && dst < dst_end;) {
++            *dst++ = *src++;
++        }
+     }
+     if (tail && *tail) {
+-        for (p = tail; *p && *p == '/'; p++);   /* skip any leading slashes in tail */
++        /* skip any leading slashes in tail */
++        for (p = tail; *p && *p == '/'; p++);
++
+         if (dst > path)
+             /* insert single slash between head & tail
+              * Making sure not to add an extra if the
+@@ -218,15 +233,28 @@ int path_concat(char *path, size_t path_size, const char *head, const char *tail
+             if (dst < dst_end && *(dst-1) != '/') {
+                 *dst++ = '/';
+             }
+-        for (src = p; *src && dst < dst_end;) *dst++ = *src++; /* copy tail */
+-        if (*src) return ENOBUFS; /* failed to copy everything */
++
++        /* Copy the tail into the path */
++        for (src = p; *src && dst < dst_end;) {
++            *dst++ = *src++;
++        }
++
++        /* If we got past dst_end and there is more data
++         * in the src buffer, we should return ENOBUFS
++         */
++        if (*src) {
++            ret = ENOBUFS; /* failed to copy everything */
++            goto fail;
++        }
+     }
+     *dst = 0;
+-    if (dst > dst_end) {
+-        return ENOBUFS;
+-    }
++
+     return SUCCESS;
+ 
++fail:
++    /* On failure, set the buffer to the empty string for safety */
++    *path = '\0';
++    return ret;
+ }
+ 
+ int make_path_absolute(char *absolute_path, size_t absolute_path_size, const char *path)
+diff --git a/path_utils/path_utils.h b/path_utils/path_utils.h
+index 2fd567c4eaa30ee1eb05af868d7d14b6e2a71a43..17ed1f4324a192c32d8229417d527424ef01ccd2 100644
+--- a/path_utils/path_utils.h
++++ b/path_utils/path_utils.h
+@@ -198,7 +198,8 @@ bool is_absolute_path(const char *path);
+  * @param[in]    tail           The second component of the path
+  *
+  * @return \c SUCCESS if successful, non-zero error code otherwise.
+- * \li \c ENOBUFS      If the buffer space is too small
++ * \li \c ENOBUFS      If the buffer space is too small. In this case,
++ *                     path will be set to an empty string.
+  */
+ int path_concat(char *path, size_t path_size, const char *head, const char *tail);
+ 
+diff --git a/path_utils/path_utils_ut.c b/path_utils/path_utils_ut.c
+index 34462cfdd4a2238f878a170fba2481b31f96e33e..aadd89b74420a4f8bc51ace779ecfb4223afa0e3 100644
+--- a/path_utils/path_utils_ut.c
++++ b/path_utils/path_utils_ut.c
+@@ -252,24 +252,35 @@ START_TEST(test_path_concat_neg)
+     char small[3];
+     char small2[5];
+     char small3[7];
+-    char p2[9];
++    char p2[10];
+ 
+     /* these two test different conditions */
+ 
+     /* Test if head is longer than the buffer */
+     fail_unless(path_concat(small, 3, "/foo", "bar") == ENOBUFS);
++    /* On ENOBUFS, path should be empty */
++    fail_unless_str_equal(small, "");
+ 
+     /* Test if head is the same length as the buffer */
+     fail_unless(path_concat(small2, 5, "/foo", "bar") == ENOBUFS);
++    /* On ENOBUFS, path should be empty */
++    fail_unless_str_equal(small2, "");
+ 
+     /* Test if head+tail is the longer than the buffer */
+     fail_unless(path_concat(small3, 7, "/foo", "bar") == ENOBUFS);
++    /* On ENOBUFS, path should be empty */
++    fail_unless_str_equal(small3, "");
+ 
+     /* off-by-one */
+-    p2[8] = 1; /* Check whether we've written too far */
++    /* Fill with garbage data for now */
++    memset(p2, 'Z', 9);
++    p2[9] = '\0';
++
+     fail_unless(path_concat(p2, 8, "/foo", "bar") == ENOBUFS);
+-    fail_unless(p2[8] == 1); /* This should be untouched */
+-    fail_unless_str_equal(p2, "/foo/ba");
++    /* Make sure we don't write past the end of the buffer */
++    fail_unless(p2[8] == 'Z', "Got [%d]", p2[8]);
++    /* On ENOBUFS, path should be empty */
++    fail_unless_str_equal(p2, "");
+ }
+ END_TEST
+ 
+-- 
+1.7.7.6
+
diff --git a/ding-libs.spec b/ding-libs.spec
index 389c8cf..0b47704 100644
--- a/ding-libs.spec
+++ b/ding-libs.spec
@@ -1,6 +1,6 @@
 Name: ding-libs
 Version: 0.1.3
-Release: 7%{?dist}
+Release: 8%{?dist}
 Summary: "Ding is not GLib" assorted utility libraries
 Group: Development/Libraries
 License: LGPLv3+
@@ -18,6 +18,7 @@ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
 
 Patch0001: 0001-path_utils-handle-off-by-one-error-in-path_concat.patch
 Patch0002: 0002-path_utils-Handle-in-path_concat.patch
+Patch0003: 0003-path_utils-path_concat-should-return-empty-string-on.patch
 
 ### Dependencies ###
 
@@ -252,6 +253,7 @@ structure
 
 %patch0001 -p1
 %patch0002 -p1
+%patch0003 -p1
 
 %build
 %configure \
@@ -285,6 +287,9 @@ rm -f */doc/html/installdox
 rm -rf $RPM_BUILD_ROOT
 
 %changelog
+* Tue Mar 06 2012 Stephen Gallagher <sgallagh at redhat.com> - 0.1.3-8
+- Make path_concat return empty string on ENOBUFS
+
 * Tue Mar 06 2012 Stephen Gallagher <sgallagh at redhat.com> - 0.1.3-7
 - Fix off-by-one bug in path_concat()
 - Resolves: rhbz#799347 - path_utils:test_path_concat_neg fails on 64-bit big


More information about the scm-commits mailing list