[gcc r14-7879] gccrs: better handling of incorrect file loading in include_* builtin macros

Arthur Cohen cohenarthur@gcc.gnu.org
Tue Jan 16 18:03:53 GMT 2024


https://gcc.gnu.org/g:8b1e1faa7f2eec13df511fa76d181337efb14f4d

commit r14-7879-g8b1e1faa7f2eec13df511fa76d181337efb14f4d
Author: Marc Poulhiès <dkm@kataplop.net>
Date:   Wed Jul 12 19:00:10 2023 +0200

    gccrs: better handling of incorrect file loading in include_* builtin macros
    
    When the load_file_bytes() fails to open the file, it emits an error but
    returns an empty vector (as if the file is empty).
    
    Instead, return a tl::optional nullopt in case of error and an empty
    vector in case of an empty file.
    
    fixes #2421
    
    gcc/rust/ChangeLog:
    
            * expand/rust-macro-builtins.cc
            (load_file_bytes): Return a tl::optional.
            (MacroBuiltin::include_byte_handler): Adjust and check file was
            correctly opened.
            (MacroBuiltin::include_str_handler): Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/empty_file: New file.
            * rust/compile/issue-2421_str.rs: New test.
    
    Signed-off-by: Marc Poulhiès <dkm@kataplop.net>

Diff:
---
 gcc/rust/expand/rust-macro-builtins.cc       | 26 ++++++++++++++++++--------
 gcc/testsuite/rust/compile/empty_file        |  0
 gcc/testsuite/rust/compile/issue-2421_str.rs | 10 ++++++++++
 3 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index 20c207ea17d..718d740b1dc 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -370,14 +370,14 @@ source_relative_path (std::string path, location_t locus)
 /* Read the full contents of the file FILENAME and return them in a vector.
    FIXME: platform specific.  */
 
-std::vector<uint8_t>
+tl::optional<std::vector<uint8_t>>
 load_file_bytes (location_t invoc_locus, const char *filename)
 {
   RAIIFile file_wrap (filename);
   if (file_wrap.get_raw () == nullptr)
     {
       rust_error_at (invoc_locus, "cannot open filename %s: %m", filename);
-      return std::vector<uint8_t> ();
+      return tl::nullopt;
     }
 
   FILE *f = file_wrap.get_raw ();
@@ -387,7 +387,7 @@ load_file_bytes (location_t invoc_locus, const char *filename)
 
   std::vector<uint8_t> buf (fsize);
 
-  if (fread (&buf[0], fsize, 1, f) != 1)
+  if (fsize > 0 && fread (&buf[0], fsize, 1, f) != 1)
     {
       rust_error_at (invoc_locus, "error reading file %s: %m", filename);
       return std::vector<uint8_t> ();
@@ -453,8 +453,12 @@ MacroBuiltin::include_bytes_handler (location_t invoc_locus,
   std::string target_filename
     = source_relative_path (lit_expr->as_string (), invoc_locus);
 
-  std::vector<uint8_t> bytes
-    = load_file_bytes (invoc_locus, target_filename.c_str ());
+  auto maybe_bytes = load_file_bytes (invoc_locus, target_filename.c_str ());
+
+  if (!maybe_bytes.has_value ())
+    return AST::Fragment::create_error ();
+
+  std::vector<uint8_t> bytes = maybe_bytes.value ();
 
   /* Is there a more efficient way to do this?  */
   std::vector<std::unique_ptr<AST::Expr>> elts;
@@ -518,8 +522,12 @@ MacroBuiltin::include_str_handler (location_t invoc_locus,
   std::string target_filename
     = source_relative_path (lit_expr->as_string (), invoc_locus);
 
-  std::vector<uint8_t> bytes
-    = load_file_bytes (invoc_locus, target_filename.c_str ());
+  auto maybe_bytes = load_file_bytes (invoc_locus, target_filename.c_str ());
+
+  if (!maybe_bytes.has_value ())
+    return AST::Fragment::create_error ();
+
+  std::vector<uint8_t> bytes = maybe_bytes.value ();
 
   /* FIXME: reuse lexer */
   int expect_single = 0;
@@ -568,8 +576,10 @@ MacroBuiltin::include_str_handler (location_t invoc_locus,
   if (expect_single)
     rust_error_at (invoc_locus, "%s was not a valid utf-8 file",
 		   target_filename.c_str ());
-  else
+  else if (!bytes.empty ())
     str = std::string ((const char *) &bytes[0], bytes.size ());
+  else
+    return tl::nullopt;
 
   auto node = AST::SingleASTNode (make_string (invoc_locus, str));
   auto str_tok = make_token (Token::make_string (invoc_locus, std::move (str)));
diff --git a/gcc/testsuite/rust/compile/empty_file b/gcc/testsuite/rust/compile/empty_file
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/gcc/testsuite/rust/compile/issue-2421_str.rs b/gcc/testsuite/rust/compile/issue-2421_str.rs
new file mode 100644
index 00000000000..2616ccbd713
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2421_str.rs
@@ -0,0 +1,10 @@
+#![feature(rustc_attrs)]
+
+#[rustc_builtin_macro]
+macro_rules! include_str {
+    () => {{}};
+}
+
+fn main() {
+    include_str!("empty_file");
+}


More information about the Gcc-cvs mailing list