readdir: fix interface to kernel getdents64 function

Issue:
  The kernel will pad the entry->d_reclen in a getdents64 call to a
  long-word boundary.  For very long records, this could exceed the
  size of a struct dirent. The mismatch in the size was causing error
  paranoid checking code in bionic to fail... thus causing an early
  "end" when reading the dirent structures from the kernel buffer.

Test:
 ls
 mkdir abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu
 ls

Change-Id: I75d1f8e45e1655fdd7bac4a08a481d086f28073a
Author: Bruce Beare <bruce.j.beare@intel.com>
diff --git a/libc/unistd/opendir.c b/libc/unistd/opendir.c
index afa3ea0..f178bc6 100644
--- a/libc/unistd/opendir.c
+++ b/libc/unistd/opendir.c
@@ -92,6 +92,9 @@
 _readdir_unlocked(DIR*  dir)
 {
     struct dirent*  entry;
+#ifndef NDEBUG
+    unsigned reclen;
+#endif
 
     if ( !dir->_DIR_avail )
     {
@@ -115,15 +118,18 @@
     if (((long)(void*)entry & 3) != 0)
         return NULL;
 
-    if ( (unsigned)entry->d_reclen > sizeof(*entry)         ||
-         entry->d_reclen <= offsetof(struct dirent, d_name) )
+#ifndef NDEBUG
+    // paranoid testing of the interface with the kernel getdents64 system call
+    reclen = offsetof(struct dirent, d_name) + strlen(entry->d_name) + 1;
+    if ( reclen > sizeof(*entry) || reclen <= offsetof(struct dirent, d_name) )
         goto Bad;
 
-    if ( (char*)entry + entry->d_reclen > (char*)dir->_DIR_buff + sizeof(dir->_DIR_buff) )
+    if ( (char*)entry + reclen > (char*)dir->_DIR_buff + sizeof(dir->_DIR_buff) )
         goto Bad;
 
-    if ( !memchr( entry->d_name, 0, entry->d_reclen - offsetof(struct dirent, d_name)) )
+    if ( !memchr( entry->d_name, 0, reclen - offsetof(struct dirent, d_name)) )
         goto Bad; 
+#endif
 
     dir->_DIR_next   = (struct dirent*)((char*)entry + entry->d_reclen);
     dir->_DIR_avail -= entry->d_reclen;