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
|