From: RĂ©mi Denis-Courmont Date: Fri, 17 Sep 2010 03:10:17 +0000 (+0300) Subject: Fix potential overflow in vlc_readdir() X-Git-Tag: 1.2.0-pre1~5255 X-Git-Url: https://git.sesse.net/?p=vlc;a=commitdiff_plain;h=1c1a4e41611e1802b60a3ceddcc1f4e1c3eb7f4e Fix potential overflow in vlc_readdir() --- diff --git a/src/text/filesystem.c b/src/text/filesystem.c index ff08e1e934..f83a4fcff8 100644 --- a/src/text/filesystem.c +++ b/src/text/filesystem.c @@ -38,9 +38,6 @@ #include #include /* NAME_MAX */ -#if !defined(NAME_MAX) && defined(_POSIX_NAME_MAX) -# define NAME_MAX _POSIX_NAME_MAX -#endif #include #include #include @@ -324,19 +321,35 @@ char *vlc_readdir( DIR *dir ) return FromWide (ent->d_name); #else + /* Beware that readdir_r() assumes is large enough to hold the result + * dirent including the file name. A buffer overflow could occur otherwise. + * In particular, pathconf() and _POSIX_NAME_MAX cannot be used here. */ struct dirent *ent; - struct - { - struct dirent ent; - char buf[NAME_MAX + 1]; - } buf; - int val = readdir_r (dir, &buf.ent, &ent); - if (val) + char *path = NULL; + + long len = fpathconf (dirfd (dir), _PC_NAME_MAX); + if (len == -1) { - errno = val; - return NULL; +#ifdef NAME_MAX + len = NAME_MAX; +#else + errno = ENOMEM; + return NULL; // OS is broken. There is no sane way to fix this. +#endif } - return ent ? vlc_fix_readdir( ent->d_name ) : NULL; + len += offsetof (struct dirent, d_name) + 1; + + struct dirent *buf = malloc (len); + if (unlikely(buf == NULL)) + return NULL; + + int val = readdir_r (dir, buf, &ent); + if (val != 0) + errno = val; + else if (ent != NULL) + path = vlc_fix_readdir (ent->d_name); + free (buf); + return path; #endif }