Hi Pádraig,

> There is a later cast to (long int) that would
> similarly truncate large values on LLP64 systems.
> How about something like this as well?
> 
> @@ -311,7 +312,7 @@ __realpath (const char *name, char *resolved)
>                  }
> 
>                len = strlen (end);
> -              if ((long int) (n + len) >= path_max)
> +              if (SIZE_MAX - len <= n || path_max <= n + len)
>                  {
>                    freea (buf);
>                    __set_errno (ENAMETOOLONG);

Thanks, also for the integer overflow check (useful also for the LP64
platforms). Here is the proposed revised patch.

Bruno
>From fcce5d7501a8ea0224ffb0f35340fbe5dfc483ef Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 14 Oct 2016 02:49:05 +0200
Subject: [PATCH] canonicalize-lgpl: Support the case path_max > INT_MAX.

* lib/canonicalize-lgpl.c (__realpath): Declare n as ssize_t, not int.
---
 ChangeLog               | 7 +++++++
 lib/canonicalize-lgpl.c | 5 +++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 32bddf8..510f191 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2016-10-14  Bruno Haible  <br...@clisp.org>
+            Pádraig Brady  <p...@draigbrady.com>
+
+	canonicalize-lgpl: Support the case path_max > INT_MAX.
+	* lib/canonicalize-lgpl.c (__realpath): Declare n as ssize_t, not int.
+	Fix overflow check, for platforms where 'size_t' is larger than 'long'.
+
 2016-10-13  Paul Eggert  <egg...@cs.ucla.edu>
 
 	stdint: port SIZE_MAX to glibc s390
diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c
index 4a38a46..7f54008 100644
--- a/lib/canonicalize-lgpl.c
+++ b/lib/canonicalize-lgpl.c
@@ -194,7 +194,6 @@ __realpath (const char *name, char *resolved)
 #else
       struct stat st;
 #endif
-      int n;
 
       /* Skip sequence of multiple path-separators.  */
       while (ISSLASH (*start))
@@ -275,6 +274,7 @@ __realpath (const char *name, char *resolved)
             {
               char *buf;
               size_t len;
+              ssize_t n;
 
               if (++num_links > MAXSYMLINKS)
                 {
@@ -311,7 +311,8 @@ __realpath (const char *name, char *resolved)
                 }
 
               len = strlen (end);
-              if ((long int) (n + len) >= path_max)
+              /* Check that n + len + 1 doesn't overflow and is <= path_max. */
+              if (n >= SIZE_MAX - len || n + len >= path_max)
                 {
                   freea (buf);
                   __set_errno (ENAMETOOLONG);
-- 
2.6.4

Reply via email to