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);

Reply via email to