From: Alejandro Colomar Date: Fri, 25 Aug 2023 19:27:05 +0000 (+0200) Subject: lib/, src/: Use asprintf(3) instead of strlen(3)+malloc(3)+snprintf(3) X-Git-Tag: 4.15.0-rc1~151 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ad3b31a59ee853598743e0cab47fa1360b4a5fb9;p=thirdparty%2Fshadow.git lib/, src/: Use asprintf(3) instead of strlen(3)+malloc(3)+snprintf(3) asprintf(3) is non-standard, but is provided by GNU, the BSDs, and musl. That makes it portable enough for us to use. This function is much simpler than the burdensome code for allocating the right size. Being simpler, it's thus safer. I took the opportunity to fix the style to my preferred one in the definitions of variables used in these calls, and also in the calls to free(3) with these pointers. That isn't gratuituous, but has a reason: it makes those appear in the diff for this patch, which helps review it. Oh, well, I had an excuse :) Reviewed-by: Iker Pedrosa Signed-off-by: Alejandro Colomar --- diff --git a/lib/commonio.c b/lib/commonio.c index 6d744ad14..df2986aaa 100644 --- a/lib/commonio.c +++ b/lib/commonio.c @@ -33,6 +33,7 @@ #include "commonio.h" #include "shadowlog_internal.h" + /* local function prototypes */ static int lrename (const char *, const char *); static int check_link_count (const char *file, bool log); @@ -354,33 +355,25 @@ bool commonio_present (const struct commonio_db *db) int commonio_lock_nowait (struct commonio_db *db, bool log) { - char* file = NULL; - char* lock = NULL; - size_t lock_file_len; - size_t file_len; - int err = 0; + int err = 0; + char *file = NULL; + char *lock = NULL; if (db->locked) { return 1; } - file_len = strlen(db->filename) + 11;/* %lu max size */ - lock_file_len = strlen(db->filename) + 6; /* sizeof ".lock" */ - file = MALLOC(file_len, char); - if (file == NULL) { + + if (asprintf(&file, "%s.%ju", db->filename, (uintmax_t) getpid()) == -1) goto cleanup_ENOMEM; - } - lock = MALLOC(lock_file_len, char); - if (lock == NULL) { + if (asprintf(&lock, "%s.lock", db->filename) == -1) goto cleanup_ENOMEM; - } - snprintf (file, file_len, "%s.%lu", - db->filename, (unsigned long) getpid ()); - snprintf (lock, lock_file_len, "%s.lock", db->filename); + if (do_lock_file (file, lock, log) != 0) { db->locked = true; lock_count++; err = 1; } + cleanup_ENOMEM: free(file); free(lock); diff --git a/lib/copydir.c b/lib/copydir.c index 36f2004d1..d60cf535b 100644 --- a/lib/copydir.c +++ b/lib/copydir.c @@ -208,11 +208,7 @@ static void remove_link (/*@only@*/struct link_name *ln) static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, const struct stat *sb) { - struct link_name *lp; - size_t src_len; - size_t dst_len; - size_t name_len; - size_t len; + struct link_name *lp; /* copy_tree () must be the entry point */ assert (NULL != src_orig); @@ -229,15 +225,11 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c } lp = XMALLOC(1, struct link_name); - src_len = strlen (src_orig); - dst_len = strlen (dst_orig); - name_len = strlen (name); lp->ln_dev = sb->st_dev; lp->ln_ino = sb->st_ino; lp->ln_count = sb->st_nlink; - len = name_len - src_len + dst_len + 1; - lp->ln_name = XMALLOC(len, char); - (void) snprintf (lp->ln_name, len, "%s%s", dst_orig, name + src_len); + if (asprintf(&lp->ln_name, "%s%s", dst_orig, name + strlen(src_orig)) == -1) + exit(EXIT_FAILURE); lp->ln_next = links; links = lp; @@ -314,8 +306,9 @@ static int copy_tree_impl (const struct path_info *src, const struct path_info * set_orig = true; } while ((0 == err) && (ent = readdir (dir)) != NULL) { - char *src_name, *dst_name; - size_t src_len, dst_len; + char *src_name = NULL; + char *dst_name; + struct path_info src_entry, dst_entry; /* * Skip the "." and ".." entries */ @@ -325,26 +318,16 @@ static int copy_tree_impl (const struct path_info *src, const struct path_info * continue; } - src_len = strlen (ent->d_name) + 2; - dst_len = strlen (ent->d_name) + 2; - src_len += strlen (src->full_path); - dst_len += strlen (dst->full_path); - - src_name = MALLOC(src_len, char); - dst_name = MALLOC(dst_len, char); - - if ((NULL == src_name) || (NULL == dst_name)) { + if (asprintf(&src_name, "%s/%s", src->full_path, ent->d_name) == -1) + { + err = -1; + continue; + } + if (asprintf(&dst_name, "%s/%s", dst->full_path, ent->d_name) == -1) + { err = -1; goto skip; } - /* - * Build the filename for both the source and - * the destination files. - */ - struct path_info src_entry, dst_entry; - - (void) snprintf (src_name, src_len, "%s/%s", src->full_path, ent->d_name); - (void) snprintf (dst_name, dst_len, "%s/%s", dst->full_path, ent->d_name); src_entry.full_path = src_name; src_entry.dirfd = dirfd(dir); @@ -356,9 +339,10 @@ static int copy_tree_impl (const struct path_info *src, const struct path_info * err = copy_entry(&src_entry, &dst_entry, reset_selinux, old_uid, new_uid, old_gid, new_gid); + + free(dst_name); skip: - free (src_name); - free (dst_name); + free(src_name); } (void) closedir (dir); (void) close (dst_fd); @@ -625,12 +609,11 @@ static int copy_symlink (const struct path_info *src, const struct path_info *ds * directory. */ if (strncmp (oldlink, src_orig, strlen (src_orig)) == 0) { - size_t len = strlen (dst_orig) + strlen (oldlink) - strlen (src_orig) + 1; - char *dummy = XMALLOC(len, char); - (void) snprintf (dummy, len, "%s%s", - dst_orig, - oldlink + strlen (src_orig)); - free (oldlink); + char *dummy; + + if (asprintf(&dummy, "%s%s", dst_orig, oldlink + strlen(src_orig)) == -1) + exit(EXIT_FAILURE); + free(oldlink); oldlink = dummy; } diff --git a/lib/env.c b/lib/env.c index e4ccee3d7..c9c03c9be 100644 --- a/lib/env.c +++ b/lib/env.c @@ -20,6 +20,8 @@ #include "prototypes.h" #include "defines.h" #include "shadowlog.h" + + /* * NEWENVP_STEP must be a power of two. This is the number * of (char *) pointers to allocate at a time, to avoid using @@ -67,16 +69,12 @@ void initenv (void) void addenv (const char *string, /*@null@*/const char *value) { - char *cp, *newstring; - size_t i; - size_t n; + char *cp, *newstring; + size_t i, n; if (NULL != value) { - size_t len = strlen (string) + strlen (value) + 2; - int wlen; - newstring = XMALLOC(len, char); - wlen = snprintf (newstring, len, "%s=%s", string, value); - assert (wlen == (int) len -1); + if (asprintf(&newstring, "%s=%s", string, value) == -1) + exit(EXIT_FAILURE); } else { newstring = xstrdup (string); } @@ -88,7 +86,7 @@ void addenv (const char *string, /*@null@*/const char *value) cp = strchr (newstring, '='); if (NULL == cp) { - free (newstring); + free(newstring); return; } @@ -105,7 +103,7 @@ void addenv (const char *string, /*@null@*/const char *value) } if (i < newenvc) { - free (newenvp[i]); + free(newenvp[i]); newenvp[i] = newstring; return; } diff --git a/lib/getdef.c b/lib/getdef.c index 7fe6cefba..585e8244f 100644 --- a/lib/getdef.c +++ b/lib/getdef.c @@ -26,6 +26,7 @@ #include "getdef.h" #include "shadowlog_internal.h" + /* * A configuration item definition. */ @@ -444,21 +445,14 @@ out: void setdef_config_file (const char* file) { #ifdef USE_ECONF - size_t len; - char* cp; - - len = strlen(file) + strlen(sysconfdir) + 2; - cp = MALLOC(len, char); - if (cp == NULL) - exit (13); - snprintf(cp, len, "%s/%s", file, sysconfdir); + char *cp; + + if (asprintf(&cp, "%s/%s", file, sysconfdir) == -1) + exit(13); sysconfdir = cp; #ifdef VENDORDIR - len = strlen(file) + strlen(vendordir) + 2; - cp = MALLOC(len, char); - if (cp == NULL) - exit (13); - snprintf(cp, len, "%s/%s", file, vendordir); + if (asprintf(&cp, "%s/%s", file, vendordir) == -1) + exit(13); vendordir = cp; #endif #else diff --git a/lib/groupio.c b/lib/groupio.c index abad2cbfd..d9d9823bb 100644 --- a/lib/groupio.c +++ b/lib/groupio.c @@ -22,6 +22,7 @@ #include "getdef.h" #include "groupio.h" + static /*@null@*/struct commonio_entry *merge_group_entries ( /*@null@*/ /*@returned@*/struct commonio_entry *gr1, /*@null@*/struct commonio_entry *gr2); @@ -300,12 +301,13 @@ static /*@null@*/struct commonio_entry *merge_group_entries ( /*@null@*/ /*@returned@*/struct commonio_entry *gr1, /*@null@*/struct commonio_entry *gr2) { - struct group *gptr1; - struct group *gptr2; - char **new_members; - size_t members = 0; - char *new_line; - size_t new_line_len, i; + char *new_line; + char **new_members; + size_t i; + size_t members = 0; + struct group *gptr1; + struct group *gptr2; + if (NULL == gr2 || NULL == gr1) { errno = EINVAL; return NULL; @@ -319,12 +321,8 @@ static /*@null@*/struct commonio_entry *merge_group_entries ( } /* Concatenate the 2 lines */ - new_line_len = strlen (gr1->line) + strlen (gr2->line) +1; - new_line = MALLOC(new_line_len + 1, char); - if (NULL == new_line) { + if (asprintf(&new_line, "%s\n%s", gr1->line, gr2->line) == -1) return NULL; - } - snprintf(new_line, new_line_len + 1, "%s\n%s", gr1->line, gr2->line); /* Concatenate the 2 list of members */ for (i=0; NULL != gptr1->gr_mem[i]; i++); @@ -343,7 +341,7 @@ static /*@null@*/struct commonio_entry *merge_group_entries ( } new_members = CALLOC (members + 1, char *); if (NULL == new_members) { - free (new_line); + free(new_line); return NULL; } for (i=0; NULL != gptr1->gr_mem[i]; i++) { diff --git a/lib/mail.c b/lib/mail.c index 304063f54..ede35f9e8 100644 --- a/lib/mail.c +++ b/lib/mail.c @@ -35,22 +35,19 @@ void mailcheck (void) */ mailbox = getenv ("MAILDIR"); if (NULL != mailbox) { - char *newmail; - size_t len = strlen (mailbox) + 5; - int wlen; + char *newmail; - newmail = XMALLOC(len, char); - wlen = snprintf (newmail, len, "%s/new", mailbox); - assert (wlen == (int) len - 1); + if (asprintf(&newmail, "%s/new", mailbox) == -1) + exit(EXIT_FAILURE); if (stat (newmail, &statbuf) != -1 && statbuf.st_size != 0) { if (statbuf.st_mtime > statbuf.st_atime) { - free (newmail); + free(newmail); (void) puts (_("You have new mail.")); return; } } - free (newmail); + free(newmail); } mailbox = getenv ("MAIL"); diff --git a/lib/prefix_flag.c b/lib/prefix_flag.c index adab9974c..7e1433079 100644 --- a/lib/prefix_flag.c +++ b/lib/prefix_flag.c @@ -29,6 +29,7 @@ #include "getdef.h" #include "shadowlog.h" + static char *passwd_db_file = NULL; static char *spw_db_file = NULL; static char *group_db_file = NULL; @@ -104,50 +105,43 @@ extern const char* process_prefix_flag (const char* short_opt, int argc, char ** log_get_progname()); exit (E_BAD_ARG); } - size_t len; - len = strlen(prefix) + strlen(PASSWD_FILE) + 2; - passwd_db_file = XMALLOC(len, char); - snprintf(passwd_db_file, len, "%s/%s", prefix, PASSWD_FILE); + + if (asprintf(&passwd_db_file, "%s/%s", prefix, PASSWD_FILE) == -1) + exit(EXIT_FAILURE); pw_setdbname(passwd_db_file); - len = strlen(prefix) + strlen(GROUP_FILE) + 2; - group_db_file = XMALLOC(len, char); - snprintf(group_db_file, len, "%s/%s", prefix, GROUP_FILE); + if (asprintf(&group_db_file, "%s/%s", prefix, GROUP_FILE) == -1) + exit(EXIT_FAILURE); gr_setdbname(group_db_file); #ifdef SHADOWGRP - len = strlen(prefix) + strlen(SGROUP_FILE) + 2; - sgroup_db_file = XMALLOC(len, char); - snprintf(sgroup_db_file, len, "%s/%s", prefix, SGROUP_FILE); + if (asprintf(&sgroup_db_file, "%s/%s", prefix, SGROUP_FILE) == -1) + exit(EXIT_FAILURE); sgr_setdbname(sgroup_db_file); #endif #ifdef USE_NIS __setspNIS(0); /* disable NIS for now, at least until it is properly supporting a "prefix" */ #endif - len = strlen(prefix) + strlen(SHADOW_FILE) + 2; - spw_db_file = XMALLOC(len, char); - snprintf(spw_db_file, len, "%s/%s", prefix, SHADOW_FILE); + if (asprintf(&spw_db_file, "%s/%s", prefix, SHADOW_FILE) == -1) + exit(EXIT_FAILURE); spw_setdbname(spw_db_file); #ifdef ENABLE_SUBIDS - len = strlen(prefix) + strlen("/etc/subuid") + 2; - suid_db_file = XMALLOC(len, char); - snprintf(suid_db_file, len, "%s/%s", prefix, "/etc/subuid"); + if (asprintf(&suid_db_file, "%s/%s", prefix, "/etc/subuid") == -1) + exit(EXIT_FAILURE); sub_uid_setdbname(suid_db_file); - len = strlen(prefix) + strlen("/etc/subgid") + 2; - sgid_db_file = XMALLOC(len, char); - snprintf(sgid_db_file, len, "%s/%s", prefix, "/etc/subgid"); + if (asprintf(&sgid_db_file, "%s/%s", prefix, "/etc/subgid") == -1) + exit(EXIT_FAILURE); sub_gid_setdbname(sgid_db_file); #endif #ifdef USE_ECONF setdef_config_file(prefix); #else - len = strlen(prefix) + strlen("/etc/login.defs") + 2; - def_conf_file = XMALLOC(len, char); - snprintf(def_conf_file, len, "%s/%s", prefix, "/etc/login.defs"); + if (asprintf(&def_conf_file, "%s/%s", prefix, "/etc/login.defs") == -1) + exit(EXIT_FAILURE); setdef_config_file(def_conf_file); #endif } diff --git a/lib/run_part.c b/lib/run_part.c index 3d0483d23..bd24d357e 100644 --- a/lib/run_part.c +++ b/lib/run_part.c @@ -13,6 +13,7 @@ #include "run_part.h" #include "shadowlog_internal.h" + int run_part (char *script_path, const char *name, const char *action) { int pid; @@ -55,25 +56,22 @@ int run_parts (const char *directory, const char *name, const char *action) } for (n=0; nd_name) + 2; - char *s = MALLOC(path_length, char); - if (!s) { - printf ("could not allocate memory\n"); + if (asprintf(&s, "%s/%s", directory, namelist[n]->d_name) == -1) { + fprintf(stderr, "could not allocate memory\n"); for (; nd_name); execute_result = 0; if (stat (s, &sb) == -1) { perror ("stat"); - free (s); + free(s); for (; npw_gid; if (prefix[0]) { - - size_t len = strlen(prefix) + strlen(pwd->pw_dir) + 2; - int wlen; - user_home = XMALLOC(len, char); - wlen = snprintf(user_home, len, "%s/%s", prefix, pwd->pw_dir); - assert (wlen == (int) len -1); - } - else { - user_home = xstrdup (pwd->pw_dir); + if (asprintf(&user_home, "%s/%s", prefix, pwd->pw_dir) == -1) + exit(EXIT_FAILURE); + } else { + user_home = xstrdup(pwd->pw_dir); } pw_close(); } diff --git a/src/usermod.c b/src/usermod.c index 7d9e661db..693c94a34 100644 --- a/src/usermod.c +++ b/src/usermod.c @@ -59,6 +59,7 @@ #endif #include "shadowlog.h" + /* * exit status values * for E_GRP_UPDATE and E_NOSPACE (not used yet), other update requests @@ -1265,16 +1266,14 @@ static void process_flags (int argc, char **argv) user_newgid = user_gid; } if (prefix[0]) { - size_t len = strlen(prefix) + strlen(user_home) + 2; - int wlen; - prefix_user_home = XMALLOC(len, char); - wlen = snprintf(prefix_user_home, len, "%s/%s", prefix, user_home); - assert (wlen == (int) len -1); + if (asprintf(&prefix_user_home, "%s/%s", prefix, user_home) == -1) + exit(EXIT_FAILURE); if (user_newhome) { - len = strlen(prefix) + strlen(user_newhome) + 2; - prefix_user_newhome = XMALLOC(len, char); - wlen = snprintf(prefix_user_newhome, len, "%s/%s", prefix, user_newhome); - assert (wlen == (int) len -1); + if (asprintf(&prefix_user_newhome, "%s/%s", + prefix, user_newhome) == -1) + { + exit(EXIT_FAILURE); + } } } @@ -2042,11 +2041,10 @@ static void update_faillog (void) */ static void move_mailbox (void) { - const char *maildir; - char* mailfile; - int fd; - struct stat st; - size_t size; + int fd; + char *mailfile; + const char *maildir; + struct stat st; maildir = getdef_str ("MAIL_DIR"); #ifdef MAIL_SPOOL_DIR @@ -2057,8 +2055,6 @@ static void move_mailbox (void) if (NULL == maildir) { return; } - size = strlen(prefix) + strlen(maildir) + strlen(user_name) + 3; - mailfile = XMALLOC(size, char); /* * O_NONBLOCK is to make sure open won't hang on mandatory locks. @@ -2067,12 +2063,11 @@ static void move_mailbox (void) * between stat and chown). --marekm */ if (prefix[0]) { - (void) snprintf (mailfile, size, "%s/%s/%s", - prefix, maildir, user_name); - } - else { - (void) snprintf (mailfile, size, "%s/%s", - maildir, user_name); + if (asprintf(&mailfile, "%s/%s/%s", prefix, maildir, user_name) == -1) + exit(EXIT_FAILURE); + } else { + if (asprintf(&mailfile, "%s/%s", maildir, user_name) == -1) + exit(EXIT_FAILURE); } fd = open (mailfile, O_RDONLY | O_NONBLOCK, 0); @@ -2114,18 +2109,17 @@ static void move_mailbox (void) (void) close (fd); if (lflg) { - char* newmailfile; - size_t newsize; + char *newmailfile; - newsize = strlen(prefix) + strlen(maildir) + strlen(user_newname) + 3; - newmailfile = XMALLOC(newsize, char); if (prefix[0]) { - (void) snprintf (newmailfile, newsize, "%s/%s/%s", - prefix, maildir, user_newname); - } - else { - (void) snprintf (newmailfile, newsize, "%s/%s", - maildir, user_newname); + if (asprintf(&newmailfile, "%s/%s/%s", + prefix, maildir, user_newname) == -1) + { + exit(EXIT_FAILURE); + } + } else { + if (asprintf(&newmailfile, "%s/%s", maildir, user_newname) == -1) + exit(EXIT_FAILURE); } if ( (link (mailfile, newmailfile) != 0) || (unlink (mailfile) != 0)) { diff --git a/src/vipw.c b/src/vipw.c index 6a9806257..78d8314c1 100644 --- a/src/vipw.c +++ b/src/vipw.c @@ -44,6 +44,7 @@ #endif /* WITH_TCB */ #include "shadowlog.h" + #define MSG_WARN_EDIT_OTHER_FILE _( \ "You have modified %s.\n"\ "You may need to modify %s for consistency.\n"\ @@ -192,16 +193,15 @@ static void vipwexit (const char *msg, int syserr, int ret) static void vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void)) { - const char *editor; - pid_t pid; - struct stat st1, st2; - int status; - FILE *f; - pid_t orig_pgrp, editor_pgrp = -1; - sigset_t mask, omask; + int status; + char *to_rename; + FILE *f; + pid_t pid, orig_pgrp, editor_pgrp = -1; + sigset_t mask, omask; + const char *editor; + struct stat st1, st2; /* FIXME: the following should have variable sizes */ - char filebackup[1024], fileedit[1024]; - char *to_rename; + char filebackup[1024], fileedit[1024]; snprintf (filebackup, sizeof filebackup, "%s-", file); #ifdef WITH_TCB @@ -294,7 +294,7 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void)) } else if (0 == pid) { /* use the system() call to invoke the editor so that it accepts command line args in the EDITOR and VISUAL environment vars */ - char *buf; + char *buf; /* Wait for parent to make us the foreground pgrp. */ if (orig_pgrp != -1) { @@ -304,9 +304,9 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void)) continue; } - buf = MALLOC(strlen(editor) + strlen(fileedit) + 2, char); - snprintf (buf, strlen (editor) + strlen (fileedit) + 2, - "%s %s", editor, fileedit); + if (asprintf(&buf, "%s %s", editor, fileedit) == -1) + exit(EXIT_FAILURE); + status = system (buf); if (-1 == status) { fprintf (stderr, _("%s: %s: %s\n"), Prog, editor, @@ -420,13 +420,11 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void)) if (stat (file, &st1) != 0) { vipwexit (_("failed to stat edited file"), errno, 1); } - to_rename = MALLOC(strlen(file) + 2, char); - if (NULL == to_rename) { - vipwexit (_("failed to allocate memory"), errno, 1); - } - snprintf (to_rename, strlen (file) + 2, "%s+", file); + if (asprintf(&to_rename, "%s+", file) == -1) + vipwexit (_("asprintf(3) failed"), errno, 1); + if (create_backup_file (f, to_rename, &st1) != 0) { - free (to_rename); + free(to_rename); vipwexit (_("failed to create backup file"), errno, 1); } (void) fclose (f); @@ -444,7 +442,7 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void)) Prog, file, strerror (errno), to_rename); #ifdef WITH_TCB if (tcb_mode) { - free (to_rename); + free(to_rename); } #endif /* WITH_TCB */ vipwexit (0, 0, 1); @@ -452,7 +450,7 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void)) #ifdef WITH_TCB if (tcb_mode) { - free (to_rename); + free(to_rename); if (shadowtcb_gain_priv () == SHADOWTCB_FAILURE) { vipwexit (_("failed to gain privileges"), errno, 1); }