Re: the 1st hunk of Cyril Roelandt's patch to rats: + size_t len = snprintf(NULL, 0, "%s/%s", filename, dirdata->d_name) + 1;
Unfortunately, relying on the return value of snprintf isn't very portable, as C99 and the Single Unix Specification v2 contradict each other on the subject, cf. the glibc manual: "*Attention:* In versions of the GNU C library prior to 2.1 the return value is the number of characters stored, not including the terminating null; unless there was not enough space in S to store the result in which case `-1' is returned. This was changed in order to comply with the ISO C99 standard." (see also the NOTES in "man 3 snprintf" on linux). A more portable, albeit less elegant solution is to calculate the required size with strlen: + size_t len = strlen(filename) + 1 + strlen(dirdata->d_name) + 1; Re: the 2nd hunk of the patch: + struct stat buf; + if(lstat(filename, &buf)==-1) { + return; + } + symname=calloc(buf.st_size, 1); + if(readlink(filename,symname,buf.st_size)==-1) { 'buf' and the call to lstat aren't necessary as there is a previous call to lstat(filename, ...) in the same function. Also, "calloc(buf.st_size,1)" seems to be an off-by-one error; you need st_size+1; cf. POSIX: "For symbolic links, [...] The value of the st_size member shall be set to the length of the pathname contained in the symbolic link not including any terminating null byte." <http://pubs.opengroup.org/onlinepubs/9699919799/functions/lstat.html> Amended patch attached.
diff --git a/engine.c b/engine.c index e07e8ab..335cb67 100644 --- a/engine.c +++ b/engine.c @@ -1051,11 +1051,9 @@ void process_directory(char *filename, int forcelang) { !strcmp(dirdata->d_name,"..")) { continue; } - buf=calloc(PATH_MAX,1); - sprintf(buf, - "%s/%s", - filename, - dirdata->d_name); + size_t len = strlen(filename) + 1 + strlen(dirdata->d_name) + 1; + buf = calloc(len, 1); + snprintf(buf, len, "%s/%s", filename, dirdata->d_name); process_file(buf,forcelang); } #endif @@ -1093,9 +1091,8 @@ void process_file(char *filename, int forcelang) /* Symbolic link check */ if(S_ISLNK(fstat.st_mode)) { if(flags & FOLLOW_SYMLINK) { - char *symname; - symname=calloc(PATH_MAX,1); - if(readlink(filename,symname,PATH_MAX)==-1) { + char *symname=calloc(fstat.st_size+1,1); + if(readlink(filename,symname,fstat.st_size+1)==-1) { return; } process_file(symname,forcelang);