Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 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 : 16 : 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 : 16 : ExternCrate::~ExternCrate () {}
36 : :
37 : : bool
38 : 0 : ExternCrate::ok () const
39 : : {
40 : 0 : return !import_stream->get ().saw_error ();
41 : : }
42 : :
43 : : bool
44 : 16 : ExternCrate::load (location_t locus)
45 : : {
46 : 16 : rust_assert (this->import_stream.has_value ());
47 : 16 : auto &import_stream = this->import_stream->get ();
48 : : // match header
49 : 16 : import_stream.require_bytes (locus, Metadata::kMagicHeader,
50 : : sizeof (Metadata::kMagicHeader));
51 : 16 : if (import_stream.saw_error ())
52 : : return false;
53 : :
54 : : // parse 16 bytes md5
55 : 16 : unsigned char checksum[16];
56 : 16 : bool ok
57 : 16 : = import_stream.do_peek (sizeof (checksum), (const char **) &checksum);
58 : 16 : if (!ok)
59 : : return false;
60 : :
61 : 16 : import_stream.advance (sizeof (checksum));
62 : :
63 : : // parse delim
64 : 16 : import_stream.require_bytes (locus, Metadata::kSzDelim,
65 : : sizeof (Metadata::kSzDelim));
66 : 16 : if (import_stream.saw_error ())
67 : : return false;
68 : :
69 : : // parse crate name
70 : : bool saw_delim = false;
71 : 592 : while (!import_stream.saw_error () && !import_stream.at_eof ())
72 : : {
73 : 296 : unsigned char byte = import_stream.get_char ();
74 : 296 : saw_delim
75 : 296 : = memcmp (&byte, Metadata::kSzDelim, sizeof (Metadata::kSzDelim)) == 0;
76 : 296 : if (saw_delim)
77 : : break;
78 : :
79 : 280 : crate_name += byte;
80 : : }
81 : 16 : 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 : 16 : std::string metadata_length_buffer;
91 : 16 : saw_delim = false;
92 : 112 : while (!import_stream.saw_error () && !import_stream.at_eof ())
93 : : {
94 : 56 : unsigned char byte = import_stream.get_char ();
95 : 56 : saw_delim
96 : 56 : = memcmp (&byte, Metadata::kSzDelim, sizeof (Metadata::kSzDelim)) == 0;
97 : 56 : if (saw_delim)
98 : : break;
99 : :
100 : 40 : metadata_length_buffer += byte;
101 : : }
102 : 16 : 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 : 16 : int expected_buffer_length = -1;
112 : 16 : ok = ExternCrate::string_to_int (locus, metadata_length_buffer, false,
113 : : &expected_buffer_length);
114 : 16 : if (!ok)
115 : : return false;
116 : :
117 : : // read the parsed size and it should be eof
118 : 16 : metadata_buffer.reserve (expected_buffer_length);
119 : 1704 : for (int i = 0; i < expected_buffer_length && !import_stream.saw_error ()
120 : 3392 : && !import_stream.at_eof ();
121 : : i++)
122 : : {
123 : 1688 : metadata_buffer += import_stream.get_char ();
124 : : }
125 : :
126 : : // compute the md5
127 : 16 : struct md5_ctx chksm;
128 : 16 : unsigned char computed_checksum[16];
129 : :
130 : 16 : md5_init_ctx (&chksm);
131 : 16 : md5_process_bytes (metadata_buffer.c_str (), metadata_buffer.size (), &chksm);
132 : 16 : 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 : 16 : return true;
149 : 16 : }
150 : :
151 : : const std::string &
152 : 32 : ExternCrate::get_crate_name () const
153 : : {
154 : 32 : return crate_name;
155 : : }
156 : :
157 : : const std::string &
158 : 16 : ExternCrate::get_metadata () const
159 : : {
160 : 16 : return metadata_buffer;
161 : : }
162 : :
163 : : // Turn a string into a integer with appropriate error handling.
164 : : bool
165 : 16 : ExternCrate::string_to_int (location_t locus, const std::string &s,
166 : : bool is_neg_ok, int *ret)
167 : : {
168 : 16 : char *end;
169 : 16 : long prio = strtol (s.c_str (), &end, 10);
170 : 16 : 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 : 16 : *ret = prio;
176 : 16 : return true;
177 : : }
178 : :
179 : : } // namespace Imports
180 : : } // namespace Rust
|