[gcc r13-4262] libstdc++: Fix unsafe use of dirent::d_name [PR107814]

Jonathan Wakely redi@gcc.gnu.org
Wed Nov 23 10:20:21 GMT 2022


https://gcc.gnu.org/g:1cac00d013856fea4cee0f13c4959c8e21afd2d9

commit r13-4262-g1cac00d013856fea4cee0f13c4959c8e21afd2d9
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Nov 22 19:15:53 2022 +0000

    libstdc++: Fix unsafe use of dirent::d_name [PR107814]
    
    Copy the fix for PR 104731 to the equivalent experimental::filesystem
    test.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/107814
            * testsuite/experimental/filesystem/iterators/error_reporting.cc:
            Use a static buffer with space after it.

Diff:
---
 .../filesystem/iterators/error_reporting.cc        | 35 ++++++++++++++--------
 1 file changed, 22 insertions(+), 13 deletions(-)

diff --git a/libstdc++-v3/testsuite/experimental/filesystem/iterators/error_reporting.cc b/libstdc++-v3/testsuite/experimental/filesystem/iterators/error_reporting.cc
index f005b7d5293..aabed14679c 100644
--- a/libstdc++-v3/testsuite/experimental/filesystem/iterators/error_reporting.cc
+++ b/libstdc++-v3/testsuite/experimental/filesystem/iterators/error_reporting.cc
@@ -29,35 +29,44 @@
 
 int choice;
 
-struct dirent global_dirent;
-
 extern "C" struct dirent* readdir(DIR*)
 {
+  // On some targets dirent::d_name is very small, but the OS allocates
+  // a trailing char array after the dirent struct. Emulate that here.
+  union State
+  {
+    struct dirent d;
+    char buf[sizeof(struct dirent) + 16] = {};
+  };
+
+  static State state;
+  char* d_name = state.buf + offsetof(struct dirent, d_name);
+
   switch (choice)
   {
   case 1:
-    global_dirent.d_ino = 999;
+    state.d.d_ino = 999;
 #if defined _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE && defined DT_REG
-    global_dirent.d_type = DT_REG;
+    state.d.d_type = DT_REG;
 #endif
-    global_dirent.d_reclen = 0;
-    std::char_traits<char>::copy(global_dirent.d_name, "file", 5);
+    state.d.d_reclen = 0;
+    std::char_traits<char>::copy(d_name, "file", 5);
     choice = 0;
-    return &global_dirent;
+    return &state.d;
   case 2:
-    global_dirent.d_ino = 111;
+    state.d.d_ino = 111;
 #if defined _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE && defined DT_DIR
-    global_dirent.d_type = DT_DIR;
+    state.d.d_type = DT_DIR;
 #endif
-    global_dirent.d_reclen = 60;
-    std::char_traits<char>::copy(global_dirent.d_name, "subdir", 7);
+    state.d.d_reclen = 60;
+    std::char_traits<char>::copy(d_name, "subdir", 7);
     choice = 1;
-    return &global_dirent;
+    return &state.d;
   default:
     errno = EIO;
     return nullptr;
   }
-  return &global_dirent;
+  return &state.d;
 }
 
 void


More information about the Libstdc++-cvs mailing list