]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
api.c: cg_build_path_locked() - work around snprintf() warnings
authorKamalesh Babulal <kamalesh.babulal@oracle.com>
Wed, 8 Feb 2023 06:55:10 +0000 (12:25 +0530)
committerTom Hromatka <tom.hromatka@oracle.com>
Fri, 10 Feb 2023 21:13:16 +0000 (14:13 -0700)
Recent gcc are unhappy when sizeof(dest) <= sizeof(src) with
snprintf()'s. We could need too many strncpy()'s and strcat()'s for
constructing file path, so let's workaround it by allocating long
enough space for keeping snprintf() happy and then use the temporarily
allocated array and use it as src for strncpy() with limit of
FILENAME_MAX.

Signed-off-by: Kamalesh Babulal <kamalesh.babulal@oracle.com>
Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com>
src/api.c

index f304d2f4f7b24ace4cf465d328f14ded62a06c35..984bab967a3044839cf9a39950081e1c2ef9d8b0 100644 (file)
--- a/src/api.c
+++ b/src/api.c
@@ -1680,7 +1680,24 @@ static char *cg_concat_path(const char *pref, const char *suf, char *path)
 /* path value have to have size at least FILENAME_MAX */
 char *cg_build_path_locked(const char *name, char *path, const char *type)
 {
-       int i, ret;
+       /*
+        * len is the allocation size for path, that stores:
+        * cg_mount_table[i].mount.path + '/' + cg_namespace_table[i] + '/'
+        */
+       int i, ret, len = (FILENAME_MAX * 2) + 2;
+       char *_path;
+
+       /*
+        * Recent gcc are unhappy when sizeof(dest) <= sizeof(src) with
+        * snprintf()'s.  Alternative is to use multiple strncpy()/strcat(),
+        * work around it by allocating large temporary buffer _path and
+        * copying the constructed _path into path.
+        */
+       _path = malloc(len);
+       if (!_path) {
+               cgroup_err("Failed to allocate memory for _path\n");
+               return NULL;
+       }
 
        /*
         * If no type is specified, and there's a valid cgroup v2 mount, then
@@ -1689,21 +1706,26 @@ char *cg_build_path_locked(const char *name, char *path, const char *type)
         * any controller.
         */
        if (!type && strlen(cg_cgroup_v2_mount_path) > 0) {
-               ret = snprintf(path, FILENAME_MAX, "%s/", cg_cgroup_v2_mount_path);
+               ret = snprintf(_path, len, "%s/", cg_cgroup_v2_mount_path);
                if (ret >= FILENAME_MAX)
-                       cgroup_dbg("filename too long: %s/", cg_cgroup_v2_mount_path);
+                       cgroup_dbg("filename too long: %s", _path);
+
+               strncpy(path, _path, FILENAME_MAX - 1);
+               path[FILENAME_MAX - 1] = '\0';
 
                if (name) {
                        char *tmp;
 
                        tmp = strdup(path);
-                       if (tmp == NULL)
-                               return NULL;
+                       if (tmp == NULL) {
+                               path = NULL;
+                               goto out;
+                       }
 
                        cg_concat_path(tmp, name, path);
                        free(tmp);
                }
-               return path;
+               goto out;
        }
 
        for (i = 0; cg_mount_table[i].name[0] != '\0'; i++) {
@@ -1717,23 +1739,17 @@ char *cg_build_path_locked(const char *name, char *path, const char *type)
                    (type && strcmp(type, CGROUP_FILE_PREFIX) == 0 &&
                     cg_mount_table[i].version == CGROUP_V2)) {
 
-                       if (cg_namespace_table[i]) {
-                               ret = snprintf(path, FILENAME_MAX, "%s/%s/",
-                                               cg_mount_table[i].mount.path,
-                                               cg_namespace_table[i]);
-                               if (ret >= FILENAME_MAX) {
-                                       cgroup_dbg("filename too long:%s/%s/",
-                                                  cg_mount_table[i].mount.path,
-                                                  cg_namespace_table[i]);
-                               }
-                       } else {
-                               ret = snprintf(path, FILENAME_MAX, "%s/",
-                                              cg_mount_table[i].mount.path);
-                               if (ret >= FILENAME_MAX) {
-                                       cgroup_dbg("filename too long:%s/",
-                                                  cg_mount_table[i].mount.path);
-                               }
-                       }
+                       if (cg_namespace_table[i])
+                               ret = snprintf(_path, len, "%s/%s/", cg_mount_table[i].mount.path,
+                                              cg_namespace_table[i]);
+                       else
+                               ret = snprintf(_path, len, "%s/", cg_mount_table[i].mount.path);
+
+                       if (ret >= FILENAME_MAX)
+                               cgroup_dbg("filename too long: %s", _path);
+
+                       strncpy(path, _path, FILENAME_MAX - 1);
+                       path[FILENAME_MAX - 1] = '\0';
 
                        if (name) {
                                char *tmp;
@@ -1745,10 +1761,16 @@ char *cg_build_path_locked(const char *name, char *path, const char *type)
                                cg_concat_path(tmp, name, path);
                                free(tmp);
                        }
-                       return path;
+                       goto out;
                }
        }
-       return NULL;
+       path = NULL;
+
+out:
+       if (_path)
+               free(_path);
+
+       return path;
 }
 
 char *cg_build_path(const char *name, char *path, const char *type)