From 37f9805dabba76b7a00bd2a0227762f6f239b598 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 14 Nov 1998 23:31:58 +0000 Subject: [PATCH] changed strlcat() and strlcpy() to have the same semantics as the OpenBSD functions of the same name. changed slprintf() to take buffer length rather than buffer length -1 --- authenticate.c | 2 +- exclude.c | 2 +- flist.c | 28 ++++++++++++++-------------- generator.c | 2 +- io.c | 2 +- lib/compat.c | 4 ++-- loadparm.c | 4 ++-- log.c | 14 +++++++------- mkproto.awk | 2 +- receiver.c | 8 ++++---- rsync.c | 4 ++-- sender.c | 6 +++--- socket.c | 4 ++-- util.c | 45 +++++++++++++++++++++++++-------------------- 14 files changed, 66 insertions(+), 61 deletions(-) diff --git a/authenticate.c b/authenticate.c index 5ecce15f..a4835a6d 100644 --- a/authenticate.c +++ b/authenticate.c @@ -55,7 +55,7 @@ static void gen_challenge(char *addr, char *challenge) memset(input, 0, sizeof(input)); - strlcpy((char *)input, addr, 16); + strlcpy((char *)input, addr, 17); gettimeofday(&tv, NULL); SIVAL(input, 16, tv.tv_sec); SIVAL(input, 20, tv.tv_usec); diff --git a/exclude.c b/exclude.c index 11d5eb08..9b325542 100644 --- a/exclude.c +++ b/exclude.c @@ -321,7 +321,7 @@ void add_cvs_excludes(void) add_exclude(cvs_ignore_list[i], 0); if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) { - slprintf(fname,sizeof(fname)-1, "%s/.cvsignore",p); + slprintf(fname,sizeof(fname), "%s/.cvsignore",p); add_exclude_file(fname,0,0); } diff --git a/flist.c b/flist.c index f614b8b2..caca010f 100644 --- a/flist.c +++ b/flist.c @@ -230,7 +230,7 @@ static void send_file_entry(struct file_struct *file,int f,unsigned base_flags) last_gid = file->gid; last_time = file->modtime; - strlcpy(lastname,fname,MAXPATHLEN-1); + strlcpy(lastname,fname,MAXPATHLEN); lastname[MAXPATHLEN-1] = 0; } @@ -265,11 +265,11 @@ static void receive_file_entry(struct file_struct **fptr, if (l2 >= MAXPATHLEN-l1) overflow("receive_file_entry"); - strlcpy(thisname,lastname,l1); + strlcpy(thisname,lastname,l1+1); read_sbuf(f,&thisname[l1],l2); thisname[l1+l2] = 0; - strlcpy(lastname,thisname,MAXPATHLEN-1); + strlcpy(lastname,thisname,MAXPATHLEN); lastname[MAXPATHLEN-1] = 0; clean_fname(thisname); @@ -370,7 +370,7 @@ static struct file_struct *make_file(char *fname) char *p; char cleaned_name[MAXPATHLEN]; - strlcpy(cleaned_name, fname, MAXPATHLEN-1); + strlcpy(cleaned_name, fname, MAXPATHLEN); cleaned_name[MAXPATHLEN-1] = 0; clean_fname(cleaned_name); fname = cleaned_name; @@ -531,7 +531,7 @@ static void send_directory(int f,struct file_list *flist,char *dir) return; } - strlcpy(fname,dir,MAXPATHLEN-1); + strlcpy(fname,dir,MAXPATHLEN); l = strlen(fname); if (fname[l-1] != '/') { if (l == MAXPATHLEN-1) { @@ -540,7 +540,7 @@ static void send_directory(int f,struct file_list *flist,char *dir) closedir(d); return; } - strlcat(fname,"/", MAXPATHLEN-1); + strlcat(fname,"/", MAXPATHLEN); l++; } p = fname + strlen(fname); @@ -562,7 +562,7 @@ static void send_directory(int f,struct file_list *flist,char *dir) if (strcmp(dname,".")==0 || strcmp(dname,"..")==0) continue; - strlcpy(p,dname,MAXPATHLEN-(l+1)); + strlcpy(p,dname,MAXPATHLEN-l); send_file_name(f,flist,fname,recurse,0); } @@ -608,11 +608,11 @@ struct file_list *send_file_list(int f,int argc,char *argv[]) char fname2[MAXPATHLEN]; char *fname = fname2; - strlcpy(fname,argv[i],MAXPATHLEN-1); + strlcpy(fname,argv[i],MAXPATHLEN); l = strlen(fname); if (l != 1 && fname[l-1] == '/') { - strlcat(fname,".",MAXPATHLEN-1); + strlcat(fname,".",MAXPATHLEN); } if (link_stat(fname,&st) != 0) { @@ -644,7 +644,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[]) thus getting their permissions right */ *p = 0; if (strcmp(lastpath,fname)) { - strlcpy(lastpath, fname, sizeof(lastpath)-1); + strlcpy(lastpath, fname, sizeof(lastpath)); *p = '/'; for (p=fname+1; (p=strchr(p,'/')); p++) { int copy_links_saved = copy_links; @@ -956,11 +956,11 @@ char *f_name(struct file_struct *f) n = (n+1)%10; if (f->dirname) { - strlcpy(p, f->dirname, MAXPATHLEN-1); - strlcat(p, "/", MAXPATHLEN-1); - strlcat(p, f->basename, MAXPATHLEN-1); + strlcpy(p, f->dirname, MAXPATHLEN); + strlcat(p, "/", MAXPATHLEN); + strlcat(p, f->basename, MAXPATHLEN); } else { - strlcpy(p, f->basename, MAXPATHLEN-1); + strlcpy(p, f->basename, MAXPATHLEN); } return p; diff --git a/generator.c b/generator.c index 06c1fa4b..b772d33e 100644 --- a/generator.c +++ b/generator.c @@ -273,7 +273,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out) if ((statret == -1) && (compare_dest != NULL)) { /* try the file at compare_dest instead */ int saveerrno = errno; - slprintf(fnamecmpbuf,MAXPATHLEN-1,"%s/%s",compare_dest,fname); + slprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",compare_dest,fname); statret = link_stat(fnamecmpbuf,&st); if (!S_ISREG(st.st_mode)) statret = -1; diff --git a/io.c b/io.c index 71911408..25d75168 100644 --- a/io.c +++ b/io.c @@ -538,7 +538,7 @@ void io_printf(int fd, const char *format, ...) int len; va_start(ap, format); - len = vslprintf(buf, sizeof(buf)-1, format, ap); + len = vslprintf(buf, sizeof(buf), format, ap); va_end(ap); if (len < 0) exit_cleanup(RERR_STREAMIO); diff --git a/lib/compat.c b/lib/compat.c index f47275f5..922d1199 100644 --- a/lib/compat.c +++ b/lib/compat.c @@ -83,10 +83,10 @@ char *rep_inet_ntoa(struct in_addr ip) unsigned char *p = (unsigned char *)&ip.s_addr; static char buf[18]; #if WORDS_BIGENDIAN - slprintf(buf, 17, "%d.%d.%d.%d", + slprintf(buf, 18, "%d.%d.%d.%d", (int)p[0], (int)p[1], (int)p[2], (int)p[3]); #else - slprintf(buf, 17, "%d.%d.%d.%d", + slprintf(buf, 18, "%d.%d.%d.%d", (int)p[3], (int)p[2], (int)p[1], (int)p[0]); #endif return buf; diff --git a/loadparm.c b/loadparm.c index 81c4943a..09fdd5aa 100644 --- a/loadparm.c +++ b/loadparm.c @@ -51,7 +51,7 @@ #define strequal(a,b) (strcasecmp(a,b)==0) #define BOOLSTR(b) ((b) ? "Yes" : "No") typedef char pstring[1024]; -#define pstrcpy(a,b) strlcpy(a,b,sizeof(pstring)-1) +#define pstrcpy(a,b) strlcpy(a,b,sizeof(pstring)) /* the following are used by loadparm for option lists */ typedef enum @@ -610,7 +610,7 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue) break; case P_GSTRING: - strlcpy((char *)parm_ptr,parmvalue,sizeof(pstring)-1); + strlcpy((char *)parm_ptr,parmvalue,sizeof(pstring)); break; case P_ENUM: diff --git a/log.c b/log.c index 18e1da06..6594d454 100644 --- a/log.c +++ b/log.c @@ -90,7 +90,7 @@ void log_open(void) /* recursion can happen with certain fatal conditions */ va_start(ap, format); - len = vslprintf(buf, sizeof(buf)-1, format, ap); + len = vslprintf(buf, sizeof(buf), format, ap); va_end(ap); if (len < 0) exit_cleanup(RERR_MESSAGEIO); @@ -188,7 +188,7 @@ static void log_formatted(int fd, extern int am_sender; int64 b; - strlcpy(buf, format, sizeof(buf)-1); + strlcpy(buf, format, sizeof(buf)); for (s=&buf[0]; s && (p=strchr(s,'%')); ) { @@ -199,18 +199,18 @@ static void log_formatted(int fd, case 'h': n = client_name(0); break; case 'a': n = client_addr(0); break; case 'l': - slprintf(buf2,sizeof(buf2)-1,"%.0f", + slprintf(buf2,sizeof(buf2),"%.0f", (double)file->length); n = buf2; break; case 'p': - slprintf(buf2,sizeof(buf2)-1,"%d", + slprintf(buf2,sizeof(buf2),"%d", (int)getpid()); n = buf2; break; case 'o': n = op; break; case 'f': - slprintf(buf2, sizeof(buf2)-1, "%s/%s", + slprintf(buf2, sizeof(buf2), "%s/%s", file->basedir?file->basedir:"", f_name(file)); clean_fname(buf2); @@ -229,7 +229,7 @@ static void log_formatted(int fd, b = stats.total_read - initial_stats->total_read; } - slprintf(buf2,sizeof(buf2)-1,"%.0f", (double)b); + slprintf(buf2,sizeof(buf2),"%.0f", (double)b); n = buf2; break; case 'c': @@ -240,7 +240,7 @@ static void log_formatted(int fd, b = stats.total_read - initial_stats->total_read; } - slprintf(buf2,sizeof(buf2)-1,"%.0f", (double)b); + slprintf(buf2,sizeof(buf2),"%.0f", (double)b); n = buf2; break; } diff --git a/mkproto.awk b/mkproto.awk index a08b1aff..6af5dfc3 100644 --- a/mkproto.awk +++ b/mkproto.awk @@ -58,7 +58,7 @@ BEGIN { next; } -!/^OFF_T|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time/ { +!/^OFF_T|^size_t|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time/ { next; } diff --git a/receiver.c b/receiver.c index ac9c6695..9701303b 100644 --- a/receiver.c +++ b/receiver.c @@ -163,7 +163,7 @@ static int get_tmpname(char *fnametmp, char *fname) rprintf(FERROR,"filename too long\n"); return 0; } - slprintf(fnametmp,MAXPATHLEN-1, "%s/.%s.XXXXXX",tmpdir,f); + slprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f); return 1; } @@ -176,11 +176,11 @@ static int get_tmpname(char *fnametmp, char *fname) if (f) { *f = 0; - slprintf(fnametmp,MAXPATHLEN-1,"%s/.%s.XXXXXX", + slprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX", fname,f+1); *f = '/'; } else { - slprintf(fnametmp,MAXPATHLEN-1,".%s.XXXXXX",fname); + slprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname); } return 1; @@ -353,7 +353,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) if ((fd1 == -1) && (compare_dest != NULL)) { /* try the file at compare_dest instead */ - slprintf(fnamecmpbuf,MAXPATHLEN-1,"%s/%s", + slprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s", compare_dest,fname); fnamecmp = fnamecmpbuf; fd1 = open(fnamecmp,O_RDONLY); diff --git a/rsync.c b/rsync.c index 7021fd15..0f8d33b4 100644 --- a/rsync.c +++ b/rsync.c @@ -94,7 +94,7 @@ int delete_file(char *fname) if (strcmp(dname,".")==0 || strcmp(dname,"..")==0) continue; - slprintf(buf, sizeof(buf)-1, "%s/%s", fname, dname); + slprintf(buf, sizeof(buf), "%s/%s", fname, dname); if (verbose > 0) rprintf(FINFO,"deleting %s\n", buf); if (delete_file(buf) != 0) { @@ -202,7 +202,7 @@ void finish_transfer(char *fname, char *fnametmp, struct file_struct *file) rprintf(FERROR,"backup filename too long\n"); return; } - slprintf(fnamebak,sizeof(fnamebak)-1,"%s%s",fname,backup_suffix); + slprintf(fnamebak,sizeof(fnamebak),"%s%s",fname,backup_suffix); if (do_rename(fname,fnamebak) != 0 && errno != ENOENT) { rprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno)); return; diff --git a/sender.c b/sender.c index 45c09201..4a344ea4 100644 --- a/sender.c +++ b/sender.c @@ -128,17 +128,17 @@ void send_files(struct file_list *flist,int f_out,int f_in) fname[0] = 0; if (file->basedir) { - strlcpy(fname,file->basedir,MAXPATHLEN-1); + strlcpy(fname,file->basedir,MAXPATHLEN); if (strlen(fname) == MAXPATHLEN-1) { io_error = 1; rprintf(FERROR, "send_files failed on long-named directory %s\n", fname); return; } - strlcat(fname,"/",MAXPATHLEN-1); + strlcat(fname,"/",MAXPATHLEN); offset = strlen(file->basedir)+1; } - strlcat(fname,f_name(file),MAXPATHLEN-strlen(fname)); + strlcat(fname,f_name(file),MAXPATHLEN); if (verbose > 2) rprintf(FINFO,"send_files(%d,%s)\n",i,fname); diff --git a/socket.c b/socket.c index 6fd4e365..b9f01a61 100644 --- a/socket.c +++ b/socket.c @@ -330,7 +330,7 @@ char *client_addr(int fd) exit_cleanup(RERR_SOCKETIO); } - strlcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr), sizeof(addr_buf)-1); + strlcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr), sizeof(addr_buf)); return addr_buf; } @@ -363,7 +363,7 @@ char *client_name(int fd) if ((hp = gethostbyaddr((char *) &sockin->sin_addr, sizeof(sockin->sin_addr), AF_INET))) { - strlcpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1); + strlcpy(name_buf,(char *)hp->h_name,sizeof(name_buf)); } diff --git a/util.c b/util.c index 8c352b2b..c5bb4a70 100644 --- a/util.c +++ b/util.c @@ -359,28 +359,34 @@ void kill_all(int sig) } /* like strncpy but does not 0 fill the buffer and always null - terminates (thus it can use maxlen+1 space in d) */ -void strlcpy(char *d, char *s, int maxlen) + terminates. bufsize is the size of the destination buffer */ +size_t strlcpy(char *d, const char *s, size_t bufsize) { - int len = strlen(s); - if (len > maxlen) len = maxlen; + size_t len = strlen(s); + size_t ret = len; + if (len >= bufsize) len = bufsize-1; memcpy(d, s, len); d[len] = 0; + return ret; } /* like strncat but does not 0 fill the buffer and always null - terminates (thus it can use maxlen+1 space in d) */ -void strlcat(char *d, char *s, int maxlen) + terminates. bufsize is the length of the buffer, which should + be one more than the maximum resulting string length */ +size_t strlcat(char *d, const char *s, size_t bufsize) { - int len1 = strlen(d); - int len2 = strlen(s); - if (len1+len2 > maxlen) { - len2 = maxlen-len1; + size_t len1 = strlen(d); + size_t len2 = strlen(s); + size_t ret = len1 + len2; + + if (len1+len2 >= bufsize) { + len2 = bufsize - (len1+1); } if (len2 > 0) { memcpy(d+len1, s, len2); d[len1+len2] = 0; } + return ret; } /* turn a user name into a uid */ @@ -502,14 +508,13 @@ void strlower(char *s) } } -/* this is like vsnprintf but the 'n' limit does not include - the terminating null. So if you have a 1024 byte buffer then - pass 1023 for n */ +/* this is like vsnprintf but it always null terminates, so you + can fit at most n-1 chars in */ int vslprintf(char *str, int n, const char *format, va_list ap) { int ret = vsnprintf(str, n, format, ap); - if (ret > n || ret < 0) { - str[n] = 0; + if (ret >= n || ret < 0) { + str[n-1] = 0; return -1; } str[ret] = 0; @@ -670,10 +675,10 @@ char *push_dir(char *dir, int save) } if (*dir == '/') { - strlcpy(curr_dir, dir, sizeof(curr_dir)-1); + strlcpy(curr_dir, dir, sizeof(curr_dir)); } else { - strlcat(curr_dir,"/", sizeof(curr_dir)-1); - strlcat(curr_dir,dir, sizeof(curr_dir)-1); + strlcat(curr_dir,"/", sizeof(curr_dir)); + strlcat(curr_dir,dir, sizeof(curr_dir)); } clean_fname(curr_dir); @@ -692,7 +697,7 @@ int pop_dir(char *dir) return ret; } - strlcpy(curr_dir, dir, sizeof(curr_dir)-1); + strlcpy(curr_dir, dir, sizeof(curr_dir)); free(dir); @@ -797,7 +802,7 @@ char *timestring(time_t t) #ifdef HAVE_STRFTIME strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm); #else - strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf)-1); + strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf)); #endif if (TimeBuf[strlen(TimeBuf)-1] == '\n') { -- 2.34.1