LCOV - code coverage report
Current view: top level - gcc/rust/metadata - rust-extern-crate.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 79.4 % 68 54
Test Date: 2026-02-28 14:20:25 Functions: 75.0 % 8 6
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #include "rust-extern-crate.h"
      20              : #include "rust-diagnostics.h"
      21              : #include "rust-export-metadata.h"
      22              : 
      23              : #include "md5.h"
      24              : 
      25              : namespace Rust {
      26              : namespace Imports {
      27              : 
      28           24 : ExternCrate::ExternCrate (Import::Stream &stream) : import_stream (stream) {}
      29              : 
      30            0 : ExternCrate::ExternCrate (const std::string &crate_name,
      31            0 :                           std::vector<ProcMacro::Procmacro> macros)
      32            0 :   : proc_macros (macros), crate_name (crate_name)
      33            0 : {}
      34              : 
      35           24 : ExternCrate::~ExternCrate () {}
      36              : 
      37              : bool
      38            0 : ExternCrate::ok () const
      39              : {
      40            0 :   return !import_stream->get ().saw_error ();
      41              : }
      42              : 
      43              : bool
      44           24 : ExternCrate::load (location_t locus)
      45              : {
      46           24 :   rust_assert (this->import_stream.has_value ());
      47           24 :   auto &import_stream = this->import_stream->get ();
      48              :   // match header
      49           24 :   import_stream.require_bytes (locus, Metadata::kMagicHeader,
      50              :                                sizeof (Metadata::kMagicHeader));
      51           24 :   if (import_stream.saw_error ())
      52              :     return false;
      53              : 
      54              :   // parse 16 bytes md5
      55           24 :   unsigned char checksum[16];
      56           24 :   bool ok
      57           24 :     = import_stream.do_peek (sizeof (checksum), (const char **) &checksum);
      58           24 :   if (!ok)
      59              :     return false;
      60              : 
      61           24 :   import_stream.advance (sizeof (checksum));
      62              : 
      63              :   // parse delim
      64           24 :   import_stream.require_bytes (locus, Metadata::kSzDelim,
      65              :                                sizeof (Metadata::kSzDelim));
      66           24 :   if (import_stream.saw_error ())
      67              :     return false;
      68              : 
      69              :   // parse crate name
      70              :   bool saw_delim = false;
      71          832 :   while (!import_stream.saw_error () && !import_stream.at_eof ())
      72              :     {
      73          416 :       unsigned char byte = import_stream.get_char ();
      74          416 :       saw_delim
      75          416 :         = memcmp (&byte, Metadata::kSzDelim, sizeof (Metadata::kSzDelim)) == 0;
      76          416 :       if (saw_delim)
      77              :         break;
      78              : 
      79          392 :       crate_name += byte;
      80              :     }
      81           24 :   if (!saw_delim || crate_name.empty ())
      82              :     {
      83            0 :       import_stream.set_saw_error ();
      84            0 :       rust_error_at (locus, "failed to read crate name field");
      85              : 
      86            0 :       return false;
      87              :     }
      88              : 
      89              :   // read until delim which is the size of the meta data
      90           24 :   std::string metadata_length_buffer;
      91           24 :   saw_delim = false;
      92          160 :   while (!import_stream.saw_error () && !import_stream.at_eof ())
      93              :     {
      94           80 :       unsigned char byte = import_stream.get_char ();
      95           80 :       saw_delim
      96           80 :         = memcmp (&byte, Metadata::kSzDelim, sizeof (Metadata::kSzDelim)) == 0;
      97           80 :       if (saw_delim)
      98              :         break;
      99              : 
     100           56 :       metadata_length_buffer += byte;
     101              :     }
     102           24 :   if (!saw_delim || metadata_length_buffer.empty ())
     103              :     {
     104            0 :       import_stream.set_saw_error ();
     105            0 :       rust_error_at (locus, "failed to read metatadata size");
     106              : 
     107            0 :       return false;
     108              :     }
     109              : 
     110              :   // interpret the string size
     111           24 :   int expected_buffer_length = -1;
     112           24 :   ok = ExternCrate::string_to_int (locus, metadata_length_buffer, false,
     113              :                                    &expected_buffer_length);
     114           24 :   if (!ok)
     115              :     return false;
     116              : 
     117              :   // read the parsed size and it should be eof
     118           24 :   metadata_buffer.reserve (expected_buffer_length);
     119         2608 :   for (int i = 0; i < expected_buffer_length && !import_stream.saw_error ()
     120         5192 :                   && !import_stream.at_eof ();
     121              :        i++)
     122              :     {
     123         2584 :       metadata_buffer += import_stream.get_char ();
     124              :     }
     125              : 
     126              :   // compute the md5
     127           24 :   struct md5_ctx chksm;
     128           24 :   unsigned char computed_checksum[16];
     129              : 
     130           24 :   md5_init_ctx (&chksm);
     131           24 :   md5_process_bytes (metadata_buffer.c_str (), metadata_buffer.size (), &chksm);
     132           24 :   md5_finish_ctx (&chksm, computed_checksum);
     133              : 
     134              :   // FIXME i think the encoding and decoding of md5 is going wrong or else we
     135              :   // are not computing it correctly
     136              :   //
     137              :   // compare the checksums
     138              :   // if (memcmp(computed_checksum, checksum, sizeof (checksum)) != 0)
     139              :   //   {
     140              :   //     rust_error_at (locus,
     141              :   //                 "checksum mismatch in metadata: %<%.*s%> vs %<%.*s%>",
     142              :   //                 sizeof (computed_checksum), computed_checksum,
     143              :   //                 sizeof (checksum), checksum);
     144              :   //     return false;
     145              :   //   }
     146              : 
     147              :   // all good
     148           24 :   return true;
     149           24 : }
     150              : 
     151              : const std::string &
     152           48 : ExternCrate::get_crate_name () const
     153              : {
     154           48 :   return crate_name;
     155              : }
     156              : 
     157              : const std::string &
     158           24 : ExternCrate::get_metadata () const
     159              : {
     160           24 :   return metadata_buffer;
     161              : }
     162              : 
     163              : // Turn a string into a integer with appropriate error handling.
     164              : bool
     165           24 : ExternCrate::string_to_int (location_t locus, const std::string &s,
     166              :                             bool is_neg_ok, int *ret)
     167              : {
     168           24 :   char *end;
     169           24 :   long prio = strtol (s.c_str (), &end, 10);
     170           24 :   if (*end != '\0' || prio > 0x7fffffff || (prio < 0 && !is_neg_ok))
     171              :     {
     172            0 :       rust_error_at (locus, "invalid integer in import data");
     173            0 :       return false;
     174              :     }
     175           24 :   *ret = prio;
     176           24 :   return true;
     177              : }
     178              : 
     179              : } // namespace Imports
     180              : } // namespace Rust
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.