From 7db3b623bd115c096f4a261d441698b20dc39d7c Mon Sep 17 00:00:00 2001 From: Rob Swindell <rob@synchro.net> Date: Tue, 13 Apr 2021 22:57:16 -0700 Subject: [PATCH] Refactor putuserrec() This started with a Coverity issue (CID 33230) which got me looking at this function and wondering: why is str2 being NUL-terminated here? Why is the length of str2 to be calculated on successive lines? What is with this (long)((long)((long)((long)) typecast? This was some of the oldest code in Synchronet (along with a lot of the other functions in this file). I tried to keep as much intact as possible while still improving the logic and readability. --- src/sbbs3/userdat.c | 81 ++++++++++++++++++++++++--------------------- src/sbbs3/userdat.h | 2 +- 2 files changed, 45 insertions(+), 38 deletions(-) diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c index ada3b2ded3..be8f0c90f1 100644 --- a/src/sbbs3/userdat.c +++ b/src/sbbs3/userdat.c @@ -2217,66 +2217,73 @@ int getuserrec(scfg_t* cfg, int usernumber,int start, int length, char *str) } /****************************************************************************/ -/* Places into user.dat at the offset for usernumber+start for length bytes */ -/* Called from various locations */ +/* Write a string (str) into user.dat at the offset for usernumber + start */ +/* 'length' may be auto-determined (from 'start') by passing 0 for length */ +/* If 'str' is longer than 'length', only 'length' characters are written */ /****************************************************************************/ -int putuserrec(scfg_t* cfg, int usernumber,int start, uint length, const char *str) +int putuserrec(scfg_t* cfg, int usernumber, int start, int length, const char *str) { - char str2[256]; + const char* p; + char buf[256]; + char path[MAX_PATH + 1]; int file; - uint c,i; + uint i; - if(!VALID_CFG(cfg) || usernumber<1 || str==NULL) - return(-1); + if(!VALID_CFG(cfg) || usernumber < 1 || str == NULL) + return -1; - if(length > sizeof(str2) - 1) - return -10; + if(length == 0) { /* auto-length */ + length = user_rec_len(start); + if(length < 1) + return -2; + } + size_t slen = strlen(str); + if(slen >= (size_t)length) + p = str; + else { + if(length > sizeof(buf)) + return -10; + memset(buf, ETX, length); + memcpy(buf, str, slen); + p = buf; + } - SAFEPRINTF(str2,"%suser/user.dat",cfg->data_dir); - if((file=nopen(str2,O_RDWR|O_DENYNONE))==-1) - return(errno); + SAFEPRINTF(path, "%suser/user.dat", cfg->data_dir); + if((file = nopen(path, O_RDWR|O_DENYNONE))==-1) + return errno; - if(filelength(file)<((long)usernumber-1)*U_LEN) { + off_t offset = (usernumber - 1) * U_LEN; + if(filelength(file) < offset) { close(file); - return(-4); - } - - if(length==0) { /* auto-length */ - length=user_rec_len(start); - if((long)length < 0) { - close(file); - return -2; - } + return -4; } - SAFECOPY(str2,str); - if(strlen(str2)<length) { - for(c=strlen(str2);c<length;c++) - str2[c]=ETX; - str2[c]=0; + offset += start; + if(lseek(file, offset, SEEK_SET) != offset) { + close(file); + return -5; } - lseek(file,(long)((long)((long)((long)usernumber-1)*U_LEN)+start),SEEK_SET); i=0; - while(i<LOOP_NODEDAB - && lock(file,(long)((long)(usernumber-1)*U_LEN)+start,length)==-1) { + while(i < LOOP_NODEDAB + && lock(file, offset, length) == -1) { if(i) mswait(100); i++; } - if(i>=LOOP_NODEDAB) { + if(i >= LOOP_NODEDAB) { close(file); - return(-3); + return -3; } - int wr = write(file, str2, length); - unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length); + int wr = write(file, p, length); + unlock(file, offset, length); close(file); if(wr != length) - return -4; - dirtyuserdat(cfg,usernumber); - return(0); + return -6; + dirtyuserdat(cfg, usernumber); + return 0; } /****************************************************************************/ diff --git a/src/sbbs3/userdat.h b/src/sbbs3/userdat.h index 2f47bfadbd..9dc1d7915f 100644 --- a/src/sbbs3/userdat.h +++ b/src/sbbs3/userdat.h @@ -81,7 +81,7 @@ DLLEXPORT uint userdatdupe(scfg_t*, uint usernumber, uint offset, uint datlen, c DLLEXPORT BOOL chk_ar(scfg_t*, uchar* str, user_t*, client_t*); /* checks access requirements */ DLLEXPORT int getuserrec(scfg_t*, int usernumber, int start, int length, char *str); -DLLEXPORT int putuserrec(scfg_t*, int usernumber, int start, uint length, const char *str); +DLLEXPORT int putuserrec(scfg_t*, int usernumber, int start, int length, const char *str); DLLEXPORT ulong adjustuserrec(scfg_t*, int usernumber, int start, int length, long adj); DLLEXPORT BOOL logoutuserdat(scfg_t*, user_t*, time_t now, time_t logontime); DLLEXPORT void resetdailyuserdat(scfg_t*, user_t*, BOOL write); -- GitLab