V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
streaming-decoder.cc
1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/wasm/streaming-decoder.h"
6 
7 #include "src/base/template-utils.h"
8 #include "src/handles.h"
9 #include "src/objects-inl.h"
10 #include "src/objects/descriptor-array.h"
11 #include "src/objects/dictionary.h"
12 #include "src/wasm/decoder.h"
13 #include "src/wasm/leb-helper.h"
14 #include "src/wasm/module-decoder.h"
15 #include "src/wasm/wasm-code-manager.h"
16 #include "src/wasm/wasm-limits.h"
17 #include "src/wasm/wasm-objects.h"
18 #include "src/wasm/wasm-result.h"
19 
20 #define TRACE_STREAMING(...) \
21  do { \
22  if (FLAG_trace_wasm_streaming) PrintF(__VA_ARGS__); \
23  } while (false)
24 
25 namespace v8 {
26 namespace internal {
27 namespace wasm {
28 
29 void StreamingDecoder::OnBytesReceived(Vector<const uint8_t> bytes) {
30  if (deserializing()) {
31  wire_bytes_for_deserializing_.insert(wire_bytes_for_deserializing_.end(),
32  bytes.begin(), bytes.end());
33  return;
34  }
35 
36  TRACE_STREAMING("OnBytesReceived(%zu bytes)\n", bytes.size());
37 
38  size_t current = 0;
39  while (ok() && current < bytes.size()) {
40  size_t num_bytes =
41  state_->ReadBytes(this, bytes.SubVector(current, bytes.size()));
42  current += num_bytes;
43  module_offset_ += num_bytes;
44  if (state_->offset() == state_->buffer().size()) {
45  state_ = state_->Next(this);
46  }
47  }
48  total_size_ += bytes.size();
49  if (ok()) {
50  processor_->OnFinishedChunk();
51  }
52 }
53 
54 size_t StreamingDecoder::DecodingState::ReadBytes(StreamingDecoder* streaming,
55  Vector<const uint8_t> bytes) {
56  Vector<uint8_t> remaining_buf = buffer() + offset();
57  size_t num_bytes = std::min(bytes.size(), remaining_buf.size());
58  TRACE_STREAMING("ReadBytes(%zu bytes)\n", num_bytes);
59  memcpy(remaining_buf.start(), &bytes.first(), num_bytes);
60  set_offset(offset() + num_bytes);
61  return num_bytes;
62 }
63 
64 void StreamingDecoder::Finish() {
65  TRACE_STREAMING("Finish\n");
66  if (!ok()) return;
67 
68  if (deserializing()) {
69  Vector<const uint8_t> wire_bytes = VectorOf(wire_bytes_for_deserializing_);
70  // Try to deserialize the module from wire bytes and module bytes.
71  if (processor_->Deserialize(compiled_module_bytes_, wire_bytes)) return;
72 
73  // Deserialization failed. Restart decoding using |wire_bytes|.
74  compiled_module_bytes_ = {};
75  DCHECK(!deserializing());
76  OnBytesReceived(wire_bytes);
77  // The decoder has received all wire bytes; fall through and finish.
78  }
79 
80  if (!state_->is_finishing_allowed()) {
81  // The byte stream ended too early, we report an error.
82  Error("unexpected end of stream");
83  return;
84  }
85 
86  OwnedVector<uint8_t> bytes = OwnedVector<uint8_t>::New(total_size_);
87  uint8_t* cursor = bytes.start();
88  {
89 #define BYTES(x) (x & 0xFF), (x >> 8) & 0xFF, (x >> 16) & 0xFF, (x >> 24) & 0xFF
90  uint8_t module_header[]{BYTES(kWasmMagic), BYTES(kWasmVersion)};
91 #undef BYTES
92  memcpy(cursor, module_header, arraysize(module_header));
93  cursor += arraysize(module_header);
94  }
95  for (const auto& buffer : section_buffers_) {
96  DCHECK_LE(cursor - bytes.start() + buffer->length(), total_size_);
97  memcpy(cursor, buffer->bytes().start(), buffer->length());
98  cursor += buffer->length();
99  }
100  processor_->OnFinishedStream(std::move(bytes));
101 }
102 
103 void StreamingDecoder::Abort() {
104  TRACE_STREAMING("Abort\n");
105  if (!ok()) return; // Failed already.
106  processor_->OnAbort();
107  Fail();
108 }
109 
110 void StreamingDecoder::SetModuleCompiledCallback(
111  ModuleCompiledCallback callback) {
112  DCHECK_NULL(module_compiled_callback_);
113  module_compiled_callback_ = callback;
114 }
115 
116 bool StreamingDecoder::SetCompiledModuleBytes(
117  Vector<const uint8_t> compiled_module_bytes) {
118  compiled_module_bytes_ = compiled_module_bytes;
119  return true;
120 }
121 
122 // An abstract class to share code among the states which decode VarInts. This
123 // class takes over the decoding of the VarInt and then calls the actual decode
124 // code with the decoded value.
125 class StreamingDecoder::DecodeVarInt32 : public DecodingState {
126  public:
127  explicit DecodeVarInt32(size_t max_value, const char* field_name)
128  : max_value_(max_value), field_name_(field_name) {}
129 
130  Vector<uint8_t> buffer() override { return ArrayVector(byte_buffer_); }
131 
132  size_t ReadBytes(StreamingDecoder* streaming,
133  Vector<const uint8_t> bytes) override;
134 
135  std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
136 
137  virtual std::unique_ptr<DecodingState> NextWithValue(
138  StreamingDecoder* streaming) = 0;
139 
140  protected:
141  uint8_t byte_buffer_[kMaxVarInt32Size];
142  // The maximum valid value decoded in this state. {Next} returns an error if
143  // this value is exceeded.
144  const size_t max_value_;
145  const char* const field_name_;
146  size_t value_ = 0;
147  size_t bytes_consumed_ = 0;
148 };
149 
150 class StreamingDecoder::DecodeModuleHeader : public DecodingState {
151  public:
152  Vector<uint8_t> buffer() override { return ArrayVector(byte_buffer_); }
153 
154  std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
155 
156  private:
157  // Checks if the magic bytes of the module header are correct.
158  void CheckHeader(Decoder* decoder);
159 
160  // The size of the module header.
161  static constexpr size_t kModuleHeaderSize = 8;
162  uint8_t byte_buffer_[kModuleHeaderSize];
163 };
164 
165 class StreamingDecoder::DecodeSectionID : public DecodingState {
166  public:
167  explicit DecodeSectionID(uint32_t module_offset)
168  : module_offset_(module_offset) {}
169 
170  Vector<uint8_t> buffer() override { return {&id_, 1}; }
171  bool is_finishing_allowed() const override { return true; }
172 
173  std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
174 
175  private:
176  uint8_t id_ = 0;
177  // The start offset of this section in the module.
178  const uint32_t module_offset_;
179 };
180 
182  public:
183  explicit DecodeSectionLength(uint8_t id, uint32_t module_offset)
184  : DecodeVarInt32(kV8MaxWasmModuleSize, "section length"),
185  section_id_(id),
186  module_offset_(module_offset) {}
187 
188  std::unique_ptr<DecodingState> NextWithValue(
189  StreamingDecoder* streaming) override;
190 
191  private:
192  const uint8_t section_id_;
193  // The start offset of this section in the module.
194  const uint32_t module_offset_;
195 };
196 
197 class StreamingDecoder::DecodeSectionPayload : public DecodingState {
198  public:
199  explicit DecodeSectionPayload(SectionBuffer* section_buffer)
200  : section_buffer_(section_buffer) {}
201 
202  Vector<uint8_t> buffer() override { return section_buffer_->payload(); }
203 
204  std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
205 
206  private:
207  SectionBuffer* const section_buffer_;
208 };
209 
211  public:
212  explicit DecodeNumberOfFunctions(SectionBuffer* section_buffer)
213  : DecodeVarInt32(kV8MaxWasmFunctions, "functions count"),
214  section_buffer_(section_buffer) {}
215 
216  std::unique_ptr<DecodingState> NextWithValue(
217  StreamingDecoder* streaming) override;
218 
219  private:
220  SectionBuffer* const section_buffer_;
221 };
222 
224  public:
225  explicit DecodeFunctionLength(SectionBuffer* section_buffer,
226  size_t buffer_offset,
227  size_t num_remaining_functions)
228  : DecodeVarInt32(kV8MaxWasmFunctionSize, "body size"),
229  section_buffer_(section_buffer),
230  buffer_offset_(buffer_offset),
231  // We are reading a new function, so one function less is remaining.
232  num_remaining_functions_(num_remaining_functions - 1) {
233  DCHECK_GT(num_remaining_functions, 0);
234  }
235 
236  std::unique_ptr<DecodingState> NextWithValue(
237  StreamingDecoder* streaming) override;
238 
239  private:
240  SectionBuffer* const section_buffer_;
241  const size_t buffer_offset_;
242  const size_t num_remaining_functions_;
243 };
244 
245 class StreamingDecoder::DecodeFunctionBody : public DecodingState {
246  public:
247  explicit DecodeFunctionBody(SectionBuffer* section_buffer,
248  size_t buffer_offset, size_t function_body_length,
249  size_t num_remaining_functions,
250  uint32_t module_offset)
251  : section_buffer_(section_buffer),
252  buffer_offset_(buffer_offset),
253  function_body_length_(function_body_length),
254  num_remaining_functions_(num_remaining_functions),
255  module_offset_(module_offset) {}
256 
257  Vector<uint8_t> buffer() override {
258  Vector<uint8_t> remaining_buffer =
259  section_buffer_->bytes() + buffer_offset_;
260  return remaining_buffer.SubVector(0, function_body_length_);
261  }
262 
263  std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
264 
265  private:
266  SectionBuffer* const section_buffer_;
267  const size_t buffer_offset_;
268  const size_t function_body_length_;
269  const size_t num_remaining_functions_;
270  const uint32_t module_offset_;
271 };
272 
273 size_t StreamingDecoder::DecodeVarInt32::ReadBytes(
274  StreamingDecoder* streaming, Vector<const uint8_t> bytes) {
275  Vector<uint8_t> buf = buffer();
276  Vector<uint8_t> remaining_buf = buf + offset();
277  size_t new_bytes = std::min(bytes.size(), remaining_buf.size());
278  TRACE_STREAMING("ReadBytes of a VarInt\n");
279  memcpy(remaining_buf.start(), &bytes.first(), new_bytes);
280  buf.Truncate(offset() + new_bytes);
281  Decoder decoder(buf, streaming->module_offset());
282  value_ = decoder.consume_u32v(field_name_);
283  // The number of bytes we actually needed to read.
284  DCHECK_GT(decoder.pc(), buffer().start());
285  bytes_consumed_ = static_cast<size_t>(decoder.pc() - buf.start());
286  TRACE_STREAMING(" ==> %zu bytes consumed\n", bytes_consumed_);
287 
288  if (decoder.failed()) {
289  if (new_bytes == remaining_buf.size()) {
290  // We only report an error if we read all bytes.
291  streaming->Error(decoder.toResult(nullptr));
292  }
293  set_offset(offset() + new_bytes);
294  return new_bytes;
295  }
296 
297  // We read all the bytes we needed.
298  DCHECK_GT(bytes_consumed_, offset());
299  new_bytes = bytes_consumed_ - offset();
300  // Set the offset to the buffer size to signal that we are at the end of this
301  // section.
302  set_offset(buffer().size());
303  return new_bytes;
304 }
305 
306 std::unique_ptr<StreamingDecoder::DecodingState>
307 StreamingDecoder::DecodeVarInt32::Next(StreamingDecoder* streaming) {
308  if (!streaming->ok()) return nullptr;
309 
310  if (value_ > max_value_) {
311  std::ostringstream oss;
312  oss << "function size > maximum function size: " << value_ << " < "
313  << max_value_;
314  return streaming->Error(oss.str());
315  }
316 
317  return NextWithValue(streaming);
318 }
319 
320 std::unique_ptr<StreamingDecoder::DecodingState>
321 StreamingDecoder::DecodeModuleHeader::Next(StreamingDecoder* streaming) {
322  TRACE_STREAMING("DecodeModuleHeader\n");
323  streaming->ProcessModuleHeader();
324  if (!streaming->ok()) return nullptr;
325  return base::make_unique<DecodeSectionID>(streaming->module_offset());
326 }
327 
328 std::unique_ptr<StreamingDecoder::DecodingState>
329 StreamingDecoder::DecodeSectionID::Next(StreamingDecoder* streaming) {
330  TRACE_STREAMING("DecodeSectionID: %s section\n",
331  SectionName(static_cast<SectionCode>(id_)));
332  return base::make_unique<DecodeSectionLength>(id_, module_offset_);
333 }
334 
335 std::unique_ptr<StreamingDecoder::DecodingState>
336 StreamingDecoder::DecodeSectionLength::NextWithValue(
337  StreamingDecoder* streaming) {
338  TRACE_STREAMING("DecodeSectionLength(%zu)\n", value_);
339  SectionBuffer* buf =
340  streaming->CreateNewBuffer(module_offset_, section_id_, value_,
341  buffer().SubVector(0, bytes_consumed_));
342  if (!buf) return nullptr;
343  if (value_ == 0) {
344  if (section_id_ == SectionCode::kCodeSectionCode) {
345  return streaming->Error("Code section cannot have size 0");
346  }
347  streaming->ProcessSection(buf);
348  if (!streaming->ok()) return nullptr;
349  // There is no payload, we go to the next section immediately.
350  return base::make_unique<DecodeSectionID>(streaming->module_offset_);
351  } else {
352  if (section_id_ == SectionCode::kCodeSectionCode) {
353  // We reached the code section. All functions of the code section are put
354  // into the same SectionBuffer.
355  return base::make_unique<DecodeNumberOfFunctions>(buf);
356  }
357  return base::make_unique<DecodeSectionPayload>(buf);
358  }
359 }
360 
361 std::unique_ptr<StreamingDecoder::DecodingState>
362 StreamingDecoder::DecodeSectionPayload::Next(StreamingDecoder* streaming) {
363  TRACE_STREAMING("DecodeSectionPayload\n");
364  streaming->ProcessSection(section_buffer_);
365  if (!streaming->ok()) return nullptr;
366  return base::make_unique<DecodeSectionID>(streaming->module_offset());
367 }
368 
369 std::unique_ptr<StreamingDecoder::DecodingState>
370 StreamingDecoder::DecodeNumberOfFunctions::NextWithValue(
371  StreamingDecoder* streaming) {
372  TRACE_STREAMING("DecodeNumberOfFunctions(%zu)\n", value_);
373  // Copy the bytes we read into the section buffer.
374  Vector<uint8_t> payload_buf = section_buffer_->payload();
375  if (payload_buf.size() < bytes_consumed_) {
376  return streaming->Error("Invalid code section length");
377  }
378  memcpy(payload_buf.start(), buffer().start(), bytes_consumed_);
379 
380  // {value} is the number of functions.
381  if (value_ == 0) {
382  if (payload_buf.size() != bytes_consumed_) {
383  return streaming->Error("not all code section bytes were consumed");
384  }
385  return base::make_unique<DecodeSectionID>(streaming->module_offset());
386  }
387 
388  streaming->StartCodeSection(value_, streaming->section_buffers_.back());
389  if (!streaming->ok()) return nullptr;
390  return base::make_unique<DecodeFunctionLength>(
391  section_buffer_, section_buffer_->payload_offset() + bytes_consumed_,
392  value_);
393 }
394 
395 std::unique_ptr<StreamingDecoder::DecodingState>
396 StreamingDecoder::DecodeFunctionLength::NextWithValue(
397  StreamingDecoder* streaming) {
398  TRACE_STREAMING("DecodeFunctionLength(%zu)\n", value_);
399  // Copy the bytes we consumed into the section buffer.
400  Vector<uint8_t> fun_length_buffer = section_buffer_->bytes() + buffer_offset_;
401  if (fun_length_buffer.size() < bytes_consumed_) {
402  return streaming->Error("Invalid code section length");
403  }
404  memcpy(fun_length_buffer.start(), buffer().start(), bytes_consumed_);
405 
406  // {value} is the length of the function.
407  if (value_ == 0) return streaming->Error("Invalid function length (0)");
408 
409  if (buffer_offset_ + bytes_consumed_ + value_ > section_buffer_->length()) {
410  return streaming->Error("not enough code section bytes");
411  }
412 
413  return base::make_unique<DecodeFunctionBody>(
414  section_buffer_, buffer_offset_ + bytes_consumed_, value_,
415  num_remaining_functions_, streaming->module_offset());
416 }
417 
418 std::unique_ptr<StreamingDecoder::DecodingState>
419 StreamingDecoder::DecodeFunctionBody::Next(StreamingDecoder* streaming) {
420  TRACE_STREAMING("DecodeFunctionBody\n");
421  streaming->ProcessFunctionBody(buffer(), module_offset_);
422  if (!streaming->ok()) return nullptr;
423 
424  size_t end_offset = buffer_offset_ + function_body_length_;
425  if (num_remaining_functions_ > 0) {
426  return base::make_unique<DecodeFunctionLength>(section_buffer_, end_offset,
427  num_remaining_functions_);
428  }
429  // We just read the last function body. Continue with the next section.
430  if (end_offset != section_buffer_->length()) {
431  return streaming->Error("not all code section bytes were used");
432  }
433  return base::make_unique<DecodeSectionID>(streaming->module_offset());
434 }
435 
436 StreamingDecoder::StreamingDecoder(
437  std::unique_ptr<StreamingProcessor> processor)
438  : processor_(std::move(processor)),
439  // A module always starts with a module header.
440  state_(new DecodeModuleHeader()) {}
441 
442 StreamingDecoder::SectionBuffer* StreamingDecoder::CreateNewBuffer(
443  uint32_t module_offset, uint8_t section_id, size_t length,
444  Vector<const uint8_t> length_bytes) {
445  // Check the order of sections. Unknown sections can appear at any position.
446  if (section_id != kUnknownSectionCode) {
447  if (section_id < next_section_id_) {
448  Error("Unexpected section");
449  return nullptr;
450  }
451  next_section_id_ = section_id + 1;
452  }
453  section_buffers_.emplace_back(std::make_shared<SectionBuffer>(
454  module_offset, section_id, length, length_bytes));
455  return section_buffers_.back().get();
456 }
457 
458 } // namespace wasm
459 } // namespace internal
460 } // namespace v8
461 
462 #undef TRACE_STREAMING
STL namespace.
Definition: libplatform.h:13