Accommodate POSIX basename(3) that takes a non-const parameter and
may modify the string buffer.

There were only two compiler warnings about discarded const, but
there are numerous instances where the code assumes non-POSIX
semantics for basename() and dirname().  Given that there is at
least a FreeBSD port of OpenCVS, cleaning this up is more than
cosmetic.

This could definitely use proofreading.

I chose __func__ (otherwise not used anywhere) over breaking an overly
long "function_" "name" into parts like that.

OK?

Index: usr.bin/cvs/admin.c
===================================================================
RCS file: /cvs/src/usr.bin/cvs/admin.c,v
retrieving revision 1.68
diff -u -p -r1.68 admin.c
--- usr.bin/cvs/admin.c 1 Jun 2017 08:08:24 -0000       1.68
+++ usr.bin/cvs/admin.c 16 Oct 2020 21:14:05 -0000
@@ -246,12 +246,17 @@ cvs_admin_local(struct cvs_file *cf)
                struct cvs_file *ocf;
                struct rcs_access *acp;
                int ofd;
-               char *d, *f, fpath[PATH_MAX], repo[PATH_MAX];
+               char *d, dbuf[PATH_MAX], *f, fbuf[PATH_MAX];
+               char fpath[PATH_MAX], repo[PATH_MAX];
 
-
-               if ((f = basename(oldfilename)) == NULL)
+               if (strlcpy(fbuf, oldfilename, sizeof(fbuf)) >= sizeof(fbuf))
+                       fatal("cvs_admin_local: truncation");
+               if ((f = basename(fbuf)) == NULL)
                        fatal("cvs_admin_local: basename failed");
-               if ((d = dirname(oldfilename)) == NULL)
+
+               if (strlcpy(dbuf, oldfilename, sizeof(dbuf)) >= sizeof(dbuf))
+                       fatal("cvs_admin_local: truncation");
+               if ((d = dirname(dbuf)) == NULL)
                        fatal("cvs_admin_local: dirname failed");
 
                cvs_get_repository_path(d, repo, PATH_MAX);
Index: usr.bin/cvs/checkout.c
===================================================================
RCS file: /cvs/src/usr.bin/cvs/checkout.c,v
retrieving revision 1.171
diff -u -p -r1.171 checkout.c
--- usr.bin/cvs/checkout.c      1 Jun 2017 08:08:24 -0000       1.171
+++ usr.bin/cvs/checkout.c      16 Oct 2020 21:46:33 -0000
@@ -239,7 +239,7 @@ checkout_check_repository(int argc, char
        struct module_checkout *mc;
        struct cvs_ignpat *ip;
        struct cvs_filelist *fl, *nxt;
-       char repo[PATH_MAX], fpath[PATH_MAX], *f[1];
+       char repo[PATH_MAX], fpath[PATH_MAX], path[PATH_MAX], *f[1];
 
        build_dirs = print_stdout ? 0 : 1;
 
@@ -329,14 +329,25 @@ checkout_check_repository(int argc, char
                                cr.flags = flags;
 
                                if (!(mc->mc_flags & MODULE_ALIAS)) {
+                                       if (strlcpy(path, fl->file_path,
+                                           sizeof(path)) >= sizeof(path))
+                                               fatal("%s: truncation",
+                                                   __func__);
                                        module_repo_root =
-                                           xstrdup(dirname(fl->file_path));
+                                           xstrdup(dirname(path));
                                        d = wdir;
+                                       if (strlcpy(path, fl->file_path,
+                                           sizeof(path)) >= sizeof(path))
+                                               fatal("%s: truncation",
+                                                   __func__);
                                        (void)xsnprintf(fpath, sizeof(fpath),
-                                           "%s/%s", d,
-                                           basename(fl->file_path));
+                                           "%s/%s", d, basename(path));
                                } else {
-                                       d = dirname(wdir);
+                                       if (strlcpy(path, wdir,
+                                           sizeof(path)) >= sizeof(path))
+                                               fatal("%s: truncation",
+                                                   __func__);
+                                       d = dirname(path);
                                        strlcpy(fpath, fl->file_path,
                                            sizeof(fpath));
                                }
@@ -387,7 +398,7 @@ checkout_check_repository(int argc, char
 static int
 checkout_classify(const char *repo, const char *arg)
 {
-       char *d, *f, fpath[PATH_MAX];
+       char *d, dbuf[PATH_MAX], *f, fbuf[PATH_MAX], fpath[PATH_MAX];
        struct stat sb;
 
        if (stat(repo, &sb) == 0) {
@@ -395,8 +406,13 @@ checkout_classify(const char *repo, cons
                        return CVS_DIR;
        }
 
-       d = dirname(repo);
-       f = basename(repo);
+       if (strlcpy(dbuf, repo, sizeof(dbuf)) >= sizeof(dbuf))
+               fatal("checkout_classify: truncation");
+       d = dirname(dbuf);
+
+       if (strlcpy(fbuf, repo, sizeof(fbuf)) >= sizeof(fbuf))
+               fatal("checkout_classify: truncation");
+       f = basename(fbuf);
 
        (void)xsnprintf(fpath, sizeof(fpath), "%s/%s%s", d, f, RCS_FILE_EXT);
        if (stat(fpath, &sb) == 0) {
Index: usr.bin/cvs/client.c
===================================================================
RCS file: /cvs/src/usr.bin/cvs/client.c,v
retrieving revision 1.128
diff -u -p -r1.128 client.c
--- usr.bin/cvs/client.c        14 Jul 2018 21:28:02 -0000      1.128
+++ usr.bin/cvs/client.c        16 Oct 2020 21:17:10 -0000
@@ -157,6 +157,7 @@ client_check_directory(char *data, char 
 {
        CVSENTRIES *entlist;
        char *entry, *parent, *base, *p;
+       char basebuf[PATH_MAX], parentbuf[PATH_MAX];
 
        STRIP_SLASH(data);
 
@@ -174,10 +175,14 @@ client_check_directory(char *data, char 
        if (cvs_cmdop == CVS_OP_EXPORT)
                return;
 
-       if ((base = basename(data)) == NULL)
+       if (strlcpy(basebuf, data, sizeof(basebuf)) >= sizeof(basebuf))
+               fatal("client_check_directory: truncation");
+       if ((base = basename(basebuf)) == NULL)
                fatal("client_check_directory: overflow");
 
-       if ((parent = dirname(data)) == NULL)
+       if (strlcpy(parentbuf, data, sizeof(parentbuf)) >= sizeof(parentbuf))
+               fatal("client_check_directory: truncation");
+       if ((parent = dirname(parentbuf)) == NULL)
                fatal("client_check_directory: overflow");
 
        if (!strcmp(parent, "."))
@@ -796,7 +801,7 @@ cvs_client_merged(char *data)
        struct timeval tv[2];
        struct tm datetm;
        char timebuf[CVS_TIME_BUFSZ], *repo, *rpath, *entry, *mode;
-       char *len, *fpath, *wdir;
+       char *len, *fpath, *wdir, wdirbuf[PATH_MAX];
 
        if (data == NULL)
                fatal("Missing argument for Merged");
@@ -817,7 +822,9 @@ cvs_client_merged(char *data)
                fatal("received a repository path that is too short");
 
        fpath = rpath + strlen(repo) + 1;
-       if ((wdir = dirname(fpath)) == NULL)
+       if (strlcpy(wdirbuf, fpath, sizeof(wdirbuf)) >= sizeof(wdirbuf))
+               fatal("cvs_client_merged: truncation");
+       if ((wdir = dirname(wdirbuf)) == NULL)
                fatal("cvs_client_merged: dirname: %s", strerror(errno));
        free(repo);
 
Index: usr.bin/cvs/file.c
===================================================================
RCS file: /cvs/src/usr.bin/cvs/file.c,v
retrieving revision 1.273
diff -u -p -r1.273 file.c
--- usr.bin/cvs/file.c  1 Jun 2017 08:38:56 -0000       1.273
+++ usr.bin/cvs/file.c  16 Oct 2020 21:22:27 -0000
@@ -265,7 +265,8 @@ cvs_file_walklist(struct cvs_flisthead *
        struct stat st;
        struct cvs_file *cf;
        struct cvs_filelist *l, *nxt;
-       char *d, *f, repo[PATH_MAX], fpath[PATH_MAX];
+       char *d, dbuf[PATH_MAX], *f, fbuf[PATH_MAX];
+       char repo[PATH_MAX], fpath[PATH_MAX];
 
        for (l = RB_MIN(cvs_flisthead, fl); l != NULL; l = nxt) {
                if (cvs_quit)
@@ -274,9 +275,14 @@ cvs_file_walklist(struct cvs_flisthead *
                cvs_log(LP_TRACE, "cvs_file_walklist: element '%s'",
                    l->file_path);
 
-               if ((f = basename(l->file_path)) == NULL)
+               if (strlcpy(fbuf, l->file_path, sizeof(fbuf)) >= sizeof(fbuf))
+                       fatal("cvs_file_walklist: truncation");
+               if ((f = basename(fbuf)) == NULL)
                        fatal("cvs_file_walklist: basename failed");
-               if ((d = dirname(l->file_path)) == NULL)
+
+               if (strlcpy(dbuf, l->file_path, sizeof(dbuf)) >= sizeof(dbuf))
+                       fatal("cvs_file_walklist: truncation");
+               if ((d = dirname(dbuf)) == NULL)
                        fatal("cvs_file_walklist: dirname failed");
 
                type = l->type;
Index: usr.bin/cvs/logmsg.c
===================================================================
RCS file: /cvs/src/usr.bin/cvs/logmsg.c,v
retrieving revision 1.60
diff -u -p -r1.60 logmsg.c
--- usr.bin/cvs/logmsg.c        28 May 2017 16:57:01 -0000      1.60
+++ usr.bin/cvs/logmsg.c        16 Oct 2020 21:10:42 -0000
@@ -100,6 +100,7 @@ cvs_logmsg_create(char *dir, struct cvs_
        struct cvs_filelist *cf;
        struct stat st1, st2;
        char *fpath, *logmsg, repo[PATH_MAX];
+       char *f, path[PATH_MAX];
        struct stat st;
        struct trigger_list *line_list;
        struct trigger_line *line;
@@ -165,28 +166,46 @@ cvs_logmsg_create(char *dir, struct cvs_
 
        if (added != NULL && !RB_EMPTY(added)) {
                fprintf(fp, "%s Added Files:", CVS_LOGMSG_PREFIX);
-               RB_FOREACH(cf, cvs_flisthead, added)
-                       fprintf(fp, "\n%s \t%s ", CVS_LOGMSG_PREFIX,
-                           dir != NULL ? basename(cf->file_path) :
-                           cf->file_path);
+               RB_FOREACH(cf, cvs_flisthead, added) {
+                       f = cf->file_path;
+                       if (dir != NULL) {
+                               if (strlcpy(path, f, sizeof(path)) >=
+                                   sizeof(path))
+                                       fatal("cvs_logmsg_create: truncation");
+                               f = basename(path);
+                       }
+                       fprintf(fp, "\n%s \t%s ", CVS_LOGMSG_PREFIX, f);
+               }
                fputs("\n", fp);
        }
 
        if (removed != NULL && !RB_EMPTY(removed)) {
                fprintf(fp, "%s Removed Files:", CVS_LOGMSG_PREFIX);
-               RB_FOREACH(cf, cvs_flisthead, removed)
-                       fprintf(fp, "\n%s \t%s ", CVS_LOGMSG_PREFIX,
-                           dir != NULL ? basename(cf->file_path) :
-                           cf->file_path);
+               RB_FOREACH(cf, cvs_flisthead, removed) {
+                       f = cf->file_path;
+                       if (dir != NULL) {
+                               if (strlcpy(path, f, sizeof(path)) >=
+                                   sizeof(path))
+                                       fatal("cvs_logmsg_create: truncation");
+                               f = basename(path);
+                       }
+                       fprintf(fp, "\n%s \t%s ", CVS_LOGMSG_PREFIX, f);
+               }
                fputs("\n", fp);
        }
 
        if (modified != NULL && !RB_EMPTY(modified)) {
                fprintf(fp, "%s Modified Files:", CVS_LOGMSG_PREFIX);
-               RB_FOREACH(cf, cvs_flisthead, modified)
-                       fprintf(fp, "\n%s \t%s ", CVS_LOGMSG_PREFIX,
-                           dir != NULL ? basename(cf->file_path) :
-                           cf->file_path);
+               RB_FOREACH(cf, cvs_flisthead, modified) {
+                       f = cf->file_path;
+                       if (dir != NULL) {
+                               if (strlcpy(path, f, sizeof(path)) >=
+                                   sizeof(path))
+                                       fatal("cvs_logmsg_create: truncation");
+                               f = basename(path);
+                       }
+                       fprintf(fp, "\n%s \t%s ", CVS_LOGMSG_PREFIX, f);
+               }
                fputs("\n", fp);
        }
 
Index: usr.bin/cvs/rcs.c
===================================================================
RCS file: /cvs/src/usr.bin/cvs/rcs.c,v
retrieving revision 1.319
diff -u -p -r1.319 rcs.c
--- usr.bin/cvs/rcs.c   28 Jun 2019 13:35:00 -0000      1.319
+++ usr.bin/cvs/rcs.c   16 Oct 2020 21:35:27 -0000
@@ -2183,8 +2183,8 @@ rcs_kwexp_line(char *rcsfile, struct rcs
        int kwtype;
        u_int j, found;
        const u_char *c, *start, *fin, *end;
-       char *kwstr;
-       char expbuf[256], buf[256];
+       char *kwstr, *rcsfile_basename;
+       char expbuf[256], buf[256], path[PATH_MAX];
        size_t clen, kwlen, len, tlen;
 
        kwtype = 0;
@@ -2202,6 +2202,10 @@ rcs_kwexp_line(char *rcsfile, struct rcs
        /* Final character in buffer. */
        fin = c + len - 1;
 
+       if (strlcpy(path, rcsfile, sizeof(path)) >= sizeof(path))
+               fatal("rcs_kwexp_line: truncation");
+       rcsfile_basename = basename(path);
+
        /*
         * Keyword formats:
         * $Keyword$
@@ -2300,7 +2304,7 @@ rcs_kwexp_line(char *rcsfile, struct rcs
                if (mode & RCS_KWEXP_VAL) {
                        if (kwtype & RCS_KW_RCSFILE) {
                                if (!(kwtype & RCS_KW_FULLPATH))
-                                       (void)strlcat(expbuf, basename(rcsfile),
+                                       (void)strlcat(expbuf, rcsfile_basename,
                                            sizeof(expbuf));
                                else
                                        (void)strlcat(expbuf, rcsfile,
@@ -2376,7 +2380,7 @@ rcs_kwexp_line(char *rcsfile, struct rcs
                                /* Log line */
                                if (!(kwtype & RCS_KW_FULLPATH))
                                        (void)strlcat(expbuf,
-                                           basename(rcsfile), sizeof(expbuf));
+                                           rcsfile_basename, sizeof(expbuf));
                                else
                                        (void)strlcat(expbuf, rcsfile,
                                            sizeof(expbuf));
Index: usr.bin/cvs/server.c
===================================================================
RCS file: /cvs/src/usr.bin/cvs/server.c,v
retrieving revision 1.105
diff -u -p -r1.105 server.c
--- usr.bin/cvs/server.c        28 Aug 2017 19:33:20 -0000      1.105
+++ usr.bin/cvs/server.c        16 Oct 2020 21:38:08 -0000
@@ -324,6 +324,7 @@ cvs_server_directory(char *data)
 {
        CVSENTRIES *entlist;
        char *dir, *repo, *parent, *entry, *dirn, *p;
+       char parentbuf[PATH_MAX], dirnbuf[PATH_MAX];
 
        if (current_cvsroot == NULL)
                fatal("No Root specified for Directory");
@@ -350,10 +351,14 @@ cvs_server_directory(char *data)
 
        cvs_mkpath(p, NULL);
 
-       if ((dirn = basename(p)) == NULL)
+       if (strlcpy(dirnbuf, p, sizeof(dirnbuf)) >= sizeof(dirnbuf))
+               fatal("cvs_server_directory: truncation");
+       if ((dirn = basename(dirnbuf)) == NULL)
                fatal("cvs_server_directory: %s", strerror(errno));
 
-       if ((parent = dirname(p)) == NULL)
+       if (strlcpy(parentbuf, p, sizeof(parentbuf)) >= sizeof(parentbuf))
+               fatal("cvs_server_directory: truncation");
+       if ((parent = dirname(parentbuf)) == NULL)
                fatal("cvs_server_directory: %s", strerror(errno));
 
        if (strcmp(parent, ".")) {
-- 
Christian "naddy" Weisgerber                          [email protected]

Reply via email to