Coverage Report

Created: 2025-08-29 06:29

/src/WasmEdge/lib/host/wasi/wasifunc.cpp
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: 2019-2024 Second State INC
3
4
#include "host/wasi/wasifunc.h"
5
#include "common/filesystem.h"
6
#include "common/spdlog.h"
7
#include "common/types.h"
8
#include "executor/executor.h"
9
#include "host/wasi/environ.h"
10
#include "runtime/instance/memory.h"
11
12
#include <algorithm>
13
#include <array>
14
#include <limits>
15
#include <numeric>
16
#include <type_traits>
17
#include <vector>
18
19
#if defined(_MSC_VER) && !defined(__clang__)
20
#define __restrict__ __restrict
21
#endif
22
23
namespace WasmEdge {
24
namespace Host {
25
26
namespace {
27
28
template <typename Container>
29
0
inline __wasi_size_t calculateBufferSize(const Container &Array) noexcept {
30
0
  std::vector<__wasi_size_t> Lengths(Array.size());
31
0
  std::transform(Array.begin(), Array.end(), Lengths.begin(),
32
0
                 [](const auto &String) -> __wasi_size_t {
33
0
                   return static_cast<__wasi_size_t>(String.size()) +
34
0
                          UINT32_C(1);
35
0
                 });
36
0
  return std::accumulate(Lengths.begin(), Lengths.end(), UINT32_C(0));
37
0
}
38
39
template <typename T> struct WasiRawType {
40
  using Type = std::underlying_type_t<T>;
41
};
42
template <> struct WasiRawType<uint8_t> {
43
  using Type = uint8_t;
44
};
45
template <> struct WasiRawType<uint16_t> {
46
  using Type = uint16_t;
47
};
48
template <> struct WasiRawType<uint32_t> {
49
  using Type = uint32_t;
50
};
51
template <> struct WasiRawType<uint64_t> {
52
  using Type = uint64_t;
53
};
54
55
template <typename T> using WasiRawTypeT = typename WasiRawType<T>::Type;
56
57
template <typename T> WASI::WasiExpect<T> cast(uint64_t) noexcept;
58
59
template <>
60
WASI::WasiExpect<__wasi_clockid_t>
61
0
cast<__wasi_clockid_t>(uint64_t ClockId) noexcept {
62
0
  switch (static_cast<WasiRawTypeT<__wasi_clockid_t>>(ClockId)) {
63
0
  case __WASI_CLOCKID_REALTIME:
64
0
  case __WASI_CLOCKID_MONOTONIC:
65
0
  case __WASI_CLOCKID_PROCESS_CPUTIME_ID:
66
0
  case __WASI_CLOCKID_THREAD_CPUTIME_ID:
67
0
    return static_cast<__wasi_clockid_t>(ClockId);
68
0
  default:
69
0
    return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
70
0
  }
71
0
}
72
73
template <>
74
WASI::WasiExpect<__wasi_advice_t>
75
0
cast<__wasi_advice_t>(uint64_t Advice) noexcept {
76
0
  switch (WasiRawTypeT<__wasi_advice_t>(Advice)) {
77
0
  case __WASI_ADVICE_NORMAL:
78
0
  case __WASI_ADVICE_SEQUENTIAL:
79
0
  case __WASI_ADVICE_RANDOM:
80
0
  case __WASI_ADVICE_WILLNEED:
81
0
  case __WASI_ADVICE_DONTNEED:
82
0
  case __WASI_ADVICE_NOREUSE:
83
0
    return static_cast<__wasi_advice_t>(Advice);
84
0
  default:
85
0
    return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
86
0
  }
87
0
}
88
89
template <>
90
WASI::WasiExpect<__wasi_whence_t>
91
0
cast<__wasi_whence_t>(uint64_t Whence) noexcept {
92
0
  switch (WasiRawTypeT<__wasi_whence_t>(Whence)) {
93
0
  case __WASI_WHENCE_SET:
94
0
  case __WASI_WHENCE_CUR:
95
0
  case __WASI_WHENCE_END:
96
0
    return static_cast<__wasi_whence_t>(Whence);
97
0
  default:
98
0
    return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
99
0
  }
100
0
}
101
102
template <>
103
WASI::WasiExpect<__wasi_eventtype_t>
104
0
cast<__wasi_eventtype_t>(uint64_t Eventtype) noexcept {
105
0
  switch (WasiRawTypeT<__wasi_eventtype_t>(Eventtype)) {
106
0
  case __WASI_EVENTTYPE_CLOCK:
107
0
  case __WASI_EVENTTYPE_FD_READ:
108
0
  case __WASI_EVENTTYPE_FD_WRITE:
109
0
    return static_cast<__wasi_eventtype_t>(Eventtype);
110
0
  default:
111
0
    return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
112
0
  }
113
0
}
114
115
template <>
116
WASI::WasiExpect<__wasi_signal_t>
117
0
cast<__wasi_signal_t>(uint64_t Signal) noexcept {
118
0
  switch (WasiRawTypeT<__wasi_signal_t>(Signal)) {
119
0
  case __WASI_SIGNAL_NONE:
120
0
  case __WASI_SIGNAL_HUP:
121
0
  case __WASI_SIGNAL_INT:
122
0
  case __WASI_SIGNAL_QUIT:
123
0
  case __WASI_SIGNAL_ILL:
124
0
  case __WASI_SIGNAL_TRAP:
125
0
  case __WASI_SIGNAL_ABRT:
126
0
  case __WASI_SIGNAL_BUS:
127
0
  case __WASI_SIGNAL_FPE:
128
0
  case __WASI_SIGNAL_KILL:
129
0
  case __WASI_SIGNAL_USR1:
130
0
  case __WASI_SIGNAL_SEGV:
131
0
  case __WASI_SIGNAL_USR2:
132
0
  case __WASI_SIGNAL_PIPE:
133
0
  case __WASI_SIGNAL_ALRM:
134
0
  case __WASI_SIGNAL_TERM:
135
0
  case __WASI_SIGNAL_CHLD:
136
0
  case __WASI_SIGNAL_CONT:
137
0
  case __WASI_SIGNAL_STOP:
138
0
  case __WASI_SIGNAL_TSTP:
139
0
  case __WASI_SIGNAL_TTIN:
140
0
  case __WASI_SIGNAL_TTOU:
141
0
  case __WASI_SIGNAL_URG:
142
0
  case __WASI_SIGNAL_XCPU:
143
0
  case __WASI_SIGNAL_XFSZ:
144
0
  case __WASI_SIGNAL_VTALRM:
145
0
  case __WASI_SIGNAL_PROF:
146
0
  case __WASI_SIGNAL_WINCH:
147
0
  case __WASI_SIGNAL_POLL:
148
0
  case __WASI_SIGNAL_PWR:
149
0
  case __WASI_SIGNAL_SYS:
150
0
    return static_cast<__wasi_signal_t>(Signal);
151
0
  default:
152
0
    return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
153
0
  }
154
0
}
155
156
template <>
157
WASI::WasiExpect<__wasi_rights_t>
158
0
cast<__wasi_rights_t>(uint64_t Rights) noexcept {
159
0
  const auto Mask =
160
0
      __WASI_RIGHTS_FD_DATASYNC | __WASI_RIGHTS_FD_READ |
161
0
      __WASI_RIGHTS_FD_SEEK | __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS |
162
0
      __WASI_RIGHTS_FD_SYNC | __WASI_RIGHTS_FD_TELL | __WASI_RIGHTS_FD_WRITE |
163
0
      __WASI_RIGHTS_FD_ADVISE | __WASI_RIGHTS_FD_ALLOCATE |
164
0
      __WASI_RIGHTS_PATH_CREATE_DIRECTORY | __WASI_RIGHTS_PATH_CREATE_FILE |
165
0
      __WASI_RIGHTS_PATH_LINK_SOURCE | __WASI_RIGHTS_PATH_LINK_TARGET |
166
0
      __WASI_RIGHTS_PATH_OPEN | __WASI_RIGHTS_FD_READDIR |
167
0
      __WASI_RIGHTS_PATH_READLINK | __WASI_RIGHTS_PATH_RENAME_SOURCE |
168
0
      __WASI_RIGHTS_PATH_RENAME_TARGET | __WASI_RIGHTS_PATH_FILESTAT_GET |
169
0
      __WASI_RIGHTS_PATH_FILESTAT_SET_SIZE |
170
0
      __WASI_RIGHTS_PATH_FILESTAT_SET_TIMES | __WASI_RIGHTS_FD_FILESTAT_GET |
171
0
      __WASI_RIGHTS_FD_FILESTAT_SET_SIZE | __WASI_RIGHTS_FD_FILESTAT_SET_TIMES |
172
0
      __WASI_RIGHTS_PATH_SYMLINK | __WASI_RIGHTS_PATH_REMOVE_DIRECTORY |
173
0
      __WASI_RIGHTS_PATH_UNLINK_FILE | __WASI_RIGHTS_POLL_FD_READWRITE |
174
0
      __WASI_RIGHTS_SOCK_SHUTDOWN | __WASI_RIGHTS_SOCK_OPEN |
175
0
      __WASI_RIGHTS_SOCK_CLOSE | __WASI_RIGHTS_SOCK_BIND |
176
0
      __WASI_RIGHTS_SOCK_RECV | __WASI_RIGHTS_SOCK_RECV_FROM |
177
0
      __WASI_RIGHTS_SOCK_SEND | __WASI_RIGHTS_SOCK_SEND_TO;
178
0
  if ((WasiRawTypeT<__wasi_rights_t>(Rights) & ~Mask) == 0) {
179
0
    return static_cast<__wasi_rights_t>(Rights);
180
0
  }
181
0
  return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
182
0
}
183
184
template <>
185
WASI::WasiExpect<__wasi_fdflags_t>
186
0
cast<__wasi_fdflags_t>(uint64_t FdFlags) noexcept {
187
0
  const auto Mask = __WASI_FDFLAGS_APPEND | __WASI_FDFLAGS_DSYNC |
188
0
                    __WASI_FDFLAGS_NONBLOCK | __WASI_FDFLAGS_RSYNC |
189
0
                    __WASI_FDFLAGS_SYNC;
190
0
  if ((WasiRawTypeT<__wasi_fdflags_t>(FdFlags) & ~Mask) == 0) {
191
0
    return static_cast<__wasi_fdflags_t>(FdFlags);
192
0
  }
193
0
  return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
194
0
}
195
196
template <>
197
WASI::WasiExpect<__wasi_fstflags_t>
198
0
cast<__wasi_fstflags_t>(uint64_t FdFlags) noexcept {
199
0
  const auto Mask = __WASI_FSTFLAGS_ATIM | __WASI_FSTFLAGS_ATIM_NOW |
200
0
                    __WASI_FSTFLAGS_MTIM | __WASI_FSTFLAGS_MTIM_NOW;
201
0
  if ((WasiRawTypeT<__wasi_fstflags_t>(FdFlags) & ~Mask) == 0) {
202
0
    const auto WasiFstFlags = static_cast<__wasi_fstflags_t>(FdFlags);
203
0
    if ((WasiFstFlags & __WASI_FSTFLAGS_ATIM) &&
204
0
        (WasiFstFlags & __WASI_FSTFLAGS_ATIM_NOW)) {
205
0
      return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
206
0
    }
207
0
    if ((WasiFstFlags & __WASI_FSTFLAGS_MTIM) &&
208
0
        (WasiFstFlags & __WASI_FSTFLAGS_MTIM_NOW)) {
209
0
      return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
210
0
    }
211
0
    return WasiFstFlags;
212
0
  }
213
214
0
  return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
215
0
}
216
217
template <>
218
WASI::WasiExpect<__wasi_lookupflags_t>
219
0
cast<__wasi_lookupflags_t>(uint64_t LookupFlags) noexcept {
220
0
  const auto Mask = __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW;
221
0
  if ((WasiRawTypeT<__wasi_lookupflags_t>(LookupFlags) & ~Mask) == 0) {
222
0
    return static_cast<__wasi_lookupflags_t>(LookupFlags);
223
0
  }
224
0
  return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
225
0
}
226
227
template <>
228
WASI::WasiExpect<__wasi_oflags_t>
229
0
cast<__wasi_oflags_t>(uint64_t OFlags) noexcept {
230
0
  const auto Mask = __WASI_OFLAGS_CREAT | __WASI_OFLAGS_DIRECTORY |
231
0
                    __WASI_OFLAGS_EXCL | __WASI_OFLAGS_TRUNC;
232
0
  if ((WasiRawTypeT<__wasi_oflags_t>(OFlags) & ~Mask) == 0) {
233
0
    return static_cast<__wasi_oflags_t>(OFlags);
234
0
  }
235
0
  return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
236
0
}
237
238
template <>
239
WASI::WasiExpect<__wasi_subclockflags_t>
240
0
cast<__wasi_subclockflags_t>(uint64_t SubClockFlags) noexcept {
241
0
  const auto Mask = __WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME;
242
0
  if ((WasiRawTypeT<__wasi_subclockflags_t>(SubClockFlags) & ~Mask) == 0) {
243
0
    return static_cast<__wasi_subclockflags_t>(SubClockFlags);
244
0
  }
245
0
  return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
246
0
}
247
248
template <>
249
WASI::WasiExpect<__wasi_riflags_t>
250
0
cast<__wasi_riflags_t>(uint64_t RiFlags) noexcept {
251
0
  const auto Mask = __WASI_RIFLAGS_RECV_PEEK | __WASI_RIFLAGS_RECV_WAITALL;
252
0
  if ((WasiRawTypeT<__wasi_riflags_t>(RiFlags) & ~Mask) == 0) {
253
0
    return static_cast<__wasi_riflags_t>(RiFlags);
254
0
  }
255
0
  return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
256
0
}
257
258
template <>
259
WASI::WasiExpect<__wasi_siflags_t>
260
0
cast<__wasi_siflags_t>(uint64_t SiFlags) noexcept {
261
0
  const auto Mask = 0;
262
0
  if ((WasiRawTypeT<__wasi_siflags_t>(SiFlags) & ~Mask) == 0) {
263
0
    return static_cast<__wasi_siflags_t>(SiFlags);
264
0
  }
265
0
  return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
266
0
}
267
268
template <>
269
WASI::WasiExpect<__wasi_sdflags_t>
270
0
cast<__wasi_sdflags_t>(uint64_t SdFlags) noexcept {
271
0
  const auto Mask = __WASI_SDFLAGS_RD | __WASI_SDFLAGS_WR;
272
0
  if ((WasiRawTypeT<__wasi_sdflags_t>(SdFlags) & ~Mask) == 0) {
273
0
    return static_cast<__wasi_sdflags_t>(SdFlags);
274
0
  }
275
0
  return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
276
0
}
277
278
template <>
279
WASI::WasiExpect<__wasi_address_family_t>
280
0
cast<__wasi_address_family_t>(uint64_t Family) noexcept {
281
0
  switch (WasiRawTypeT<__wasi_address_family_t>(Family)) {
282
0
  case __WASI_ADDRESS_FAMILY_INET4:
283
0
  case __WASI_ADDRESS_FAMILY_INET6:
284
0
  case __WASI_ADDRESS_FAMILY_AF_UNIX:
285
0
    return static_cast<__wasi_address_family_t>(Family);
286
0
  default:
287
0
    return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
288
0
  }
289
0
}
290
291
template <>
292
WASI::WasiExpect<__wasi_sock_type_t>
293
0
cast<__wasi_sock_type_t>(uint64_t SockType) noexcept {
294
0
  switch (WasiRawTypeT<__wasi_sock_type_t>(SockType)) {
295
0
  case __WASI_SOCK_TYPE_SOCK_DGRAM:
296
0
  case __WASI_SOCK_TYPE_SOCK_STREAM:
297
0
    return static_cast<__wasi_sock_type_t>(SockType);
298
0
  default:
299
0
    return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
300
0
  }
301
0
}
302
303
template <>
304
WASI::WasiExpect<__wasi_sock_opt_level_t>
305
0
cast<__wasi_sock_opt_level_t>(uint64_t SockOptLevel) noexcept {
306
0
  switch (WasiRawTypeT<__wasi_sock_opt_level_t>(SockOptLevel)) {
307
0
  case __WASI_SOCK_OPT_LEVEL_SOL_SOCKET:
308
0
    return static_cast<__wasi_sock_opt_level_t>(SockOptLevel);
309
0
  default:
310
0
    return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
311
0
  }
312
0
}
313
314
template <>
315
WASI::WasiExpect<__wasi_sock_opt_so_t>
316
0
cast<__wasi_sock_opt_so_t>(uint64_t SockOptName) noexcept {
317
0
  switch (WasiRawTypeT<__wasi_sock_opt_so_t>(SockOptName)) {
318
0
  case __WASI_SOCK_OPT_SO_REUSEADDR:
319
0
  case __WASI_SOCK_OPT_SO_TYPE:
320
0
  case __WASI_SOCK_OPT_SO_ERROR:
321
0
  case __WASI_SOCK_OPT_SO_DONTROUTE:
322
0
  case __WASI_SOCK_OPT_SO_BROADCAST:
323
0
  case __WASI_SOCK_OPT_SO_SNDBUF:
324
0
  case __WASI_SOCK_OPT_SO_RCVBUF:
325
0
  case __WASI_SOCK_OPT_SO_KEEPALIVE:
326
0
  case __WASI_SOCK_OPT_SO_OOBINLINE:
327
0
  case __WASI_SOCK_OPT_SO_LINGER:
328
0
  case __WASI_SOCK_OPT_SO_RCVLOWAT:
329
0
  case __WASI_SOCK_OPT_SO_RCVTIMEO:
330
0
  case __WASI_SOCK_OPT_SO_SNDTIMEO:
331
0
  case __WASI_SOCK_OPT_SO_ACCEPTCONN:
332
0
  case __WASI_SOCK_OPT_SO_BINDTODEVICE:
333
0
    return static_cast<__wasi_sock_opt_so_t>(SockOptName);
334
0
  default:
335
0
    return WASI::WasiUnexpect(__WASI_ERRNO_INVAL);
336
0
  }
337
0
}
338
339
template <typename T, size_t MaxSize> class StaticVector {
340
public:
341
0
  constexpr StaticVector() = default;
Unexecuted instantiation: wasifunc.cpp:WasmEdge::Host::(anonymous namespace)::StaticVector<cxx20::span<unsigned char, 18446744073709551615ul>, 1024ul>::StaticVector()
Unexecuted instantiation: wasifunc.cpp:WasmEdge::Host::(anonymous namespace)::StaticVector<cxx20::span<unsigned char const, 18446744073709551615ul>, 1024ul>::StaticVector()
342
  constexpr const T *data() const noexcept {
343
    return reinterpret_cast<T *>(Storage);
344
  }
345
0
  constexpr T *data() noexcept { return reinterpret_cast<T *>(Storage); }
Unexecuted instantiation: wasifunc.cpp:WasmEdge::Host::(anonymous namespace)::StaticVector<cxx20::span<unsigned char, 18446744073709551615ul>, 1024ul>::data()
Unexecuted instantiation: wasifunc.cpp:WasmEdge::Host::(anonymous namespace)::StaticVector<cxx20::span<unsigned char const, 18446744073709551615ul>, 1024ul>::data()
346
0
  constexpr size_t size() const noexcept { return Size; }
Unexecuted instantiation: wasifunc.cpp:WasmEdge::Host::(anonymous namespace)::StaticVector<cxx20::span<unsigned char, 18446744073709551615ul>, 1024ul>::size() const
Unexecuted instantiation: wasifunc.cpp:WasmEdge::Host::(anonymous namespace)::StaticVector<cxx20::span<unsigned char const, 18446744073709551615ul>, 1024ul>::size() const
347
  template <typename... ArgsT>
348
  void emplace_back_unchecked(ArgsT &&...Args) noexcept(
349
0
      std::is_nothrow_constructible_v<T, ArgsT...>) {
350
0
    assuming(Size < MaxSize);
351
0
    new (data() + Size) T(std::forward<ArgsT>(Args)...);
352
0
    ++Size;
353
0
  }
Unexecuted instantiation: wasifunc.cpp:void WasmEdge::Host::(anonymous namespace)::StaticVector<cxx20::span<unsigned char, 18446744073709551615ul>, 1024ul>::emplace_back_unchecked<cxx20::span<unsigned char, 18446744073709551615ul> const&>(cxx20::span<unsigned char, 18446744073709551615ul> const&)
Unexecuted instantiation: wasifunc.cpp:void WasmEdge::Host::(anonymous namespace)::StaticVector<cxx20::span<unsigned char const, 18446744073709551615ul>, 1024ul>::emplace_back_unchecked<cxx20::span<unsigned char const, 18446744073709551615ul> const&>(cxx20::span<unsigned char const, 18446744073709551615ul> const&)
Unexecuted instantiation: wasifunc.cpp:void WasmEdge::Host::(anonymous namespace)::StaticVector<cxx20::span<unsigned char const, 18446744073709551615ul>, 1024ul>::emplace_back_unchecked<cxx20::span<unsigned char, 18446744073709551615ul> const&>(cxx20::span<unsigned char, 18446744073709551615ul> const&)
354
0
  ~StaticVector() noexcept(std::is_nothrow_destructible_v<T>) {
355
0
    std::destroy_n(data(), Size);
356
0
  }
Unexecuted instantiation: wasifunc.cpp:WasmEdge::Host::(anonymous namespace)::StaticVector<cxx20::span<unsigned char, 18446744073709551615ul>, 1024ul>::~StaticVector()
Unexecuted instantiation: wasifunc.cpp:WasmEdge::Host::(anonymous namespace)::StaticVector<cxx20::span<unsigned char const, 18446744073709551615ul>, 1024ul>::~StaticVector()
357
358
private:
359
  size_t Size = 0;
360
  alignas(alignof(T)) uint8_t Storage[sizeof(T[MaxSize])];
361
};
362
363
bool AllowAFUNIX(const Runtime::CallingFrame &Frame,
364
0
                 __wasi_address_family_t AddressFamily) {
365
0
  if (AddressFamily == __WASI_ADDRESS_FAMILY_AF_UNIX) {
366
0
    return Frame.getExecutor()
367
0
        ->getConfigure()
368
0
        .getRuntimeConfigure()
369
0
        .isAllowAFUNIX();
370
0
  }
371
0
  return true;
372
0
}
373
} // namespace
374
375
Expect<uint32_t> WasiArgsGet::body(const Runtime::CallingFrame &Frame,
376
0
                                   uint32_t ArgvPtr, uint32_t ArgvBufPtr) {
377
  // Check memory instance from module.
378
0
  auto *MemInst = Frame.getMemoryByIndex(0);
379
0
  if (MemInst == nullptr) {
380
0
    return __WASI_ERRNO_FAULT;
381
0
  }
382
383
  // Store **Argv.
384
0
  const auto &Arguments = Env.getArguments();
385
0
  const uint32_t ArgvSize = static_cast<uint32_t>(Arguments.size());
386
0
  const uint32_t ArgvBufSize = calculateBufferSize(Arguments);
387
388
  // Check for invalid address.
389
0
  const auto Argv = MemInst->getSpan<uint8_t_ptr>(ArgvPtr, ArgvSize);
390
0
  if (unlikely(Argv.size() != ArgvSize)) {
391
0
    return __WASI_ERRNO_FAULT;
392
0
  }
393
0
  const auto ArgvBuf = MemInst->getSpan<uint8_t>(ArgvBufPtr, ArgvBufSize);
394
0
  if (unlikely(ArgvBuf.size() != ArgvBufSize)) {
395
0
    return __WASI_ERRNO_FAULT;
396
0
  }
397
398
0
  if (!Argv.empty()) {
399
0
    Argv[0] = ArgvBufPtr;
400
0
  }
401
402
0
  if (auto Res = Env.argsGet(Argv, ArgvBuf); unlikely(!Res)) {
403
0
    return Res.error();
404
0
  }
405
406
0
  return __WASI_ERRNO_SUCCESS;
407
0
}
408
409
Expect<uint32_t> WasiArgsSizesGet::body(const Runtime::CallingFrame &Frame,
410
                                        uint32_t /* Out */ ArgcPtr,
411
0
                                        uint32_t /* Out */ ArgvBufSizePtr) {
412
  // Check memory instance from module.
413
0
  auto *MemInst = Frame.getMemoryByIndex(0);
414
0
  if (MemInst == nullptr) {
415
0
    return __WASI_ERRNO_FAULT;
416
0
  }
417
418
  // Check for invalid address.
419
0
  auto *const __restrict__ Argc = MemInst->getPointer<__wasi_size_t *>(ArgcPtr);
420
0
  if (unlikely(Argc == nullptr)) {
421
0
    return __WASI_ERRNO_FAULT;
422
0
  }
423
0
  auto *const __restrict__ ArgvBufSize =
424
0
      MemInst->getPointer<__wasi_size_t *>(ArgvBufSizePtr);
425
0
  if (unlikely(ArgvBufSize == nullptr)) {
426
0
    return __WASI_ERRNO_FAULT;
427
0
  }
428
429
0
  if (auto Res = Env.argsSizesGet(*Argc, *ArgvBufSize); unlikely(!Res)) {
430
0
    return Res.error();
431
0
  }
432
0
  return __WASI_ERRNO_SUCCESS;
433
0
}
434
435
Expect<uint32_t> WasiEnvironGet::body(const Runtime::CallingFrame &Frame,
436
0
                                      uint32_t EnvPtr, uint32_t EnvBufPtr) {
437
  // Check memory instance from module.
438
0
  auto *MemInst = Frame.getMemoryByIndex(0);
439
0
  if (MemInst == nullptr) {
440
0
    return __WASI_ERRNO_FAULT;
441
0
  }
442
443
  // Store **Env.
444
0
  const auto &EnvironVariables = Env.getEnvironVariables();
445
0
  const uint32_t EnvSize = static_cast<uint32_t>(EnvironVariables.size());
446
0
  const uint32_t EnvBufSize = calculateBufferSize(EnvironVariables);
447
448
  // Check for invalid address.
449
0
  const auto EnvSpan = MemInst->getSpan<uint8_t_ptr>(EnvPtr, EnvSize);
450
0
  if (unlikely(EnvSpan.size() != EnvSize)) {
451
0
    return __WASI_ERRNO_FAULT;
452
0
  }
453
0
  const auto EnvBuf = MemInst->getSpan<uint8_t>(EnvBufPtr, EnvBufSize);
454
0
  if (unlikely(EnvBuf.size() != EnvBufSize)) {
455
0
    return __WASI_ERRNO_FAULT;
456
0
  }
457
458
0
  if (!EnvSpan.empty()) {
459
0
    EnvSpan[0] = EnvBufPtr;
460
0
  }
461
462
0
  if (auto Res = this->Env.environGet(EnvSpan, EnvBuf); unlikely(!Res)) {
463
0
    return Res.error();
464
0
  }
465
466
0
  return __WASI_ERRNO_SUCCESS;
467
0
}
468
469
Expect<uint32_t> WasiEnvironSizesGet::body(const Runtime::CallingFrame &Frame,
470
                                           uint32_t /* Out */ EnvCntPtr,
471
0
                                           uint32_t /* Out */ EnvBufSizePtr) {
472
  // Check memory instance from module.
473
0
  auto *MemInst = Frame.getMemoryByIndex(0);
474
0
  if (MemInst == nullptr) {
475
0
    return __WASI_ERRNO_FAULT;
476
0
  }
477
478
  // Check for invalid address.
479
0
  auto *const __restrict__ Envc =
480
0
      MemInst->getPointer<__wasi_size_t *>(EnvCntPtr);
481
0
  if (unlikely(Envc == nullptr)) {
482
0
    return __WASI_ERRNO_FAULT;
483
0
  }
484
0
  auto *const __restrict__ EnvBufSize =
485
0
      MemInst->getPointer<__wasi_size_t *>(EnvBufSizePtr);
486
0
  if (unlikely(EnvBufSize == nullptr)) {
487
0
    return __WASI_ERRNO_FAULT;
488
0
  }
489
490
0
  if (auto Res = Env.environSizesGet(*Envc, *EnvBufSize); unlikely(!Res)) {
491
0
    return Res.error();
492
0
  }
493
0
  return __WASI_ERRNO_SUCCESS;
494
0
}
495
496
Expect<uint32_t> WasiClockResGet::body(const Runtime::CallingFrame &Frame,
497
                                       uint32_t ClockId,
498
0
                                       uint32_t /* Out */ ResolutionPtr) {
499
  // Check memory instance from module.
500
0
  auto *MemInst = Frame.getMemoryByIndex(0);
501
0
  if (MemInst == nullptr) {
502
0
    return __WASI_ERRNO_FAULT;
503
0
  }
504
505
0
  auto *const Resolution =
506
0
      MemInst->getPointer<__wasi_timestamp_t *>(ResolutionPtr);
507
0
  if (unlikely(Resolution == nullptr)) {
508
0
    return __WASI_ERRNO_FAULT;
509
0
  }
510
511
0
  __wasi_clockid_t WasiClockId;
512
0
  if (auto Res = cast<__wasi_clockid_t>(ClockId); unlikely(!Res)) {
513
0
    return Res.error();
514
0
  } else {
515
0
    WasiClockId = *Res;
516
0
  }
517
518
0
  if (auto Res = Env.clockResGet(WasiClockId, *Resolution); unlikely(!Res)) {
519
0
    return Res.error();
520
0
  }
521
0
  return __WASI_ERRNO_SUCCESS;
522
0
}
523
524
Expect<uint32_t> WasiClockTimeGet::body(const Runtime::CallingFrame &Frame,
525
                                        uint32_t ClockId, uint64_t Precision,
526
0
                                        uint32_t /* Out */ TimePtr) {
527
  // Check memory instance from module.
528
0
  auto *MemInst = Frame.getMemoryByIndex(0);
529
0
  if (MemInst == nullptr) {
530
0
    return __WASI_ERRNO_FAULT;
531
0
  }
532
533
0
  auto *const Time = MemInst->getPointer<__wasi_timestamp_t *>(TimePtr);
534
0
  if (unlikely(Time == nullptr)) {
535
0
    return __WASI_ERRNO_FAULT;
536
0
  }
537
538
0
  __wasi_clockid_t WasiClockId;
539
0
  if (auto Res = cast<__wasi_clockid_t>(ClockId); unlikely(!Res)) {
540
0
    return Res.error();
541
0
  } else {
542
0
    WasiClockId = *Res;
543
0
  }
544
545
0
  const __wasi_timestamp_t WasiPrecision = Precision;
546
547
0
  if (auto Res = Env.clockTimeGet(WasiClockId, WasiPrecision, *Time);
548
0
      unlikely(!Res)) {
549
0
    return Res.error();
550
0
  }
551
0
  return __WASI_ERRNO_SUCCESS;
552
0
}
553
554
Expect<uint32_t> WasiFdAdvise::body(const Runtime::CallingFrame &, int32_t Fd,
555
                                    uint64_t Offset, uint64_t Len,
556
0
                                    uint32_t Advice) {
557
0
  __wasi_advice_t WasiAdvice;
558
0
  if (auto Res = cast<__wasi_advice_t>(Advice); unlikely(!Res)) {
559
0
    return Res.error();
560
0
  } else {
561
0
    WasiAdvice = *Res;
562
0
  }
563
564
0
  const __wasi_fd_t WasiFd = Fd;
565
0
  const __wasi_filesize_t WasiOffset = Offset;
566
0
  const __wasi_filesize_t WasiLen = Len;
567
568
0
  if (auto Res = Env.fdAdvise(WasiFd, WasiOffset, WasiLen, WasiAdvice);
569
0
      unlikely(!Res)) {
570
0
    return Res.error();
571
0
  }
572
0
  return __WASI_ERRNO_SUCCESS;
573
0
}
574
575
Expect<uint32_t> WasiFdAllocate::body(const Runtime::CallingFrame &, int32_t Fd,
576
0
                                      uint64_t Offset, uint64_t Len) {
577
0
  const __wasi_fd_t WasiFd = Fd;
578
0
  const __wasi_filesize_t WasiOffset = Offset;
579
0
  const __wasi_filesize_t WasiLen = Len;
580
581
0
  if (auto Res = Env.fdAllocate(WasiFd, WasiOffset, WasiLen); unlikely(!Res)) {
582
0
    return Res.error();
583
0
  }
584
0
  return __WASI_ERRNO_SUCCESS;
585
0
}
586
587
0
Expect<uint32_t> WasiFdClose::body(const Runtime::CallingFrame &, int32_t Fd) {
588
0
  const __wasi_fd_t WasiFd = Fd;
589
590
0
  if (auto Res = Env.fdClose(WasiFd); unlikely(!Res)) {
591
0
    return Res.error();
592
0
  }
593
0
  return __WASI_ERRNO_SUCCESS;
594
0
}
595
596
Expect<uint32_t> WasiFdDatasync::body(const Runtime::CallingFrame &,
597
0
                                      int32_t Fd) {
598
0
  const __wasi_fd_t WasiFd = Fd;
599
600
0
  if (auto Res = Env.fdDatasync(WasiFd); unlikely(!Res)) {
601
0
    return Res.error();
602
0
  }
603
0
  return __WASI_ERRNO_SUCCESS;
604
0
}
605
606
Expect<uint32_t> WasiFdFdstatGet::body(const Runtime::CallingFrame &Frame,
607
                                       int32_t Fd,
608
0
                                       uint32_t /* Out */ FdStatPtr) {
609
  // Check memory instance from module.
610
0
  auto *MemInst = Frame.getMemoryByIndex(0);
611
0
  if (MemInst == nullptr) {
612
0
    return __WASI_ERRNO_FAULT;
613
0
  }
614
615
0
  auto *const FdStat = MemInst->getPointer<__wasi_fdstat_t *>(FdStatPtr);
616
0
  if (unlikely(FdStat == nullptr)) {
617
0
    return __WASI_ERRNO_FAULT;
618
0
  }
619
620
0
  const __wasi_fd_t WasiFd = Fd;
621
622
0
  if (auto Res = Env.fdFdstatGet(WasiFd, *FdStat); unlikely(!Res)) {
623
0
    return Res.error();
624
0
  }
625
0
  return __WASI_ERRNO_SUCCESS;
626
0
}
627
628
Expect<uint32_t> WasiFdFdstatSetFlags::body(const Runtime::CallingFrame &,
629
0
                                            int32_t Fd, uint32_t FsFlags) {
630
0
  __wasi_fdflags_t WasiFdFlags;
631
0
  if (auto Res = cast<__wasi_fdflags_t>(FsFlags); unlikely(!Res)) {
632
0
    return Res.error();
633
0
  } else {
634
0
    WasiFdFlags = *Res;
635
0
  }
636
637
0
  const __wasi_fd_t WasiFd = Fd;
638
639
0
  if (auto Res = Env.fdFdstatSetFlags(WasiFd, WasiFdFlags); unlikely(!Res)) {
640
0
    return Res.error();
641
0
  }
642
0
  return __WASI_ERRNO_SUCCESS;
643
0
}
644
645
Expect<uint32_t> WasiFdFdstatSetRights::body(const Runtime::CallingFrame &,
646
                                             int32_t Fd, uint64_t FsRightsBase,
647
0
                                             uint64_t FsRightsInheriting) {
648
0
  __wasi_rights_t WasiFsRightsBase;
649
0
  if (auto Res = cast<__wasi_rights_t>(FsRightsBase); unlikely(!Res)) {
650
0
    return Res.error();
651
0
  } else {
652
0
    WasiFsRightsBase = *Res;
653
0
  }
654
655
0
  __wasi_rights_t WasiFsRightsInheriting;
656
0
  if (auto Res = cast<__wasi_rights_t>(FsRightsInheriting); unlikely(!Res)) {
657
0
    return Res.error();
658
0
  } else {
659
0
    WasiFsRightsInheriting = *Res;
660
0
  }
661
662
0
  const __wasi_fd_t WasiFd = Fd;
663
664
0
  if (auto Res = Env.fdFdstatSetRights(WasiFd, WasiFsRightsBase,
665
0
                                       WasiFsRightsInheriting);
666
0
      unlikely(!Res)) {
667
0
    return Res.error();
668
0
  }
669
0
  return __WASI_ERRNO_SUCCESS;
670
0
}
671
672
Expect<uint32_t> WasiFdFilestatGet::body(const Runtime::CallingFrame &Frame,
673
                                         int32_t Fd,
674
0
                                         uint32_t /* Out */ FilestatPtr) {
675
  // Check memory instance from module.
676
0
  auto *MemInst = Frame.getMemoryByIndex(0);
677
0
  if (MemInst == nullptr) {
678
0
    return __WASI_ERRNO_FAULT;
679
0
  }
680
681
0
  auto *const Filestat = MemInst->getPointer<__wasi_filestat_t *>(FilestatPtr);
682
0
  if (unlikely(Filestat == nullptr)) {
683
0
    return __WASI_ERRNO_FAULT;
684
0
  }
685
686
0
  const __wasi_fd_t WasiFd = Fd;
687
688
0
  if (auto Res = Env.fdFilestatGet(WasiFd, *Filestat); unlikely(!Res)) {
689
0
    return Res.error();
690
0
  }
691
0
  return __WASI_ERRNO_SUCCESS;
692
0
}
693
694
Expect<uint32_t> WasiFdFilestatSetSize::body(const Runtime::CallingFrame &,
695
0
                                             int32_t Fd, uint64_t Size) {
696
0
  const __wasi_fd_t WasiFd = Fd;
697
0
  const __wasi_filesize_t WasiSize = Size;
698
699
0
  if (auto Res = Env.fdFilestatSetSize(WasiFd, WasiSize); unlikely(!Res)) {
700
0
    return Res.error();
701
0
  }
702
0
  return __WASI_ERRNO_SUCCESS;
703
0
}
704
705
Expect<uint32_t> WasiFdFilestatSetTimes::body(const Runtime::CallingFrame &,
706
                                              int32_t Fd, uint64_t ATim,
707
                                              uint64_t MTim,
708
0
                                              uint32_t FstFlags) {
709
0
  __wasi_fstflags_t WasiFstFlags;
710
0
  if (auto Res = cast<__wasi_fstflags_t>(FstFlags); unlikely(!Res)) {
711
0
    return Res.error();
712
0
  } else {
713
0
    WasiFstFlags = *Res;
714
0
  }
715
716
0
  const __wasi_fd_t WasiFd = Fd;
717
0
  const __wasi_timestamp_t WasiATim = ATim;
718
0
  const __wasi_timestamp_t WasiMTim = MTim;
719
720
0
  if (auto Res =
721
0
          Env.fdFilestatSetTimes(WasiFd, WasiATim, WasiMTim, WasiFstFlags);
722
0
      unlikely(!Res)) {
723
0
    return Res.error();
724
0
  }
725
0
  return __WASI_ERRNO_SUCCESS;
726
0
}
727
728
Expect<uint32_t> WasiFdPread::body(const Runtime::CallingFrame &Frame,
729
                                   int32_t Fd, uint32_t IOVsPtr,
730
                                   uint32_t IOVsLen, uint64_t Offset,
731
0
                                   uint32_t /* Out */ NReadPtr) {
732
  // Check memory instance from module.
733
0
  auto *MemInst = Frame.getMemoryByIndex(0);
734
0
  if (MemInst == nullptr) {
735
0
    return __WASI_ERRNO_FAULT;
736
0
  }
737
738
0
  const __wasi_size_t WasiIOVsLen = IOVsLen;
739
0
  if (unlikely(WasiIOVsLen > WASI::kIOVMax)) {
740
0
    return __WASI_ERRNO_INVAL;
741
0
  }
742
743
  // Check for invalid address.
744
0
  const auto IOVsArray = MemInst->getSpan<__wasi_iovec_t>(IOVsPtr, WasiIOVsLen);
745
0
  if (unlikely(IOVsArray.size() != WasiIOVsLen)) {
746
0
    return __WASI_ERRNO_FAULT;
747
0
  }
748
749
0
  auto *const NRead = MemInst->getPointer<__wasi_size_t *>(NReadPtr);
750
0
  if (unlikely(NRead == nullptr)) {
751
0
    return __WASI_ERRNO_FAULT;
752
0
  }
753
754
0
  __wasi_size_t TotalSize = 0;
755
0
  StaticVector<Span<uint8_t>, WASI::kIOVMax> WasiIOVs;
756
757
0
  for (auto &IOV : IOVsArray) {
758
    // Capping total size.
759
0
    const __wasi_size_t Space =
760
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
761
0
    const EndianValue<uint32_t> IOVBufLen = IOV.buf_len;
762
0
    const __wasi_size_t BufLen =
763
0
        unlikely(IOVBufLen.le() > Space) ? Space : IOVBufLen.le();
764
0
    TotalSize += BufLen;
765
766
    // Check for invalid address.
767
0
    const auto ReadArr =
768
0
        MemInst->getSpan<uint8_t>(EndianValue(IOV.buf).le(), BufLen);
769
0
    if (unlikely(ReadArr.size() != BufLen)) {
770
0
      return __WASI_ERRNO_FAULT;
771
0
    }
772
0
    WasiIOVs.emplace_back_unchecked(ReadArr);
773
0
  }
774
775
0
  const __wasi_fd_t WasiFd = Fd;
776
0
  const __wasi_filesize_t WasiOffset = Offset;
777
778
0
  if (auto Res = Env.fdPread(WasiFd, WasiIOVs, WasiOffset, *NRead);
779
0
      unlikely(!Res)) {
780
0
    return Res.error();
781
0
  }
782
0
  return __WASI_ERRNO_SUCCESS;
783
0
}
784
785
Expect<uint32_t> WasiFdPrestatDirName::body(const Runtime::CallingFrame &Frame,
786
                                            int32_t Fd, uint32_t PathBufPtr,
787
0
                                            uint32_t PathLen) {
788
  // Check memory instance from module.
789
0
  auto *MemInst = Frame.getMemoryByIndex(0);
790
0
  if (MemInst == nullptr) {
791
0
    return __WASI_ERRNO_FAULT;
792
0
  }
793
794
0
  const auto PathBuf = MemInst->getSpan<uint8_t>(PathBufPtr, PathLen);
795
0
  if (unlikely(PathBuf.size() != PathLen)) {
796
0
    return __WASI_ERRNO_FAULT;
797
0
  }
798
799
0
  const __wasi_fd_t WasiFd = Fd;
800
801
0
  if (auto Res = Env.fdPrestatDirName(WasiFd, PathBuf); unlikely(!Res)) {
802
0
    return Res.error();
803
0
  }
804
0
  return __WASI_ERRNO_SUCCESS;
805
0
}
806
807
Expect<uint32_t> WasiFdPrestatGet::body(const Runtime::CallingFrame &Frame,
808
                                        int32_t Fd,
809
0
                                        uint32_t /* Out */ PreStatPtr) {
810
  // Check memory instance from module.
811
0
  auto *MemInst = Frame.getMemoryByIndex(0);
812
0
  if (MemInst == nullptr) {
813
0
    return __WASI_ERRNO_FAULT;
814
0
  }
815
816
0
  __wasi_prestat_t *const PreStat =
817
0
      MemInst->getPointer<__wasi_prestat_t *>(PreStatPtr);
818
0
  if (unlikely(PreStat == nullptr)) {
819
0
    return __WASI_ERRNO_FAULT;
820
0
  }
821
822
0
  const __wasi_fd_t WasiFd = Fd;
823
824
0
  if (auto Res = Env.fdPrestatGet(WasiFd, *PreStat); unlikely(!Res)) {
825
0
    return Res.error();
826
0
  }
827
0
  return __WASI_ERRNO_SUCCESS;
828
0
}
829
830
Expect<uint32_t> WasiFdPwrite::body(const Runtime::CallingFrame &Frame,
831
                                    int32_t Fd, uint32_t IOVsPtr,
832
                                    uint32_t IOVsLen, uint64_t Offset,
833
0
                                    uint32_t /* Out */ NWrittenPtr) {
834
  // Check memory instance from module.
835
0
  auto *MemInst = Frame.getMemoryByIndex(0);
836
0
  if (MemInst == nullptr) {
837
0
    return __WASI_ERRNO_FAULT;
838
0
  }
839
840
0
  const __wasi_size_t WasiIOVsLen = IOVsLen;
841
0
  if (unlikely(WasiIOVsLen > WASI::kIOVMax)) {
842
0
    return __WASI_ERRNO_INVAL;
843
0
  }
844
845
  // Check for invalid address.
846
0
  const auto IOVsArray =
847
0
      MemInst->getSpan<__wasi_ciovec_t>(IOVsPtr, WasiIOVsLen);
848
0
  if (unlikely(IOVsArray.size() != WasiIOVsLen)) {
849
0
    return __WASI_ERRNO_FAULT;
850
0
  }
851
852
  // Check for invalid address.
853
0
  auto *const NWritten = MemInst->getPointer<__wasi_size_t *>(NWrittenPtr);
854
0
  if (unlikely(NWritten == nullptr)) {
855
0
    return __WASI_ERRNO_FAULT;
856
0
  }
857
858
0
  __wasi_size_t TotalSize = 0;
859
0
  StaticVector<Span<const uint8_t>, WASI::kIOVMax> WasiIOVs;
860
861
0
  for (auto &IOV : IOVsArray) {
862
    // Capping total size.
863
0
    const __wasi_size_t Space =
864
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
865
866
0
    const EndianValue<uint32_t> IOVBufLen = IOV.buf_len;
867
0
    const __wasi_size_t BufLen =
868
0
        unlikely(IOVBufLen.le() > Space) ? Space : IOVBufLen.le();
869
0
    TotalSize += BufLen;
870
871
    // Check for invalid address.
872
0
    const auto WriteArr =
873
0
        MemInst->getSpan<const uint8_t>(EndianValue(IOV.buf).le(), BufLen);
874
0
    if (unlikely(WriteArr.size() != BufLen)) {
875
0
      return __WASI_ERRNO_FAULT;
876
0
    }
877
0
    WasiIOVs.emplace_back_unchecked(WriteArr);
878
0
  }
879
880
0
  const __wasi_fd_t WasiFd = Fd;
881
0
  const __wasi_filesize_t WasiOffset = Offset;
882
883
0
  if (auto Res = Env.fdPwrite(WasiFd, WasiIOVs, WasiOffset, *NWritten);
884
0
      unlikely(!Res)) {
885
0
    return Res.error();
886
0
  }
887
0
  return __WASI_ERRNO_SUCCESS;
888
0
}
889
890
Expect<uint32_t> WasiFdRead::body(const Runtime::CallingFrame &Frame,
891
                                  int32_t Fd, uint32_t IOVsPtr,
892
                                  uint32_t IOVsLen,
893
0
                                  uint32_t /* Out */ NReadPtr) {
894
  // Check memory instance from module.
895
0
  auto *MemInst = Frame.getMemoryByIndex(0);
896
0
  if (MemInst == nullptr) {
897
0
    return __WASI_ERRNO_FAULT;
898
0
  }
899
900
0
  const __wasi_size_t WasiIOVsLen = IOVsLen;
901
0
  if (unlikely(WasiIOVsLen > WASI::kIOVMax)) {
902
0
    return __WASI_ERRNO_INVAL;
903
0
  }
904
905
  // Check for invalid address.
906
0
  const auto IOVsArray = MemInst->getSpan<__wasi_iovec_t>(IOVsPtr, WasiIOVsLen);
907
0
  if (unlikely(IOVsArray.size() != WasiIOVsLen)) {
908
0
    return __WASI_ERRNO_FAULT;
909
0
  }
910
911
0
  auto *const NRead = MemInst->getPointer<__wasi_size_t *>(NReadPtr);
912
0
  if (unlikely(NRead == nullptr)) {
913
0
    return __WASI_ERRNO_FAULT;
914
0
  }
915
916
0
  __wasi_size_t TotalSize = 0;
917
0
  StaticVector<Span<uint8_t>, WASI::kIOVMax> WasiIOVs;
918
919
0
  for (auto &IOV : IOVsArray) {
920
    // Capping total size.
921
0
    const __wasi_size_t Space =
922
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
923
0
    const EndianValue<uint32_t> IOVBufLen = IOV.buf_len;
924
0
    const __wasi_size_t BufLen =
925
0
        unlikely(IOVBufLen.le() > Space) ? Space : IOVBufLen.le();
926
0
    TotalSize += BufLen;
927
928
    // Check for invalid address.
929
0
    const auto ReadArr =
930
0
        MemInst->getSpan<uint8_t>(EndianValue(IOV.buf).le(), BufLen);
931
0
    if (unlikely(ReadArr.size() != BufLen)) {
932
0
      return __WASI_ERRNO_FAULT;
933
0
    }
934
0
    WasiIOVs.emplace_back_unchecked(ReadArr);
935
0
  }
936
937
0
  const __wasi_fd_t WasiFd = Fd;
938
939
0
  if (auto Res = Env.fdRead(WasiFd, WasiIOVs, *NRead); unlikely(!Res)) {
940
0
    return Res.error();
941
0
  }
942
0
  return __WASI_ERRNO_SUCCESS;
943
0
}
944
945
Expect<uint32_t> WasiFdReadDir::body(const Runtime::CallingFrame &Frame,
946
                                     int32_t Fd, uint32_t BufPtr,
947
                                     uint32_t BufLen, uint64_t Cookie,
948
0
                                     uint32_t /* Out */ NReadPtr) {
949
  // Check memory instance from module.
950
0
  auto *MemInst = Frame.getMemoryByIndex(0);
951
0
  if (MemInst == nullptr) {
952
0
    return __WASI_ERRNO_FAULT;
953
0
  }
954
955
0
  const __wasi_size_t WasiBufLen = BufLen;
956
957
  // Check for invalid address.
958
0
  const auto Buf = MemInst->getSpan<uint8_t>(BufPtr, WasiBufLen);
959
0
  if (unlikely(Buf.size() != WasiBufLen)) {
960
0
    return __WASI_ERRNO_FAULT;
961
0
  }
962
963
0
  auto *const NRead = MemInst->getPointer<__wasi_size_t *>(NReadPtr);
964
0
  if (unlikely(NRead == nullptr)) {
965
0
    return __WASI_ERRNO_FAULT;
966
0
  }
967
968
0
  const __wasi_fd_t WasiFd = Fd;
969
0
  const __wasi_dircookie_t WasiCookie = Cookie;
970
971
0
  if (auto Res = Env.fdReaddir(WasiFd, Buf, WasiCookie, *NRead);
972
0
      unlikely(!Res)) {
973
0
    return Res.error();
974
0
  }
975
0
  return __WASI_ERRNO_SUCCESS;
976
0
}
977
978
Expect<uint32_t> WasiFdRenumber::body(const Runtime::CallingFrame &, int32_t Fd,
979
0
                                      int32_t ToFd) {
980
0
  const __wasi_fd_t WasiFd = Fd;
981
0
  const __wasi_fd_t WasiToFd = ToFd;
982
983
0
  if (auto Res = Env.fdRenumber(WasiFd, WasiToFd); unlikely(!Res)) {
984
0
    return Res.error();
985
0
  }
986
0
  return __WASI_ERRNO_SUCCESS;
987
0
}
988
989
Expect<int32_t> WasiFdSeek::body(const Runtime::CallingFrame &Frame, int32_t Fd,
990
                                 int64_t Offset, uint32_t Whence,
991
0
                                 uint32_t /* Out */ NewOffsetPtr) {
992
  // Check memory instance from module.
993
0
  auto *MemInst = Frame.getMemoryByIndex(0);
994
0
  if (MemInst == nullptr) {
995
0
    return __WASI_ERRNO_FAULT;
996
0
  }
997
998
0
  __wasi_whence_t WasiWhence;
999
0
  if (auto Res = cast<__wasi_whence_t>(Whence); unlikely(!Res)) {
1000
0
    return Res.error();
1001
0
  } else {
1002
0
    WasiWhence = *Res;
1003
0
  }
1004
1005
  // Check for invalid address.
1006
0
  auto *NewOffset = MemInst->getPointer<__wasi_filesize_t *>(NewOffsetPtr);
1007
0
  if (unlikely(NewOffset == nullptr)) {
1008
0
    return __WASI_ERRNO_FAULT;
1009
0
  }
1010
1011
0
  const __wasi_fd_t WasiFd = Fd;
1012
0
  const __wasi_filedelta_t WasiOffset = Offset;
1013
1014
0
  if (auto Res = Env.fdSeek(WasiFd, WasiOffset, WasiWhence, *NewOffset);
1015
0
      unlikely(!Res)) {
1016
0
    return Res.error();
1017
0
  }
1018
0
  return __WASI_ERRNO_SUCCESS;
1019
0
}
1020
1021
0
Expect<uint32_t> WasiFdSync::body(const Runtime::CallingFrame &, int32_t Fd) {
1022
0
  const __wasi_fd_t WasiFd = Fd;
1023
1024
0
  if (auto Res = Env.fdSync(WasiFd); unlikely(!Res)) {
1025
0
    return Res.error();
1026
0
  }
1027
0
  return __WASI_ERRNO_SUCCESS;
1028
0
}
1029
1030
Expect<uint32_t> WasiFdTell::body(const Runtime::CallingFrame &Frame,
1031
0
                                  int32_t Fd, uint32_t /* Out */ OffsetPtr) {
1032
  // Check memory instance from module.
1033
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1034
0
  if (MemInst == nullptr) {
1035
0
    return __WASI_ERRNO_FAULT;
1036
0
  }
1037
1038
  // Check for invalid address.
1039
0
  __wasi_filesize_t *Offset =
1040
0
      MemInst->getPointer<__wasi_filesize_t *>(OffsetPtr);
1041
0
  if (unlikely(Offset == nullptr)) {
1042
0
    return __WASI_ERRNO_FAULT;
1043
0
  }
1044
1045
0
  const __wasi_fd_t WasiFd = Fd;
1046
1047
0
  if (auto Res = Env.fdTell(WasiFd, *Offset); unlikely(!Res)) {
1048
0
    return Res.error();
1049
0
  }
1050
0
  return __WASI_ERRNO_SUCCESS;
1051
0
}
1052
1053
Expect<uint32_t> WasiFdWrite::body(const Runtime::CallingFrame &Frame,
1054
                                   int32_t Fd, uint32_t IOVsPtr,
1055
                                   uint32_t IOVsLen,
1056
0
                                   uint32_t /* Out */ NWrittenPtr) {
1057
  // Check memory instance from module.
1058
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1059
0
  if (MemInst == nullptr) {
1060
0
    return __WASI_ERRNO_FAULT;
1061
0
  }
1062
1063
0
  const __wasi_size_t WasiIOVsLen = IOVsLen;
1064
0
  if (unlikely(WasiIOVsLen > WASI::kIOVMax)) {
1065
0
    return __WASI_ERRNO_INVAL;
1066
0
  }
1067
1068
  // Check for invalid address.
1069
0
  const auto IOVsArray =
1070
0
      MemInst->getSpan<__wasi_ciovec_t>(IOVsPtr, WasiIOVsLen);
1071
0
  if (unlikely(IOVsArray.size() != WasiIOVsLen)) {
1072
0
    return __WASI_ERRNO_FAULT;
1073
0
  }
1074
1075
  // Check for invalid address.
1076
0
  auto *const NWritten = MemInst->getPointer<__wasi_size_t *>(NWrittenPtr);
1077
0
  if (unlikely(NWritten == nullptr)) {
1078
0
    return __WASI_ERRNO_FAULT;
1079
0
  }
1080
1081
0
  __wasi_size_t TotalSize = 0;
1082
0
  StaticVector<Span<const uint8_t>, WASI::kIOVMax> WasiIOVs;
1083
1084
0
  for (auto &IOV : IOVsArray) {
1085
    // Capping total size.
1086
0
    const __wasi_size_t Space =
1087
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
1088
0
    const EndianValue<uint32_t> IOVBufLen = IOV.buf_len;
1089
0
    const __wasi_size_t BufLen =
1090
0
        unlikely(IOVBufLen.le() > Space) ? Space : IOVBufLen.le();
1091
0
    TotalSize += BufLen;
1092
1093
    // Check for invalid address.
1094
0
    const auto WriteArr =
1095
0
        MemInst->getSpan<const uint8_t>(EndianValue(IOV.buf).le(), BufLen);
1096
0
    if (unlikely(WriteArr.size() != BufLen)) {
1097
0
      return __WASI_ERRNO_FAULT;
1098
0
    }
1099
0
    WasiIOVs.emplace_back_unchecked(WriteArr);
1100
0
  }
1101
1102
0
  const __wasi_fd_t WasiFd = Fd;
1103
1104
0
  if (auto Res = Env.fdWrite(WasiFd, WasiIOVs, *NWritten); unlikely(!Res)) {
1105
0
    return Res.error();
1106
0
  }
1107
0
  return __WASI_ERRNO_SUCCESS;
1108
0
}
1109
1110
Expect<uint32_t>
1111
WasiPathCreateDirectory::body(const Runtime::CallingFrame &Frame, int32_t Fd,
1112
0
                              uint32_t PathPtr, uint32_t PathLen) {
1113
  // Check memory instance from module.
1114
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1115
0
  if (MemInst == nullptr) {
1116
0
    return __WASI_ERRNO_FAULT;
1117
0
  }
1118
1119
0
  const __wasi_size_t WasiPathLen = PathLen;
1120
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1121
0
  if (unlikely(Path.size() != WasiPathLen)) {
1122
0
    return __WASI_ERRNO_FAULT;
1123
0
  }
1124
1125
0
  const __wasi_fd_t WasiFd = Fd;
1126
1127
0
  if (auto Res = Env.pathCreateDirectory(WasiFd, Path); unlikely(!Res)) {
1128
0
    return Res.error();
1129
0
  }
1130
0
  return __WASI_ERRNO_SUCCESS;
1131
0
}
1132
1133
Expect<uint32_t> WasiPathFilestatGet::body(const Runtime::CallingFrame &Frame,
1134
                                           int32_t Fd, uint32_t Flags,
1135
                                           uint32_t PathPtr, uint32_t PathLen,
1136
0
                                           uint32_t /* Out */ FilestatPtr) {
1137
  // Check memory instance from module.
1138
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1139
0
  if (MemInst == nullptr) {
1140
0
    return __WASI_ERRNO_FAULT;
1141
0
  }
1142
1143
0
  __wasi_lookupflags_t WasiFlags;
1144
0
  if (auto Res = cast<__wasi_lookupflags_t>(Flags); unlikely(!Res)) {
1145
0
    return Res.error();
1146
0
  } else {
1147
0
    WasiFlags = *Res;
1148
0
  }
1149
1150
0
  auto *const Filestat = MemInst->getPointer<__wasi_filestat_t *>(FilestatPtr);
1151
0
  if (unlikely(Filestat == nullptr)) {
1152
0
    return __WASI_ERRNO_FAULT;
1153
0
  }
1154
1155
0
  const __wasi_size_t WasiPathLen = PathLen;
1156
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1157
0
  if (unlikely(Path.size() != WasiPathLen)) {
1158
0
    return __WASI_ERRNO_FAULT;
1159
0
  }
1160
1161
0
  const __wasi_fd_t WasiFd = Fd;
1162
1163
0
  if (auto Res = Env.pathFilestatGet(WasiFd, Path, WasiFlags, *Filestat);
1164
0
      unlikely(!Res)) {
1165
0
    return Res.error();
1166
0
  }
1167
0
  return __WASI_ERRNO_SUCCESS;
1168
0
}
1169
1170
Expect<uint32_t>
1171
WasiPathFilestatSetTimes::body(const Runtime::CallingFrame &Frame, int32_t Fd,
1172
                               uint32_t Flags, uint32_t PathPtr,
1173
                               uint32_t PathLen, uint64_t ATim, uint64_t MTim,
1174
0
                               uint32_t FstFlags) {
1175
  // Check memory instance from module.
1176
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1177
0
  if (MemInst == nullptr) {
1178
0
    return __WASI_ERRNO_FAULT;
1179
0
  }
1180
1181
0
  __wasi_lookupflags_t WasiFlags;
1182
0
  if (auto Res = cast<__wasi_lookupflags_t>(Flags); unlikely(!Res)) {
1183
0
    return Res.error();
1184
0
  } else {
1185
0
    WasiFlags = *Res;
1186
0
  }
1187
1188
0
  __wasi_fstflags_t WasiFstFlags;
1189
0
  if (auto Res = cast<__wasi_fstflags_t>(FstFlags); unlikely(!Res)) {
1190
0
    return Res.error();
1191
0
  } else {
1192
0
    WasiFstFlags = *Res;
1193
0
  }
1194
1195
0
  const __wasi_size_t WasiPathLen = PathLen;
1196
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1197
0
  if (unlikely(Path.size() != WasiPathLen)) {
1198
0
    return __WASI_ERRNO_FAULT;
1199
0
  }
1200
1201
0
  const __wasi_fd_t WasiFd = Fd;
1202
0
  const __wasi_timestamp_t WasiATim = ATim;
1203
0
  const __wasi_timestamp_t WasiMTim = MTim;
1204
1205
0
  if (auto Res = Env.pathFilestatSetTimes(WasiFd, Path, WasiFlags, WasiATim,
1206
0
                                          WasiMTim, WasiFstFlags);
1207
0
      unlikely(!Res)) {
1208
0
    return Res.error();
1209
0
  }
1210
0
  return __WASI_ERRNO_SUCCESS;
1211
0
}
1212
1213
Expect<uint32_t> WasiPathLink::body(const Runtime::CallingFrame &Frame,
1214
                                    int32_t OldFd, uint32_t OldFlags,
1215
                                    uint32_t OldPathPtr, uint32_t OldPathLen,
1216
                                    int32_t NewFd, uint32_t NewPathPtr,
1217
0
                                    uint32_t NewPathLen) {
1218
  // Check memory instance from module.
1219
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1220
0
  if (MemInst == nullptr) {
1221
0
    return __WASI_ERRNO_FAULT;
1222
0
  }
1223
1224
0
  __wasi_lookupflags_t WasiOldFlags;
1225
0
  if (auto Res = cast<__wasi_lookupflags_t>(OldFlags); unlikely(!Res)) {
1226
0
    return Res.error();
1227
0
  } else {
1228
0
    WasiOldFlags = *Res;
1229
0
  }
1230
1231
0
  const __wasi_size_t WasiOldPathLen = OldPathLen;
1232
0
  const auto OldPath = MemInst->getStringView(OldPathPtr, WasiOldPathLen);
1233
0
  if (unlikely(OldPath.size() != WasiOldPathLen)) {
1234
0
    return __WASI_ERRNO_FAULT;
1235
0
  }
1236
1237
0
  const __wasi_size_t WasiNewPathLen = NewPathLen;
1238
0
  const auto NewPath = MemInst->getStringView(NewPathPtr, WasiNewPathLen);
1239
0
  if (unlikely(NewPath.size() != WasiNewPathLen)) {
1240
0
    return __WASI_ERRNO_FAULT;
1241
0
  }
1242
1243
0
  const __wasi_fd_t WasiOldFd = OldFd;
1244
0
  const __wasi_fd_t WasinewFd = NewFd;
1245
1246
0
  if (auto Res =
1247
0
          Env.pathLink(WasiOldFd, OldPath, WasinewFd, NewPath, WasiOldFlags);
1248
0
      unlikely(!Res)) {
1249
0
    return Res.error();
1250
0
  }
1251
0
  return __WASI_ERRNO_SUCCESS;
1252
0
}
1253
1254
Expect<uint32_t> WasiPathOpen::body(
1255
    const Runtime::CallingFrame &Frame, int32_t DirFd, uint32_t DirFlags,
1256
    uint32_t PathPtr, uint32_t PathLen, uint32_t OFlags, uint64_t FsRightsBase,
1257
0
    uint64_t FsRightsInheriting, uint32_t FsFlags, uint32_t /* Out */ FdPtr) {
1258
  // Check memory instance from module.
1259
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1260
0
  if (MemInst == nullptr) {
1261
0
    return __WASI_ERRNO_FAULT;
1262
0
  }
1263
1264
0
  __wasi_lookupflags_t WasiDirFlags;
1265
0
  if (auto Res = cast<__wasi_lookupflags_t>(DirFlags); unlikely(!Res)) {
1266
0
    return Res.error();
1267
0
  } else {
1268
0
    WasiDirFlags = *Res;
1269
0
  }
1270
1271
0
  __wasi_oflags_t WasiOFlags;
1272
0
  if (auto Res = cast<__wasi_oflags_t>(OFlags); unlikely(!Res)) {
1273
0
    return Res.error();
1274
0
  } else {
1275
0
    WasiOFlags = *Res;
1276
0
  }
1277
1278
0
  __wasi_rights_t WasiFsRightsBase;
1279
0
  if (auto Res = cast<__wasi_rights_t>(FsRightsBase); unlikely(!Res)) {
1280
0
    return Res.error();
1281
0
  } else {
1282
0
    WasiFsRightsBase = *Res;
1283
0
  }
1284
1285
0
  __wasi_rights_t WasiFsRightsInheriting;
1286
0
  if (auto Res = cast<__wasi_rights_t>(FsRightsInheriting); unlikely(!Res)) {
1287
0
    return Res.error();
1288
0
  } else {
1289
0
    WasiFsRightsInheriting = *Res;
1290
0
  }
1291
1292
0
  __wasi_fdflags_t WasiFsFlags;
1293
0
  if (auto Res = cast<__wasi_fdflags_t>(FsFlags); unlikely(!Res)) {
1294
0
    return Res.error();
1295
0
  } else {
1296
0
    WasiFsFlags = *Res;
1297
0
  }
1298
1299
0
  const __wasi_size_t WasiPathLen = PathLen;
1300
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1301
0
  if (unlikely(Path.size() != WasiPathLen)) {
1302
0
    return __WASI_ERRNO_FAULT;
1303
0
  }
1304
1305
0
  auto *const Fd = MemInst->getPointer<__wasi_fd_t *>(FdPtr);
1306
0
  if (unlikely(Fd == nullptr)) {
1307
0
    return __WASI_ERRNO_FAULT;
1308
0
  }
1309
1310
  // Open directory and read/write rights should fail with isdir
1311
0
  if ((WasiOFlags & __WASI_OFLAGS_DIRECTORY) &&
1312
0
      (WasiFsRightsBase & __WASI_RIGHTS_FD_READ) &&
1313
0
      (WasiFsRightsBase & __WASI_RIGHTS_FD_WRITE)) {
1314
0
    return __WASI_ERRNO_ISDIR;
1315
0
  }
1316
1317
0
  const __wasi_fd_t WasiDirFd = DirFd;
1318
1319
0
  if (auto Res =
1320
0
          Env.pathOpen(WasiDirFd, Path, WasiDirFlags, WasiOFlags,
1321
0
                       WasiFsRightsBase, WasiFsRightsInheriting, WasiFsFlags);
1322
0
      unlikely(!Res)) {
1323
0
    return Res.error();
1324
0
  } else {
1325
0
    *Fd = EndianValue(*Res).le();
1326
0
  }
1327
0
  return __WASI_ERRNO_SUCCESS;
1328
0
}
1329
1330
Expect<uint32_t> WasiPathReadLink::body(const Runtime::CallingFrame &Frame,
1331
                                        int32_t Fd, uint32_t PathPtr,
1332
                                        uint32_t PathLen, uint32_t BufPtr,
1333
                                        uint32_t BufLen,
1334
0
                                        uint32_t /* Out */ NReadPtr) {
1335
  // Check memory instance from module.
1336
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1337
0
  if (MemInst == nullptr) {
1338
0
    return __WASI_ERRNO_FAULT;
1339
0
  }
1340
1341
0
  const __wasi_size_t WasiPathLen = PathLen;
1342
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1343
0
  if (unlikely(Path.size() != WasiPathLen)) {
1344
0
    return __WASI_ERRNO_FAULT;
1345
0
  }
1346
1347
0
  const __wasi_size_t WasiBufLen = BufLen;
1348
1349
0
  const auto Buf = MemInst->getSpan<char>(BufPtr, WasiBufLen);
1350
0
  if (unlikely(Buf.size() != WasiBufLen)) {
1351
0
    return __WASI_ERRNO_FAULT;
1352
0
  }
1353
1354
0
  auto *const NRead = MemInst->getPointer<__wasi_size_t *>(NReadPtr);
1355
0
  if (unlikely(NRead == nullptr)) {
1356
0
    return __WASI_ERRNO_FAULT;
1357
0
  }
1358
1359
0
  const __wasi_fd_t WasiFd = Fd;
1360
1361
0
  if (auto Res = Env.pathReadlink(WasiFd, Path, Buf, *NRead); unlikely(!Res)) {
1362
0
    return Res.error();
1363
0
  }
1364
0
  return __WASI_ERRNO_SUCCESS;
1365
0
}
1366
1367
Expect<uint32_t>
1368
WasiPathRemoveDirectory::body(const Runtime::CallingFrame &Frame, int32_t Fd,
1369
0
                              uint32_t PathPtr, uint32_t PathLen) {
1370
  // Check memory instance from module.
1371
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1372
0
  if (MemInst == nullptr) {
1373
0
    return __WASI_ERRNO_FAULT;
1374
0
  }
1375
1376
0
  const __wasi_size_t WasiPathLen = PathLen;
1377
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1378
0
  if (unlikely(Path.size() != WasiPathLen)) {
1379
0
    return __WASI_ERRNO_FAULT;
1380
0
  }
1381
1382
0
  const __wasi_fd_t WasiFd = Fd;
1383
1384
0
  if (auto Res = Env.pathRemoveDirectory(WasiFd, Path); unlikely(!Res)) {
1385
0
    return Res.error();
1386
0
  }
1387
0
  return __WASI_ERRNO_SUCCESS;
1388
0
}
1389
1390
Expect<uint32_t> WasiPathRename::body(const Runtime::CallingFrame &Frame,
1391
                                      int32_t Fd, uint32_t OldPathPtr,
1392
                                      uint32_t OldPathLen, int32_t NewFd,
1393
                                      uint32_t NewPathPtr,
1394
0
                                      uint32_t NewPathLen) {
1395
  // Check memory instance from module.
1396
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1397
0
  if (MemInst == nullptr) {
1398
0
    return __WASI_ERRNO_FAULT;
1399
0
  }
1400
1401
0
  const __wasi_size_t WasiOldPathLen = OldPathLen;
1402
0
  const auto OldPath = MemInst->getStringView(OldPathPtr, WasiOldPathLen);
1403
0
  if (unlikely(OldPath.size() != WasiOldPathLen)) {
1404
0
    return __WASI_ERRNO_FAULT;
1405
0
  }
1406
1407
0
  const __wasi_size_t WasiNewPathLen = NewPathLen;
1408
0
  const auto NewPath = MemInst->getStringView(NewPathPtr, WasiNewPathLen);
1409
0
  if (unlikely(NewPath.size() != WasiNewPathLen)) {
1410
0
    return __WASI_ERRNO_FAULT;
1411
0
  }
1412
1413
0
  const __wasi_fd_t WasiFd = Fd;
1414
0
  const __wasi_fd_t WasiNewFd = NewFd;
1415
1416
0
  if (auto Res = Env.pathRename(WasiFd, OldPath, WasiNewFd, NewPath);
1417
0
      unlikely(!Res)) {
1418
0
    return Res.error();
1419
0
  }
1420
0
  return __WASI_ERRNO_SUCCESS;
1421
0
}
1422
1423
Expect<uint32_t> WasiPathSymlink::body(const Runtime::CallingFrame &Frame,
1424
                                       uint32_t OldPathPtr, uint32_t OldPathLen,
1425
                                       int32_t Fd, uint32_t NewPathPtr,
1426
0
                                       uint32_t NewPathLen) {
1427
  // Check memory instance from module.
1428
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1429
0
  if (MemInst == nullptr) {
1430
0
    return __WASI_ERRNO_FAULT;
1431
0
  }
1432
1433
0
  const __wasi_size_t WasiOldPathLen = OldPathLen;
1434
0
  const auto OldPath = MemInst->getStringView(OldPathPtr, WasiOldPathLen);
1435
0
  if (unlikely(OldPath.size() != WasiOldPathLen)) {
1436
0
    return __WASI_ERRNO_FAULT;
1437
0
  }
1438
1439
0
  const __wasi_size_t WasiNewPathLen = NewPathLen;
1440
0
  const auto NewPath = MemInst->getStringView(NewPathPtr, WasiNewPathLen);
1441
0
  if (unlikely(NewPath.size() != WasiNewPathLen)) {
1442
0
    return __WASI_ERRNO_FAULT;
1443
0
  }
1444
1445
0
  if (OldPath.empty() || NewPath.empty()) {
1446
0
    return __WASI_ERRNO_NOENT;
1447
0
  }
1448
1449
0
  const __wasi_fd_t WasiFd = Fd;
1450
1451
0
  if (auto Res = Env.pathSymlink(OldPath, WasiFd, NewPath); unlikely(!Res)) {
1452
0
    return Res.error();
1453
0
  }
1454
0
  return __WASI_ERRNO_SUCCESS;
1455
0
}
1456
1457
Expect<uint32_t> WasiPathUnlinkFile::body(const Runtime::CallingFrame &Frame,
1458
                                          int32_t Fd, uint32_t PathPtr,
1459
0
                                          uint32_t PathLen) {
1460
  // Check memory instance from module.
1461
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1462
0
  if (MemInst == nullptr) {
1463
0
    return __WASI_ERRNO_FAULT;
1464
0
  }
1465
1466
0
  const __wasi_size_t WasiPathLen = PathLen;
1467
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1468
0
  if (unlikely(Path.size() != WasiPathLen)) {
1469
0
    return __WASI_ERRNO_FAULT;
1470
0
  }
1471
1472
0
  const __wasi_fd_t WasiFd = Fd;
1473
1474
0
  if (auto Res = Env.pathUnlinkFile(WasiFd, Path); unlikely(!Res)) {
1475
0
    return Res.error();
1476
0
  }
1477
0
  return __WASI_ERRNO_SUCCESS;
1478
0
}
1479
template <WASI::TriggerType Trigger>
1480
Expect<uint32_t> WasiPollOneoff<Trigger>::body(
1481
    const Runtime::CallingFrame &Frame, uint32_t InPtr, uint32_t OutPtr,
1482
0
    uint32_t NSubscriptions, uint32_t /* Out */ NEventsPtr) {
1483
  // Check memory instance from module.
1484
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1485
0
  if (MemInst == nullptr) {
1486
0
    return __WASI_ERRNO_FAULT;
1487
0
  }
1488
1489
0
  const EndianValue<__wasi_size_t> WasiNSub = NSubscriptions;
1490
1491
0
  const auto Subs =
1492
0
      MemInst->getSpan<const __wasi_subscription_t>(InPtr, WasiNSub.raw());
1493
0
  if (unlikely(Subs.size() != WasiNSub.raw())) {
1494
0
    return __WASI_ERRNO_FAULT;
1495
0
  }
1496
1497
0
  const auto Events = MemInst->getSpan<__wasi_event_t>(OutPtr, WasiNSub.raw());
1498
0
  if (unlikely(Events.size() != WasiNSub.raw())) {
1499
0
    return __WASI_ERRNO_FAULT;
1500
0
  }
1501
1502
0
  auto *const NEvents = MemInst->getPointer<__wasi_size_t *>(NEventsPtr);
1503
0
  if (unlikely(NEvents == nullptr)) {
1504
0
    return __WASI_ERRNO_FAULT;
1505
0
  }
1506
1507
  // Validate contents
1508
0
  if (auto Poll = this->Env.acquirePoller(Events); unlikely(!Poll)) {
1509
0
    for (__wasi_size_t I = 0; I < WasiNSub.raw(); ++I) {
1510
0
      Events[I].userdata = Subs[I].userdata;
1511
0
      Events[I].error = Poll.error();
1512
0
      Events[I].type = Subs[I].u.tag;
1513
0
    }
1514
0
    *NEvents = WasiNSub.le();
1515
0
    return Poll.error();
1516
0
  } else {
1517
0
    auto &Poller = *Poll;
1518
0
    for (auto &Sub : Subs) {
1519
0
      const EndianValue<__wasi_userdata_t> WasiUserData = Sub.userdata;
1520
1521
0
      __wasi_eventtype_t Type;
1522
0
      if (auto Res = cast<__wasi_eventtype_t>(Sub.u.tag); unlikely(!Res)) {
1523
0
        Poller.error(WasiUserData.le(), Res.error(), Sub.u.tag);
1524
0
        continue;
1525
0
      } else {
1526
0
        Type = *Res;
1527
0
      }
1528
1529
0
      switch (Type) {
1530
0
      case __WASI_EVENTTYPE_CLOCK: {
1531
0
        __wasi_clockid_t WasiClockId;
1532
0
        if (auto Res =
1533
0
                cast<__wasi_clockid_t>(EndianValue(Sub.u.u.clock.id).le());
1534
0
            unlikely(!Res)) {
1535
0
          Poller.error(WasiUserData.le(), Res.error(), Type);
1536
0
          continue;
1537
0
        } else {
1538
0
          WasiClockId = *Res;
1539
0
        }
1540
1541
0
        __wasi_subclockflags_t WasiFlags;
1542
0
        if (auto Res = cast<__wasi_subclockflags_t>(
1543
0
                EndianValue(Sub.u.u.clock.flags).le());
1544
0
            unlikely(!Res)) {
1545
0
          Poller.error(WasiUserData.le(), Res.error(), Type);
1546
0
          continue;
1547
0
        } else {
1548
0
          WasiFlags = *Res;
1549
0
        }
1550
1551
0
        const EndianValue<__wasi_timestamp_t> WasiTimeout =
1552
0
            Sub.u.u.clock.timeout;
1553
0
        const EndianValue<__wasi_timestamp_t> WasiPrecision =
1554
0
            Sub.u.u.clock.precision;
1555
1556
0
        Poller.clock(WasiClockId, WasiTimeout.le(), WasiPrecision.le(),
1557
0
                     WasiFlags, WasiUserData.le());
1558
0
        continue;
1559
0
      }
1560
0
      case __WASI_EVENTTYPE_FD_READ: {
1561
0
        const EndianValue<__wasi_fd_t> WasiFd = Sub.u.u.fd_read.file_descriptor;
1562
0
        Poller.read(WasiFd.le(), Trigger, WasiUserData.le());
1563
0
        continue;
1564
0
      }
1565
0
      case __WASI_EVENTTYPE_FD_WRITE: {
1566
0
        const EndianValue<__wasi_fd_t> WasiFd =
1567
0
            Sub.u.u.fd_write.file_descriptor;
1568
0
        Poller.write(WasiFd.le(), Trigger, WasiUserData.le());
1569
0
        continue;
1570
0
      }
1571
0
      default:
1572
0
        assumingUnreachable();
1573
0
      }
1574
0
    }
1575
0
    Poller.wait();
1576
0
    *NEvents = EndianValue<__wasi_size_t>(Poller.result()).le();
1577
0
    Poller.reset();
1578
0
    this->Env.releasePoller(std::move(Poller));
1579
0
  }
1580
1581
0
  return __WASI_ERRNO_SUCCESS;
1582
0
}
Unexecuted instantiation: WasmEdge::Host::WasiPollOneoff<(WasmEdge::Host::WASI::TriggerType)0>::body(WasmEdge::Runtime::CallingFrame const&, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: WasmEdge::Host::WasiPollOneoff<(WasmEdge::Host::WASI::TriggerType)1>::body(WasmEdge::Runtime::CallingFrame const&, unsigned int, unsigned int, unsigned int, unsigned int)
1583
1584
template class WasiPollOneoff<WASI::TriggerType::Level>;
1585
template class WasiPollOneoff<WASI::TriggerType::Edge>;
1586
1587
Expect<void> WasiProcExit::body(const Runtime::CallingFrame &,
1588
0
                                uint32_t ExitCode) {
1589
0
  Env.procExit(ExitCode);
1590
0
  return Unexpect(ErrCode::Value::Terminated);
1591
0
}
1592
1593
Expect<uint32_t> WasiProcRaise::body(const Runtime::CallingFrame &,
1594
0
                                     uint32_t Signal) {
1595
0
  __wasi_signal_t WasiSignal;
1596
0
  if (auto Res = cast<__wasi_signal_t>(Signal); unlikely(!Res)) {
1597
0
    return Res.error();
1598
0
  } else {
1599
0
    WasiSignal = *Res;
1600
0
  }
1601
1602
0
  if (auto Res = Env.procRaise(WasiSignal); unlikely(!Res)) {
1603
0
    return Res.error();
1604
0
  }
1605
0
  return __WASI_ERRNO_SUCCESS;
1606
0
}
1607
1608
0
Expect<uint32_t> WasiSchedYield::body(const Runtime::CallingFrame &) {
1609
0
  if (auto Res = Env.schedYield(); unlikely(!Res)) {
1610
0
    return Res.error();
1611
0
  }
1612
0
  return __WASI_ERRNO_SUCCESS;
1613
0
}
1614
1615
Expect<uint32_t> WasiRandomGet::body(const Runtime::CallingFrame &Frame,
1616
0
                                     uint32_t BufPtr, uint32_t BufLen) {
1617
  // Check memory instance from module.
1618
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1619
0
  if (MemInst == nullptr) {
1620
0
    return __WASI_ERRNO_FAULT;
1621
0
  }
1622
1623
0
  const __wasi_size_t WasiBufLen = BufLen;
1624
1625
0
  const auto Buf = MemInst->getSpan<uint8_t>(BufPtr, WasiBufLen);
1626
0
  if (unlikely(Buf.size() != WasiBufLen)) {
1627
0
    return __WASI_ERRNO_FAULT;
1628
0
  }
1629
1630
0
  if (auto Res = Env.randomGet(Buf); unlikely(!Res)) {
1631
0
    return Res.error();
1632
0
  }
1633
0
  return __WASI_ERRNO_SUCCESS;
1634
0
}
1635
1636
Expect<uint32_t> WasiSockOpenV1::body(const Runtime::CallingFrame &Frame,
1637
                                      uint32_t AddressFamily, uint32_t SockType,
1638
0
                                      uint32_t /* Out */ RoFdPtr) {
1639
  // Check memory instance from module.
1640
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1641
0
  if (MemInst == nullptr) {
1642
0
    return __WASI_ERRNO_FAULT;
1643
0
  }
1644
1645
0
  __wasi_fd_t *const RoFd = MemInst->getPointer<__wasi_fd_t *>(RoFdPtr);
1646
0
  if (RoFd == nullptr) {
1647
0
    return __WASI_ERRNO_FAULT;
1648
0
  }
1649
1650
0
  __wasi_address_family_t WasiAddressFamily;
1651
0
  if (auto Res = cast<__wasi_address_family_t>(AddressFamily); unlikely(!Res)) {
1652
0
    return Res.error();
1653
0
  } else {
1654
0
    WasiAddressFamily = *Res;
1655
0
  }
1656
1657
0
  if (!AllowAFUNIX(Frame, WasiAddressFamily)) {
1658
0
    return __WASI_ERRNO_NOSYS;
1659
0
  }
1660
1661
0
  __wasi_sock_type_t WasiSockType;
1662
0
  if (auto Res = cast<__wasi_sock_type_t>(SockType); unlikely(!Res)) {
1663
0
    return Res.error();
1664
0
  } else {
1665
0
    WasiSockType = *Res;
1666
0
  }
1667
1668
0
  if (auto Res = Env.sockOpen(WasiAddressFamily, WasiSockType);
1669
0
      unlikely(!Res)) {
1670
0
    return Res.error();
1671
0
  } else {
1672
0
    *RoFd = EndianValue(*Res).le();
1673
0
  }
1674
1675
0
  return __WASI_ERRNO_SUCCESS;
1676
0
}
1677
1678
Expect<uint32_t> WasiSockBindV1::body(const Runtime::CallingFrame &Frame,
1679
                                      int32_t Fd, uint32_t AddressPtr,
1680
0
                                      uint32_t Port) {
1681
  // Check memory instance from module.
1682
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1683
0
  if (MemInst == nullptr) {
1684
0
    return __WASI_ERRNO_FAULT;
1685
0
  }
1686
0
  __wasi_address_t *InnerAddress =
1687
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
1688
0
  if (InnerAddress == nullptr) {
1689
0
    return __WASI_ERRNO_FAULT;
1690
0
  }
1691
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
1692
0
  const auto Address = MemInst->getSpan<const uint8_t>(
1693
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
1694
0
  if (Address.size() != InnerAddressBufLen) {
1695
0
    return __WASI_ERRNO_FAULT;
1696
0
  }
1697
1698
0
  __wasi_address_family_t WasiAddressFamily;
1699
0
  switch (Address.size()) {
1700
0
  case 4:
1701
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET4;
1702
0
    break;
1703
0
  case 16:
1704
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET6;
1705
0
    break;
1706
0
  default:
1707
0
    return __WASI_ERRNO_INVAL;
1708
0
  }
1709
1710
0
  const __wasi_fd_t WasiFd = Fd;
1711
1712
0
  if (auto Res = Env.sockBind(WasiFd, WasiAddressFamily, Address,
1713
0
                              static_cast<uint16_t>(Port));
1714
0
      unlikely(!Res)) {
1715
0
    return Res.error();
1716
0
  }
1717
0
  return __WASI_ERRNO_SUCCESS;
1718
0
}
1719
1720
Expect<uint32_t> WasiSockListenV1::body(const Runtime::CallingFrame &,
1721
0
                                        int32_t Fd, int32_t Backlog) {
1722
0
  const __wasi_fd_t WasiFd = Fd;
1723
0
  if (auto Res = Env.sockListen(WasiFd, Backlog); unlikely(!Res)) {
1724
0
    return Res.error();
1725
0
  }
1726
0
  return __WASI_ERRNO_SUCCESS;
1727
0
}
1728
1729
Expect<uint32_t> WasiSockAcceptV1::body(const Runtime::CallingFrame &Frame,
1730
                                        int32_t Fd,
1731
0
                                        uint32_t /* Out */ RoFdPtr) {
1732
  // Check memory instance from module.
1733
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1734
0
  if (MemInst == nullptr) {
1735
0
    return __WASI_ERRNO_FAULT;
1736
0
  }
1737
0
  __wasi_fd_t *const RoFd = MemInst->getPointer<__wasi_fd_t *>(RoFdPtr);
1738
0
  if (RoFd == nullptr) {
1739
0
    return __WASI_ERRNO_FAULT;
1740
0
  }
1741
0
  const __wasi_fd_t WasiFd = Fd;
1742
0
  const __wasi_fdflags_t WasiFdFlags = static_cast<__wasi_fdflags_t>(0);
1743
0
  if (auto Res = Env.sockAccept(WasiFd, WasiFdFlags); unlikely(!Res)) {
1744
0
    return Res.error();
1745
0
  } else {
1746
0
    *RoFd = EndianValue(*Res).le();
1747
0
  }
1748
1749
0
  return __WASI_ERRNO_SUCCESS;
1750
0
}
1751
1752
Expect<uint32_t> WasiSockAcceptV2::body(const Runtime::CallingFrame &Frame,
1753
                                        int32_t Fd, uint32_t FsFlags,
1754
0
                                        uint32_t /* Out */ RoFdPtr) {
1755
  // Check memory instance from module.
1756
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1757
0
  if (MemInst == nullptr) {
1758
0
    return __WASI_ERRNO_FAULT;
1759
0
  }
1760
0
  __wasi_fd_t *const RoFd = MemInst->getPointer<__wasi_fd_t *>(RoFdPtr);
1761
0
  if (RoFd == nullptr) {
1762
0
    return __WASI_ERRNO_FAULT;
1763
0
  }
1764
0
  const __wasi_fd_t WasiFd = Fd;
1765
1766
0
  __wasi_fdflags_t WasiFdFlags;
1767
0
  if (auto Res = cast<__wasi_fdflags_t>(FsFlags); unlikely(!Res)) {
1768
0
    return Res.error();
1769
0
  } else {
1770
0
    WasiFdFlags = *Res;
1771
0
  }
1772
1773
0
  if (auto Res = Env.sockAccept(WasiFd, WasiFdFlags); unlikely(!Res)) {
1774
0
    return Res.error();
1775
0
  } else {
1776
0
    *RoFd = EndianValue(*Res).le();
1777
0
  }
1778
1779
0
  return __WASI_ERRNO_SUCCESS;
1780
0
}
1781
1782
Expect<uint32_t> WasiSockConnectV1::body(const Runtime::CallingFrame &Frame,
1783
                                         int32_t Fd, uint32_t AddressPtr,
1784
0
                                         uint32_t Port) {
1785
  // Check memory instance from module.
1786
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1787
0
  if (MemInst == nullptr) {
1788
0
    return __WASI_ERRNO_FAULT;
1789
0
  }
1790
0
  __wasi_address_t *InnerAddress =
1791
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
1792
0
  if (InnerAddress == nullptr) {
1793
0
    return __WASI_ERRNO_FAULT;
1794
0
  }
1795
1796
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
1797
0
  const auto Address = MemInst->getSpan<uint8_t>(
1798
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
1799
0
  if (Address.size() != InnerAddressBufLen) {
1800
0
    return __WASI_ERRNO_FAULT;
1801
0
  }
1802
1803
0
  __wasi_address_family_t WasiAddressFamily;
1804
0
  switch (Address.size()) {
1805
0
  case 4:
1806
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET4;
1807
0
    break;
1808
0
  case 16:
1809
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET6;
1810
0
    break;
1811
0
  default:
1812
0
    return __WASI_ERRNO_INVAL;
1813
0
  }
1814
1815
0
  const __wasi_fd_t WasiFd = Fd;
1816
0
  if (auto Res = Env.sockConnect(WasiFd, WasiAddressFamily, Address,
1817
0
                                 static_cast<uint16_t>(Port));
1818
0
      unlikely(!Res)) {
1819
0
    return Res.error();
1820
0
  }
1821
1822
0
  return __WASI_ERRNO_SUCCESS;
1823
0
}
1824
1825
Expect<uint32_t> WasiSockRecvV1::body(const Runtime::CallingFrame &Frame,
1826
                                      int32_t Fd, uint32_t RiDataPtr,
1827
                                      uint32_t RiDataLen, uint32_t RiFlags,
1828
                                      uint32_t /* Out */ RoDataLenPtr,
1829
0
                                      uint32_t /* Out */ RoFlagsPtr) {
1830
  // Check memory instance from module.
1831
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1832
0
  if (MemInst == nullptr) {
1833
0
    return __WASI_ERRNO_FAULT;
1834
0
  }
1835
1836
0
  __wasi_riflags_t WasiRiFlags;
1837
0
  if (auto Res = cast<__wasi_riflags_t>(RiFlags); unlikely(!Res)) {
1838
0
    return Res.error();
1839
0
  } else {
1840
0
    WasiRiFlags = EndianValue(*Res).le();
1841
0
  }
1842
1843
0
  const __wasi_size_t WasiRiDataLen = RiDataLen;
1844
0
  if (unlikely(WasiRiDataLen > WASI::kIOVMax)) {
1845
0
    return __WASI_ERRNO_INVAL;
1846
0
  }
1847
1848
  // Check for invalid address.
1849
0
  const auto RiDataArray =
1850
0
      MemInst->getSpan<__wasi_iovec_t>(RiDataPtr, WasiRiDataLen);
1851
0
  if (unlikely(RiDataArray.size() != WasiRiDataLen)) {
1852
0
    return __WASI_ERRNO_FAULT;
1853
0
  }
1854
1855
0
  auto *const RoDataLen = MemInst->getPointer<__wasi_size_t *>(RoDataLenPtr);
1856
0
  if (unlikely(RoDataLen == nullptr)) {
1857
0
    return __WASI_ERRNO_FAULT;
1858
0
  }
1859
1860
0
  auto *const RoFlags = MemInst->getPointer<__wasi_roflags_t *>(RoFlagsPtr);
1861
0
  if (unlikely(RoFlags == nullptr)) {
1862
0
    return __WASI_ERRNO_FAULT;
1863
0
  }
1864
0
  __wasi_size_t TotalSize = 0;
1865
0
  StaticVector<Span<uint8_t>, WASI::kIOVMax> WasiRiData;
1866
1867
0
  for (auto &RiData : RiDataArray) {
1868
    // Capping total size.
1869
0
    const __wasi_size_t Space =
1870
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
1871
0
    const uint32_t RiDataBufLen = EndianValue(RiData.buf_len).le();
1872
0
    const __wasi_size_t BufLen =
1873
0
        unlikely(RiDataBufLen > Space) ? Space : RiDataBufLen;
1874
0
    TotalSize += BufLen;
1875
1876
    // Check for invalid address.
1877
0
    const auto RiDataArr =
1878
0
        MemInst->getSpan<uint8_t>(EndianValue(RiData.buf).le(), BufLen);
1879
    // Check for invalid address.
1880
0
    if (unlikely(RiDataArr.size() != BufLen)) {
1881
0
      return __WASI_ERRNO_FAULT;
1882
0
    }
1883
0
    WasiRiData.emplace_back_unchecked(RiDataArr);
1884
0
  }
1885
1886
0
  const __wasi_fd_t WasiFd = Fd;
1887
1888
0
  if (auto Res =
1889
0
          Env.sockRecv(WasiFd, WasiRiData, WasiRiFlags, *RoDataLen, *RoFlags);
1890
0
      unlikely(!Res)) {
1891
0
    return Res.error();
1892
0
  }
1893
1894
0
  return __WASI_ERRNO_SUCCESS;
1895
0
}
1896
1897
Expect<uint32_t> WasiSockRecvFromV1::body(const Runtime::CallingFrame &Frame,
1898
                                          int32_t Fd, uint32_t RiDataPtr,
1899
                                          uint32_t RiDataLen,
1900
                                          uint32_t AddressPtr, uint32_t RiFlags,
1901
                                          uint32_t /* Out */ RoDataLenPtr,
1902
0
                                          uint32_t /* Out */ RoFlagsPtr) {
1903
  // Check memory instance from module.
1904
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1905
0
  if (MemInst == nullptr) {
1906
0
    return __WASI_ERRNO_FAULT;
1907
0
  }
1908
1909
0
  __wasi_address_t *InnerAddress =
1910
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
1911
0
  if (InnerAddress == nullptr) {
1912
0
    return __WASI_ERRNO_FAULT;
1913
0
  }
1914
1915
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
1916
0
  const auto Address = MemInst->getSpan<uint8_t>(
1917
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
1918
0
  if (Address.size() != InnerAddressBufLen) {
1919
0
    return __WASI_ERRNO_FAULT;
1920
0
  }
1921
1922
0
  __wasi_riflags_t WasiRiFlags;
1923
0
  if (auto Res = cast<__wasi_riflags_t>(RiFlags); unlikely(!Res)) {
1924
0
    return Res.error();
1925
0
  } else {
1926
0
    WasiRiFlags = *Res;
1927
0
  }
1928
1929
0
  const __wasi_size_t WasiRiDataLen = RiDataLen;
1930
0
  if (unlikely(WasiRiDataLen > WASI::kIOVMax)) {
1931
0
    return __WASI_ERRNO_INVAL;
1932
0
  }
1933
1934
0
  const auto RiDataArray =
1935
0
      MemInst->getSpan<__wasi_iovec_t>(RiDataPtr, WasiRiDataLen);
1936
0
  if (unlikely(RiDataArray.size() != WasiRiDataLen)) {
1937
0
    return __WASI_ERRNO_FAULT;
1938
0
  }
1939
1940
0
  auto *const RoDataLen = MemInst->getPointer<__wasi_size_t *>(RoDataLenPtr);
1941
0
  if (unlikely(RoDataLen == nullptr)) {
1942
0
    return __WASI_ERRNO_FAULT;
1943
0
  }
1944
1945
0
  auto *const RoFlags = MemInst->getPointer<__wasi_roflags_t *>(RoFlagsPtr);
1946
0
  if (unlikely(RoFlags == nullptr)) {
1947
0
    return __WASI_ERRNO_FAULT;
1948
0
  }
1949
0
  __wasi_size_t TotalSize = 0;
1950
0
  StaticVector<Span<uint8_t>, WASI::kIOVMax> WasiRiData;
1951
0
  for (auto &RiData : RiDataArray) {
1952
    // Capping total size.
1953
0
    const __wasi_size_t Space =
1954
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
1955
0
    const uint32_t RiDataBufLen = EndianValue(RiData.buf_len).le();
1956
0
    const __wasi_size_t BufLen =
1957
0
        unlikely(RiDataBufLen > Space) ? Space : RiDataBufLen;
1958
1959
    // Check for invalid address.
1960
0
    const auto RiDataArr =
1961
0
        MemInst->getSpan<uint8_t>(EndianValue(RiData.buf).le(), BufLen);
1962
    // Check for invalid address.
1963
0
    if (unlikely(RiDataArr.size() != BufLen)) {
1964
0
      return __WASI_ERRNO_FAULT;
1965
0
    }
1966
0
    WasiRiData.emplace_back_unchecked(RiDataArr);
1967
0
  }
1968
1969
0
  const __wasi_fd_t WasiFd = Fd;
1970
1971
0
  if (auto Res = Env.sockRecvFrom(WasiFd, WasiRiData, WasiRiFlags, nullptr,
1972
0
                                  Address, nullptr, *RoDataLen, *RoFlags);
1973
0
      unlikely(!Res)) {
1974
0
    return Res.error();
1975
0
  }
1976
1977
0
  return __WASI_ERRNO_SUCCESS;
1978
0
}
1979
1980
Expect<uint32_t> WasiSockSendV1::body(const Runtime::CallingFrame &Frame,
1981
                                      int32_t Fd, uint32_t SiDataPtr,
1982
                                      uint32_t SiDataLen, uint32_t SiFlags,
1983
0
                                      uint32_t /* Out */ SoDataLenPtr) {
1984
  // Check memory instance from module.
1985
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1986
0
  if (MemInst == nullptr) {
1987
0
    return __WASI_ERRNO_FAULT;
1988
0
  }
1989
1990
0
  __wasi_siflags_t WasiSiFlags;
1991
0
  if (auto Res = cast<__wasi_siflags_t>(SiFlags); unlikely(!Res)) {
1992
0
    return Res.error();
1993
0
  } else {
1994
0
    WasiSiFlags = *Res;
1995
0
  }
1996
1997
0
  const __wasi_size_t WasiSiDataLen = SiDataLen;
1998
0
  if (unlikely(WasiSiDataLen > WASI::kIOVMax)) {
1999
0
    return __WASI_ERRNO_INVAL;
2000
0
  }
2001
2002
  // Check for invalid address.
2003
0
  const auto SiDataArray =
2004
0
      MemInst->getSpan<__wasi_ciovec_t>(SiDataPtr, WasiSiDataLen);
2005
0
  if (unlikely(SiDataArray.size() != WasiSiDataLen)) {
2006
0
    return __WASI_ERRNO_FAULT;
2007
0
  }
2008
2009
0
  auto *const SoDataLen = MemInst->getPointer<__wasi_size_t *>(SoDataLenPtr);
2010
0
  if (unlikely(SoDataLen == nullptr)) {
2011
0
    return __WASI_ERRNO_FAULT;
2012
0
  }
2013
2014
0
  __wasi_size_t TotalSize = 0;
2015
0
  StaticVector<Span<const uint8_t>, WASI::kIOVMax> WasiSiData;
2016
2017
0
  for (auto &SiData : SiDataArray) {
2018
    // Capping total size.
2019
0
    const __wasi_size_t Space =
2020
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
2021
0
    const uint32_t SiDataBufLen = EndianValue(SiData.buf_len).le();
2022
0
    const __wasi_size_t BufLen =
2023
0
        unlikely(SiDataBufLen > Space) ? Space : SiDataBufLen;
2024
0
    TotalSize += BufLen;
2025
2026
    // Check for invalid address.
2027
0
    const auto SiDataArr =
2028
0
        MemInst->getSpan<uint8_t>(EndianValue(SiData.buf).le(), BufLen);
2029
0
    if (unlikely(SiDataArr.size() != BufLen)) {
2030
0
      return __WASI_ERRNO_FAULT;
2031
0
    }
2032
0
    WasiSiData.emplace_back_unchecked(SiDataArr);
2033
0
  }
2034
2035
0
  const __wasi_fd_t WasiFd = Fd;
2036
2037
0
  if (auto Res = Env.sockSend(WasiFd, WasiSiData, WasiSiFlags, *SoDataLen);
2038
0
      unlikely(!Res)) {
2039
0
    return Res.error();
2040
0
  }
2041
0
  return __WASI_ERRNO_SUCCESS;
2042
0
}
2043
2044
Expect<uint32_t> WasiSockSendToV1::body(const Runtime::CallingFrame &Frame,
2045
                                        int32_t Fd, uint32_t SiDataPtr,
2046
                                        uint32_t SiDataLen, uint32_t AddressPtr,
2047
                                        int32_t Port, uint32_t SiFlags,
2048
0
                                        uint32_t /* Out */ SoDataLenPtr) {
2049
  // Check memory instance from module.
2050
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2051
0
  if (MemInst == nullptr) {
2052
0
    return __WASI_ERRNO_FAULT;
2053
0
  }
2054
2055
0
  __wasi_address_t *InnerAddress =
2056
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
2057
0
  if (InnerAddress == nullptr) {
2058
0
    return __WASI_ERRNO_FAULT;
2059
0
  }
2060
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
2061
0
  const auto Address = MemInst->getSpan<uint8_t>(
2062
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
2063
0
  if (Address.size() != InnerAddressBufLen) {
2064
0
    return __WASI_ERRNO_FAULT;
2065
0
  }
2066
2067
0
  __wasi_address_family_t WasiAddressFamily;
2068
0
  switch (Address.size()) {
2069
0
  case 4:
2070
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET4;
2071
0
    break;
2072
0
  case 16:
2073
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET6;
2074
0
    break;
2075
0
  default:
2076
0
    return __WASI_ERRNO_INVAL;
2077
0
  }
2078
2079
0
  __wasi_siflags_t WasiSiFlags;
2080
0
  if (auto Res = cast<__wasi_siflags_t>(SiFlags); unlikely(!Res)) {
2081
0
    return Res.error();
2082
0
  } else {
2083
0
    WasiSiFlags = *Res;
2084
0
  }
2085
2086
0
  const __wasi_size_t WasiSiDataLen = SiDataLen;
2087
0
  if (unlikely(WasiSiDataLen > WASI::kIOVMax)) {
2088
0
    return __WASI_ERRNO_INVAL;
2089
0
  }
2090
2091
  // Check for invalid address.
2092
0
  const auto SiDataArray =
2093
0
      MemInst->getSpan<__wasi_ciovec_t>(SiDataPtr, WasiSiDataLen);
2094
0
  if (unlikely(SiDataArray.size() != WasiSiDataLen)) {
2095
0
    return __WASI_ERRNO_FAULT;
2096
0
  }
2097
2098
0
  auto *const SoDataLen = MemInst->getPointer<__wasi_size_t *>(SoDataLenPtr);
2099
0
  if (unlikely(SoDataLen == nullptr)) {
2100
0
    return __WASI_ERRNO_FAULT;
2101
0
  }
2102
2103
0
  __wasi_size_t TotalSize = 0;
2104
0
  StaticVector<Span<const uint8_t>, WASI::kIOVMax> WasiSiData;
2105
2106
0
  for (auto &SiData : SiDataArray) {
2107
    // Capping total size.
2108
0
    const __wasi_size_t Space =
2109
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
2110
0
    const uint32_t SiDataBufLen = EndianValue(SiData.buf_len).le();
2111
0
    const __wasi_size_t BufLen =
2112
0
        unlikely(SiDataBufLen > Space) ? Space : SiDataBufLen;
2113
0
    TotalSize += BufLen;
2114
2115
    // Check for invalid address.
2116
0
    const auto SiDataArr =
2117
0
        MemInst->getSpan<uint8_t>(EndianValue(SiData.buf).le(), BufLen);
2118
0
    if (unlikely(SiDataArr.size() != BufLen)) {
2119
0
      return __WASI_ERRNO_FAULT;
2120
0
    }
2121
0
    WasiSiData.emplace_back_unchecked(SiDataArr);
2122
0
  }
2123
2124
0
  const __wasi_fd_t WasiFd = Fd;
2125
2126
0
  if (auto Res =
2127
0
          Env.sockSendTo(WasiFd, WasiSiData, WasiSiFlags, WasiAddressFamily,
2128
0
                         Address, static_cast<uint16_t>(Port), *SoDataLen);
2129
0
      unlikely(!Res)) {
2130
0
    return Res.error();
2131
0
  }
2132
2133
0
  return __WASI_ERRNO_SUCCESS;
2134
0
}
2135
2136
Expect<uint32_t> WasiSockShutdown::body(const Runtime::CallingFrame &,
2137
0
                                        int32_t Fd, uint32_t SdFlags) {
2138
0
  __wasi_sdflags_t WasiSdFlags;
2139
0
  if (auto Res = cast<__wasi_sdflags_t>(SdFlags); unlikely(!Res)) {
2140
0
    return Res.error();
2141
0
  } else {
2142
0
    WasiSdFlags = *Res;
2143
0
  }
2144
2145
0
  const __wasi_fd_t WasiFd = Fd;
2146
2147
0
  if (auto Res = Env.sockShutdown(WasiFd, WasiSdFlags); unlikely(!Res)) {
2148
0
    return Res.error();
2149
0
  }
2150
0
  return __WASI_ERRNO_SUCCESS;
2151
0
}
2152
2153
Expect<uint32_t> WasiSockSetOpt::body(const Runtime::CallingFrame &Frame,
2154
                                      int32_t Fd, uint32_t SockOptLevel,
2155
                                      uint32_t SockOptName, uint32_t FlagPtr,
2156
0
                                      uint32_t FlagSize) {
2157
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2158
0
  if (MemInst == nullptr) {
2159
0
    return __WASI_ERRNO_FAULT;
2160
0
  }
2161
2162
0
  __wasi_sock_opt_level_t WasiSockOptLevel;
2163
0
  if (auto Res = cast<__wasi_sock_opt_level_t>(SockOptLevel); unlikely(!Res)) {
2164
0
    return Res.error();
2165
0
  } else {
2166
0
    WasiSockOptLevel = *Res;
2167
0
  }
2168
2169
0
  __wasi_sock_opt_so_t WasiSockOptName;
2170
0
  if (auto Res = cast<__wasi_sock_opt_so_t>(SockOptName); unlikely(!Res)) {
2171
0
    return Res.error();
2172
0
  } else {
2173
0
    WasiSockOptName = *Res;
2174
0
  }
2175
2176
0
  const auto Flag = MemInst->getSpan<uint8_t>(FlagPtr, FlagSize);
2177
0
  if (Flag.size() != FlagSize) {
2178
0
    return __WASI_ERRNO_FAULT;
2179
0
  }
2180
2181
0
  const __wasi_fd_t WasiFd = Fd;
2182
2183
0
  if (auto Res =
2184
0
          Env.sockSetOpt(WasiFd, WasiSockOptLevel, WasiSockOptName, Flag);
2185
0
      unlikely(!Res)) {
2186
0
    return Res.error();
2187
0
  }
2188
2189
0
  return __WASI_ERRNO_SUCCESS;
2190
0
}
2191
2192
Expect<uint32_t> WasiSockGetAddrinfo::body(
2193
    const Runtime::CallingFrame &Frame, uint32_t NodePtr, uint32_t NodeLen,
2194
    uint32_t ServicePtr, uint32_t ServiceLen, uint32_t HintsPtr,
2195
0
    uint32_t ResPtr, uint32_t MaxResLength, uint32_t ResLengthPtr) {
2196
  // Check memory instance from module.
2197
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2198
0
  if (MemInst == nullptr) {
2199
0
    return __WASI_ERRNO_FAULT;
2200
0
  }
2201
2202
0
  const auto Node = MemInst->getStringView(NodePtr, NodeLen);
2203
0
  if (Node.size() != NodeLen) {
2204
0
    return __WASI_ERRNO_FAULT;
2205
0
  }
2206
2207
0
  const auto Service = MemInst->getStringView(ServicePtr, ServiceLen);
2208
0
  if (Service.size() != ServiceLen) {
2209
0
    return __WASI_ERRNO_FAULT;
2210
0
  }
2211
2212
0
  auto *Hint = MemInst->getPointer<const __wasi_addrinfo_t *>(HintsPtr);
2213
0
  if (Hint == nullptr) {
2214
0
    return __WASI_ERRNO_FAULT;
2215
0
  }
2216
2217
0
  auto *const ResBuf = MemInst->getPointer<const uint8_t_ptr *>(ResPtr);
2218
0
  if (ResBuf == nullptr) {
2219
0
    return __WASI_ERRNO_FAULT;
2220
0
  }
2221
2222
0
  auto *const ResLength = MemInst->getPointer<__wasi_size_t *>(ResLengthPtr);
2223
0
  if (ResLength == nullptr) {
2224
0
    return __WASI_ERRNO_FAULT;
2225
0
  }
2226
2227
  // service and node can not be empty at the same time
2228
0
  if (Service.empty() && Node.empty()) {
2229
0
    return __WASI_ERRNO_AINONAME;
2230
0
  }
2231
2232
0
  if (MaxResLength < 1) {
2233
0
    return __WASI_ERRNO_AIMEMORY;
2234
0
  }
2235
2236
0
  if (Hint->ai_flags &
2237
0
      ~(__WASI_AIFLAGS_AI_PASSIVE | __WASI_AIFLAGS_AI_CANONNAME |
2238
0
        __WASI_AIFLAGS_AI_NUMERICHOST | __WASI_AIFLAGS_AI_NUMERICSERV |
2239
0
        __WASI_AIFLAGS_AI_ADDRCONFIG | __WASI_AIFLAGS_AI_V4MAPPED |
2240
0
        __WASI_AIFLAGS_AI_ALL)) {
2241
0
    return __WASI_ERRNO_AIBADFLAG;
2242
0
  }
2243
0
  if (Hint->ai_flags & __WASI_AIFLAGS_AI_CANONNAME && Node.empty()) {
2244
0
    return __WASI_ERRNO_AIBADFLAG;
2245
0
  }
2246
0
  switch (Hint->ai_family) {
2247
0
  case __WASI_ADDRESS_FAMILY_UNSPEC:
2248
0
  case __WASI_ADDRESS_FAMILY_INET4:
2249
0
  case __WASI_ADDRESS_FAMILY_INET6:
2250
0
    break;
2251
0
  default:
2252
0
    return __WASI_ERRNO_AIFAMILY;
2253
0
  }
2254
0
  switch (Hint->ai_protocol) {
2255
0
  case __WASI_PROTOCOL_IPPROTO_IP:
2256
0
  case __WASI_PROTOCOL_IPPROTO_TCP:
2257
0
  case __WASI_PROTOCOL_IPPROTO_UDP:
2258
0
    break;
2259
0
  default:
2260
0
    return __WASI_ERRNO_NOSYS;
2261
0
  }
2262
0
  switch (Hint->ai_socktype) {
2263
0
  case __WASI_SOCK_TYPE_SOCK_ANY:
2264
0
  case __WASI_SOCK_TYPE_SOCK_DGRAM:
2265
0
  case __WASI_SOCK_TYPE_SOCK_STREAM:
2266
0
    break;
2267
0
  default:
2268
0
    return __WASI_ERRNO_NOSYS;
2269
0
  }
2270
2271
0
  auto Body = [&]() -> WASI::WasiExpect<void> {
2272
0
    auto initWasiAddrinfoArray =
2273
0
        [&MemInst](uint8_t_ptr Base, uint32_t Length,
2274
0
                   Span<__wasi_addrinfo_t *> WasiAddrinfoArray) noexcept
2275
0
        -> WASI::WasiExpect<void> {
2276
0
      for (uint32_t Item = 0; Item < Length; Item++) {
2277
0
        auto *const TmpAddrinfo =
2278
0
            MemInst->getPointer<__wasi_addrinfo_t *>(Base);
2279
0
        if (TmpAddrinfo == nullptr) {
2280
0
          return WASI::WasiUnexpect(__WASI_ERRNO_FAULT);
2281
0
        }
2282
0
        WasiAddrinfoArray[Item] = TmpAddrinfo;
2283
0
        Base = TmpAddrinfo->ai_next;
2284
0
      }
2285
0
      return {};
2286
0
    };
2287
2288
0
    auto initAiAddrArray =
2289
0
        [&MemInst](Span<__wasi_addrinfo_t *> WasiAddrinfoArray,
2290
0
                   Span<__wasi_sockaddr_t *> WasiSockAddrArray) noexcept
2291
0
        -> WASI::WasiExpect<void> {
2292
0
      for (uint32_t Item = 0; Item < WasiAddrinfoArray.size(); Item++) {
2293
0
        auto *const Addr = MemInst->getPointer<__wasi_sockaddr_t *>(
2294
0
            WasiAddrinfoArray[Item]->ai_addr);
2295
0
        if (Addr == nullptr) {
2296
0
          return WASI::WasiUnexpect(__WASI_ERRNO_FAULT);
2297
0
        }
2298
0
        WasiSockAddrArray[Item] = Addr;
2299
0
      }
2300
0
      return {};
2301
0
    };
2302
2303
0
    auto initAiAddrSaDataArray =
2304
0
        [&MemInst](Span<__wasi_sockaddr_t *> WasiSockAddrArray,
2305
0
                   Span<char *> AiSockAddrSaDataArray) noexcept
2306
0
        -> WASI::WasiExpect<void> {
2307
0
      for (uint32_t Item = 0; Item < WasiSockAddrArray.size(); Item++) {
2308
0
        const auto WasiSockAddr =
2309
0
            MemInst->getSpan<char>(WasiSockAddrArray[Item]->sa_data,
2310
0
                                   WasiSockAddrArray[Item]->sa_data_len);
2311
0
        if (WasiSockAddr.size() != WasiSockAddrArray[Item]->sa_data_len) {
2312
0
          return WASI::WasiUnexpect(__WASI_ERRNO_FAULT);
2313
0
        }
2314
0
        AiSockAddrSaDataArray[Item] = WasiSockAddr.data();
2315
0
      }
2316
0
      return {};
2317
0
    };
2318
2319
0
    auto initAiCanonnameArray =
2320
0
        [&MemInst](Span<__wasi_addrinfo_t *> WasiAddrinfoArray,
2321
0
                   Span<char *> WasiAddrinfoCanonnameArray) noexcept
2322
0
        -> WASI::WasiExpect<void> {
2323
0
      for (uint32_t Item = 0; Item < WasiAddrinfoArray.size(); Item++) {
2324
0
        const auto CanonName =
2325
0
            MemInst->getSpan<char>(WasiAddrinfoArray[Item]->ai_canonname,
2326
0
                                   WasiAddrinfoArray[Item]->ai_canonname_len);
2327
0
        if (CanonName.size() != WasiAddrinfoArray[Item]->ai_canonname_len) {
2328
0
          return WASI::WasiUnexpect(__WASI_ERRNO_FAULT);
2329
0
        }
2330
0
        WasiAddrinfoCanonnameArray[Item] = CanonName.data();
2331
0
      }
2332
0
      return {};
2333
0
    };
2334
2335
0
    std::vector<__wasi_addrinfo_t *> WasiAddrinfoArray(MaxResLength, nullptr);
2336
0
    std::vector<__wasi_sockaddr_t *> WasiSockAddrArray(MaxResLength, nullptr);
2337
0
    std::vector<char *> AiAddrSaDataArray(MaxResLength, nullptr);
2338
0
    std::vector<char *> AiCanonnameArray(MaxResLength, nullptr);
2339
2340
0
    EXPECTED_TRY(
2341
0
        initWasiAddrinfoArray(*ResBuf, MaxResLength, WasiAddrinfoArray));
2342
0
    EXPECTED_TRY(initAiAddrArray(WasiAddrinfoArray, WasiSockAddrArray));
2343
0
    EXPECTED_TRY(initAiAddrSaDataArray(WasiSockAddrArray, AiAddrSaDataArray));
2344
0
    EXPECTED_TRY(initAiCanonnameArray(WasiAddrinfoArray, AiCanonnameArray));
2345
2346
0
    EXPECTED_TRY(Env.getAddrInfo(
2347
0
        Node, Service, *Hint, MaxResLength, WasiAddrinfoArray,
2348
0
        WasiSockAddrArray, AiAddrSaDataArray, AiCanonnameArray, *ResLength));
2349
0
    return {};
2350
0
  };
2351
0
  if (auto Res = Body(); unlikely(!Res)) {
2352
0
    return Res.error();
2353
0
  }
2354
2355
0
  return __WASI_ERRNO_SUCCESS;
2356
0
}
2357
2358
Expect<uint32_t>
2359
WasiSockGetLocalAddrV1::body(const Runtime::CallingFrame &Frame, int32_t Fd,
2360
                             uint32_t AddressPtr, uint32_t AddressTypePtr,
2361
0
                             uint32_t PortPtr) {
2362
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2363
0
  if (MemInst == nullptr) {
2364
0
    return __WASI_ERRNO_FAULT;
2365
0
  }
2366
0
  __wasi_address_t *InnerAddress =
2367
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
2368
0
  if (InnerAddress == nullptr) {
2369
0
    return __WASI_ERRNO_FAULT;
2370
0
  }
2371
2372
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
2373
0
  const auto Address = MemInst->getSpan<uint8_t>(
2374
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
2375
0
  if (Address.size() != InnerAddressBufLen) {
2376
0
    return __WASI_ERRNO_FAULT;
2377
0
  }
2378
2379
0
  switch (Address.size()) {
2380
0
  case 4:
2381
0
    break;
2382
0
  case 16:
2383
0
    break;
2384
0
  default:
2385
0
    return __WASI_ERRNO_INVAL;
2386
0
  }
2387
2388
0
  uint32_t *const RoAddressType =
2389
0
      MemInst->getPointer<uint32_t *>(AddressTypePtr);
2390
0
  if (RoAddressType == nullptr) {
2391
0
    return __WASI_ERRNO_FAULT;
2392
0
  }
2393
0
  __wasi_address_family_t AddressType;
2394
2395
0
  uint32_t *const RoPort = MemInst->getPointer<uint32_t *>(PortPtr);
2396
0
  if (RoPort == nullptr) {
2397
0
    return __WASI_ERRNO_FAULT;
2398
0
  }
2399
2400
0
  uint16_t Port;
2401
0
  const __wasi_fd_t WasiFd = Fd;
2402
2403
0
  if (auto Res = Env.sockGetLocalAddr(WasiFd, &AddressType, Address, &Port);
2404
0
      unlikely(!Res)) {
2405
0
    return Res.error();
2406
0
  }
2407
0
  *RoPort = EndianValue(Port).le();
2408
  // XXX: This is a workaround
2409
  // The correct one should be `*RoAddressType = AddressType;`
2410
  // However, due to this bugfix will break the existing applications.
2411
  // So we changed back to the old way.
2412
0
  switch (AddressType) {
2413
0
  case __WASI_ADDRESS_FAMILY_INET4:
2414
0
    *RoAddressType = EndianValue(4U).le();
2415
0
    break;
2416
0
  case __WASI_ADDRESS_FAMILY_INET6:
2417
0
    *RoAddressType = EndianValue(6U).le();
2418
0
    break;
2419
0
  default:
2420
0
    assumingUnreachable();
2421
0
  }
2422
0
  return __WASI_ERRNO_SUCCESS;
2423
0
}
2424
2425
Expect<uint32_t> WasiSockGetPeerAddrV1::body(const Runtime::CallingFrame &Frame,
2426
                                             int32_t Fd, uint32_t AddressPtr,
2427
                                             uint32_t AddressTypePtr,
2428
0
                                             uint32_t PortPtr) {
2429
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2430
0
  if (MemInst == nullptr) {
2431
0
    return __WASI_ERRNO_FAULT;
2432
0
  }
2433
0
  __wasi_address_t *InnerAddress =
2434
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
2435
0
  if (InnerAddress == nullptr) {
2436
0
    return __WASI_ERRNO_FAULT;
2437
0
  }
2438
2439
0
  const auto Address =
2440
0
      MemInst->getSpan<uint8_t>(EndianValue(InnerAddress->buf).le(),
2441
0
                                EndianValue(InnerAddress->buf_len).le());
2442
0
  if (Address.size() != EndianValue(InnerAddress->buf_len).le()) {
2443
0
    return __WASI_ERRNO_FAULT;
2444
0
  }
2445
2446
0
  switch (Address.size()) {
2447
0
  case 4:
2448
0
    break;
2449
0
  case 16:
2450
0
    break;
2451
0
  default:
2452
0
    return __WASI_ERRNO_INVAL;
2453
0
  }
2454
2455
0
  uint32_t *const RoAddressType =
2456
0
      MemInst->getPointer<uint32_t *>(AddressTypePtr);
2457
0
  if (RoAddressType == nullptr) {
2458
0
    return __WASI_ERRNO_FAULT;
2459
0
  }
2460
0
  __wasi_address_family_t AddressType;
2461
2462
0
  uint32_t *const RoPort = MemInst->getPointer<uint32_t *>(PortPtr);
2463
0
  if (RoPort == nullptr) {
2464
0
    return __WASI_ERRNO_FAULT;
2465
0
  }
2466
0
  EndianValue<uint16_t> Port;
2467
2468
0
  const __wasi_fd_t WasiFd = Fd;
2469
2470
0
  if (auto Res =
2471
0
          Env.sockGetPeerAddr(WasiFd, &AddressType, Address, &Port.raw());
2472
0
      unlikely(!Res)) {
2473
0
    return Res.error();
2474
0
  }
2475
0
  *RoPort = Port.le();
2476
  // XXX: This is a workaround
2477
  // The correct one should be `*RoAddressType = AddressType;`
2478
  // However, due to this bugfix will break the existing applications.
2479
  // So we changed back to the old way.
2480
0
  switch (AddressType) {
2481
0
  case __WASI_ADDRESS_FAMILY_INET4:
2482
0
    *RoAddressType = EndianValue(4U).le();
2483
0
    break;
2484
0
  case __WASI_ADDRESS_FAMILY_INET6:
2485
0
    *RoAddressType = EndianValue(6U).le();
2486
0
    break;
2487
0
  default:
2488
0
    assumingUnreachable();
2489
0
  }
2490
0
  return __WASI_ERRNO_SUCCESS;
2491
0
}
2492
2493
Expect<uint32_t> WasiSockOpenV2::body(const Runtime::CallingFrame &Frame,
2494
                                      uint32_t AddressFamily, uint32_t SockType,
2495
0
                                      uint32_t /* Out */ RoFdPtr) {
2496
  // Check memory instance from module.
2497
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2498
0
  if (MemInst == nullptr) {
2499
0
    return __WASI_ERRNO_FAULT;
2500
0
  }
2501
2502
0
  __wasi_fd_t *const RoFd = MemInst->getPointer<__wasi_fd_t *>(RoFdPtr);
2503
0
  if (RoFd == nullptr) {
2504
0
    return __WASI_ERRNO_FAULT;
2505
0
  }
2506
2507
0
  __wasi_address_family_t WasiAddressFamily;
2508
0
  if (auto Res = cast<__wasi_address_family_t>(AddressFamily); unlikely(!Res)) {
2509
0
    return Res.error();
2510
0
  } else {
2511
0
    WasiAddressFamily = *Res;
2512
0
  }
2513
2514
0
  if (!AllowAFUNIX(Frame, WasiAddressFamily)) {
2515
0
    return __WASI_ERRNO_NOSYS;
2516
0
  }
2517
2518
0
  __wasi_sock_type_t WasiSockType;
2519
0
  if (auto Res = cast<__wasi_sock_type_t>(SockType); unlikely(!Res)) {
2520
0
    return Res.error();
2521
0
  } else {
2522
0
    WasiSockType = *Res;
2523
0
  }
2524
2525
0
  if (auto Res = Env.sockOpen(WasiAddressFamily, WasiSockType);
2526
0
      unlikely(!Res)) {
2527
0
    return Res.error();
2528
0
  } else {
2529
0
    *RoFd = EndianValue(*Res).le();
2530
0
  }
2531
2532
0
  return __WASI_ERRNO_SUCCESS;
2533
0
}
2534
2535
Expect<uint32_t> WasiSockBindV2::body(const Runtime::CallingFrame &Frame,
2536
                                      int32_t Fd, uint32_t AddressPtr,
2537
0
                                      uint32_t Port) {
2538
  // Check memory instance from module.
2539
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2540
0
  if (MemInst == nullptr) {
2541
0
    return __WASI_ERRNO_FAULT;
2542
0
  }
2543
0
  auto *const InnerAddress =
2544
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
2545
0
  if (InnerAddress == nullptr) {
2546
0
    return __WASI_ERRNO_FAULT;
2547
0
  }
2548
2549
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
2550
0
  auto Address = MemInst->getSpan<const uint8_t>(
2551
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
2552
0
  if (Address.size() != InnerAddressBufLen) {
2553
0
    return __WASI_ERRNO_FAULT;
2554
0
  }
2555
2556
0
  __wasi_address_family_t WasiAddressFamily;
2557
0
  switch (Address.size()) {
2558
0
  case 4:
2559
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET4;
2560
0
    break;
2561
0
  case 16:
2562
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET6;
2563
0
    break;
2564
0
  case 128: {
2565
0
    auto &Storage =
2566
0
        *reinterpret_cast<const WASI::WasiAddrStorage *>(Address.data());
2567
0
    WasiAddressFamily = Storage.getAddressFamily();
2568
0
    Address = Storage.getAddress();
2569
0
    break;
2570
0
  }
2571
0
  default:
2572
0
    return __WASI_ERRNO_INVAL;
2573
0
  }
2574
2575
0
  const __wasi_fd_t WasiFd = Fd;
2576
0
  if (auto Res = Env.sockBind(WasiFd, WasiAddressFamily, Address,
2577
0
                              static_cast<uint16_t>(Port));
2578
0
      unlikely(!Res)) {
2579
0
    return Res.error();
2580
0
  }
2581
0
  return __WASI_ERRNO_SUCCESS;
2582
0
}
2583
2584
Expect<uint32_t> WasiSockListenV2::body(const Runtime::CallingFrame &,
2585
0
                                        int32_t Fd, int32_t Backlog) {
2586
0
  const __wasi_fd_t WasiFd = Fd;
2587
0
  if (auto Res = Env.sockListen(WasiFd, Backlog); unlikely(!Res)) {
2588
0
    return Res.error();
2589
0
  }
2590
0
  return __WASI_ERRNO_SUCCESS;
2591
0
}
2592
2593
Expect<uint32_t> WasiSockConnectV2::body(const Runtime::CallingFrame &Frame,
2594
                                         int32_t Fd, uint32_t AddressPtr,
2595
0
                                         uint32_t Port) {
2596
  // Check memory instance from module.
2597
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2598
0
  if (MemInst == nullptr) {
2599
0
    return __WASI_ERRNO_FAULT;
2600
0
  }
2601
0
  __wasi_address_t *InnerAddress =
2602
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
2603
0
  if (InnerAddress == nullptr) {
2604
0
    return __WASI_ERRNO_FAULT;
2605
0
  }
2606
2607
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
2608
0
  auto Address = MemInst->getSpan<const uint8_t>(
2609
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
2610
0
  if (Address.size() != InnerAddressBufLen) {
2611
0
    return __WASI_ERRNO_FAULT;
2612
0
  }
2613
2614
0
  __wasi_address_family_t WasiAddressFamily;
2615
0
  switch (Address.size()) {
2616
0
  case 4:
2617
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET4;
2618
0
    break;
2619
0
  case 16:
2620
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET6;
2621
0
    break;
2622
0
  case 128: {
2623
0
    auto &Storage =
2624
0
        *reinterpret_cast<const WASI::WasiAddrStorage *>(Address.data());
2625
0
    WasiAddressFamily = Storage.getAddressFamily();
2626
0
    Address = Storage.getAddress();
2627
0
    break;
2628
0
  }
2629
0
  default:
2630
0
    return __WASI_ERRNO_INVAL;
2631
0
  }
2632
2633
0
  const __wasi_fd_t WasiFd = Fd;
2634
0
  if (auto Res = Env.sockConnect(WasiFd, WasiAddressFamily, Address,
2635
0
                                 static_cast<uint16_t>(Port));
2636
0
      unlikely(!Res)) {
2637
0
    return Res.error();
2638
0
  }
2639
2640
0
  return __WASI_ERRNO_SUCCESS;
2641
0
}
2642
2643
Expect<uint32_t> WasiSockRecvV2::body(const Runtime::CallingFrame &Frame,
2644
                                      int32_t Fd, uint32_t RiDataPtr,
2645
                                      uint32_t RiDataLen, uint32_t RiFlags,
2646
                                      uint32_t /* Out */ RoDataLenPtr,
2647
0
                                      uint32_t /* Out */ RoFlagsPtr) {
2648
  // Check memory instance from module.
2649
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2650
0
  if (MemInst == nullptr) {
2651
0
    return __WASI_ERRNO_FAULT;
2652
0
  }
2653
2654
0
  __wasi_riflags_t WasiRiFlags;
2655
0
  if (auto Res = cast<__wasi_riflags_t>(RiFlags); unlikely(!Res)) {
2656
0
    return Res.error();
2657
0
  } else {
2658
0
    WasiRiFlags = EndianValue(*Res).le();
2659
0
  }
2660
2661
0
  const __wasi_size_t WasiRiDataLen = RiDataLen;
2662
0
  if (unlikely(WasiRiDataLen > WASI::kIOVMax)) {
2663
0
    return __WASI_ERRNO_INVAL;
2664
0
  }
2665
2666
  // Check for invalid address.
2667
0
  const auto RiDataArray =
2668
0
      MemInst->getSpan<__wasi_iovec_t>(RiDataPtr, WasiRiDataLen);
2669
0
  if (unlikely(RiDataArray.size() != WasiRiDataLen)) {
2670
0
    return __WASI_ERRNO_FAULT;
2671
0
  }
2672
2673
0
  auto *const RoDataLen = MemInst->getPointer<__wasi_size_t *>(RoDataLenPtr);
2674
0
  if (unlikely(RoDataLen == nullptr)) {
2675
0
    return __WASI_ERRNO_FAULT;
2676
0
  }
2677
2678
0
  auto *const RoFlags = MemInst->getPointer<__wasi_roflags_t *>(RoFlagsPtr);
2679
0
  if (unlikely(RoFlags == nullptr)) {
2680
0
    return __WASI_ERRNO_FAULT;
2681
0
  }
2682
0
  __wasi_size_t TotalSize = 0;
2683
0
  StaticVector<Span<uint8_t>, WASI::kIOVMax> WasiRiData;
2684
2685
0
  for (auto &RiData : RiDataArray) {
2686
    // Capping total size.
2687
0
    const __wasi_size_t Space =
2688
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
2689
0
    const uint32_t RiDataBufLen = EndianValue(RiData.buf_len).le();
2690
0
    const __wasi_size_t BufLen =
2691
0
        unlikely(RiDataBufLen > Space) ? Space : RiDataBufLen;
2692
0
    TotalSize += BufLen;
2693
2694
    // Check for invalid address.
2695
0
    const auto RiDataArr =
2696
0
        MemInst->getSpan<uint8_t>(EndianValue(RiData.buf).le(), BufLen);
2697
0
    if (unlikely(RiDataArr.size() != BufLen)) {
2698
0
      return __WASI_ERRNO_FAULT;
2699
0
    }
2700
0
    WasiRiData.emplace_back_unchecked(RiDataArr);
2701
0
  }
2702
2703
0
  const __wasi_fd_t WasiFd = Fd;
2704
2705
0
  if (auto Res =
2706
0
          Env.sockRecv(WasiFd, WasiRiData, WasiRiFlags, *RoDataLen, *RoFlags);
2707
0
      unlikely(!Res)) {
2708
0
    return Res.error();
2709
0
  }
2710
0
  return __WASI_ERRNO_SUCCESS;
2711
0
}
2712
2713
Expect<uint32_t> WasiSockRecvFromV2::body(const Runtime::CallingFrame &Frame,
2714
                                          int32_t Fd, uint32_t RiDataPtr,
2715
                                          uint32_t RiDataLen,
2716
                                          uint32_t AddressPtr, uint32_t RiFlags,
2717
                                          uint32_t /* Out */ PortPtr,
2718
                                          uint32_t /* Out */ RoDataLenPtr,
2719
0
                                          uint32_t /* Out */ RoFlagsPtr) {
2720
  // Check memory instance from module.
2721
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2722
0
  if (MemInst == nullptr) {
2723
0
    return __WASI_ERRNO_FAULT;
2724
0
  }
2725
2726
0
  __wasi_address_t *InnerAddress =
2727
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
2728
0
  if (InnerAddress == nullptr) {
2729
0
    return __WASI_ERRNO_FAULT;
2730
0
  }
2731
2732
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
2733
0
  auto Address = MemInst->getSpan<uint8_t>(EndianValue(InnerAddress->buf).le(),
2734
0
                                           InnerAddressBufLen);
2735
0
  if (Address.size() != InnerAddressBufLen) {
2736
0
    return __WASI_ERRNO_FAULT;
2737
0
  }
2738
2739
0
  __wasi_address_family_t WasiAddressFamily;
2740
0
  WASI::WasiAddrStorage *Storage = nullptr;
2741
0
  switch (Address.size()) {
2742
0
  case 4:
2743
0
  case 16:
2744
0
    break;
2745
0
  case 128:
2746
0
    Storage = reinterpret_cast<WASI::WasiAddrStorage *>(Address.data());
2747
0
    Address = Storage->getAddress();
2748
0
    break;
2749
0
  default:
2750
0
    return __WASI_ERRNO_INVAL;
2751
0
  }
2752
2753
0
  __wasi_riflags_t WasiRiFlags;
2754
0
  if (auto Res = cast<__wasi_riflags_t>(RiFlags); unlikely(!Res)) {
2755
0
    return Res.error();
2756
0
  } else {
2757
0
    WasiRiFlags = *Res;
2758
0
  }
2759
2760
0
  const __wasi_size_t WasiRiDataLen = RiDataLen;
2761
0
  if (unlikely(WasiRiDataLen > WASI::kIOVMax)) {
2762
0
    return __WASI_ERRNO_INVAL;
2763
0
  }
2764
2765
  // Check for invalid address.
2766
0
  uint16_t *const RoPort = MemInst->getPointer<uint16_t *>(PortPtr);
2767
0
  if (RoPort == nullptr) {
2768
0
    return __WASI_ERRNO_FAULT;
2769
0
  }
2770
2771
0
  const auto RiDataArray =
2772
0
      MemInst->getSpan<__wasi_iovec_t>(RiDataPtr, WasiRiDataLen);
2773
0
  if (unlikely(RiDataArray.size() != WasiRiDataLen)) {
2774
0
    return __WASI_ERRNO_FAULT;
2775
0
  }
2776
2777
0
  auto *const RoDataLen = MemInst->getPointer<__wasi_size_t *>(RoDataLenPtr);
2778
0
  if (unlikely(RoDataLen == nullptr)) {
2779
0
    return __WASI_ERRNO_FAULT;
2780
0
  }
2781
2782
0
  auto *const RoFlags = MemInst->getPointer<__wasi_roflags_t *>(RoFlagsPtr);
2783
0
  if (unlikely(RoFlags == nullptr)) {
2784
0
    return __WASI_ERRNO_FAULT;
2785
0
  }
2786
0
  __wasi_size_t TotalSize = 0;
2787
0
  StaticVector<Span<uint8_t>, WASI::kIOVMax> WasiRiData;
2788
2789
0
  for (auto &RiData : RiDataArray) {
2790
    // Capping total size.
2791
0
    const __wasi_size_t Space =
2792
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
2793
0
    const uint32_t RiDataBufLen = EndianValue(RiData.buf_len).le();
2794
0
    const __wasi_size_t BufLen =
2795
0
        unlikely(RiDataBufLen > Space) ? Space : RiDataBufLen;
2796
0
    TotalSize += BufLen;
2797
2798
    // Check for invalid address.
2799
0
    const auto RiDataArr =
2800
0
        MemInst->getSpan<uint8_t>(EndianValue(RiData.buf).le(), BufLen);
2801
0
    if (unlikely(RiDataArr.size() != BufLen)) {
2802
0
      return __WASI_ERRNO_FAULT;
2803
0
    }
2804
0
    WasiRiData.emplace_back_unchecked(RiDataArr);
2805
0
  }
2806
2807
0
  const __wasi_fd_t WasiFd = Fd;
2808
2809
0
  if (auto Res =
2810
0
          Env.sockRecvFrom(WasiFd, WasiRiData, WasiRiFlags, &WasiAddressFamily,
2811
0
                           Address, RoPort, *RoDataLen, *RoFlags);
2812
0
      unlikely(!Res)) {
2813
0
    return Res.error();
2814
0
  }
2815
0
  if (Storage) {
2816
0
    Storage->setAddressFamily(WasiAddressFamily);
2817
0
  }
2818
0
  return __WASI_ERRNO_SUCCESS;
2819
0
}
2820
2821
Expect<uint32_t> WasiSockSendV2::body(const Runtime::CallingFrame &Frame,
2822
                                      int32_t Fd, uint32_t SiDataPtr,
2823
                                      uint32_t SiDataLen, uint32_t SiFlags,
2824
0
                                      uint32_t /* Out */ SoDataLenPtr) {
2825
  // Check memory instance from module.
2826
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2827
0
  if (MemInst == nullptr) {
2828
0
    return __WASI_ERRNO_FAULT;
2829
0
  }
2830
2831
0
  __wasi_siflags_t WasiSiFlags;
2832
0
  if (auto Res = cast<__wasi_siflags_t>(SiFlags); unlikely(!Res)) {
2833
0
    return Res.error();
2834
0
  } else {
2835
0
    WasiSiFlags = *Res;
2836
0
  }
2837
2838
0
  const __wasi_size_t WasiSiDataLen = SiDataLen;
2839
0
  if (unlikely(WasiSiDataLen > WASI::kIOVMax)) {
2840
0
    return __WASI_ERRNO_INVAL;
2841
0
  }
2842
2843
  // Check for invalid address.
2844
0
  const auto SiDataArray =
2845
0
      MemInst->getSpan<__wasi_ciovec_t>(SiDataPtr, WasiSiDataLen);
2846
0
  if (unlikely(SiDataArray.size() != WasiSiDataLen)) {
2847
0
    return __WASI_ERRNO_FAULT;
2848
0
  }
2849
2850
0
  auto *const SoDataLen = MemInst->getPointer<__wasi_size_t *>(SoDataLenPtr);
2851
0
  if (unlikely(SoDataLen == nullptr)) {
2852
0
    return __WASI_ERRNO_FAULT;
2853
0
  }
2854
2855
0
  __wasi_size_t TotalSize = 0;
2856
0
  StaticVector<Span<const uint8_t>, WASI::kIOVMax> WasiSiData;
2857
2858
0
  for (auto &SiData : SiDataArray) {
2859
    // Capping total size.
2860
0
    const __wasi_size_t Space =
2861
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
2862
0
    const uint32_t SiDataBufLen = EndianValue(SiData.buf_len).le();
2863
0
    const __wasi_size_t BufLen =
2864
0
        unlikely(SiDataBufLen > Space) ? Space : SiDataBufLen;
2865
0
    TotalSize += BufLen;
2866
2867
    // Check for invalid address.
2868
0
    const auto SiDataArr =
2869
0
        MemInst->getSpan<uint8_t>(EndianValue(SiData.buf).le(), BufLen);
2870
0
    if (unlikely(SiDataArr.size() != BufLen)) {
2871
0
      return __WASI_ERRNO_FAULT;
2872
0
    }
2873
0
    WasiSiData.emplace_back_unchecked(SiDataArr);
2874
0
  }
2875
2876
0
  const __wasi_fd_t WasiFd = Fd;
2877
2878
0
  if (auto Res = Env.sockSend(WasiFd, WasiSiData, WasiSiFlags, *SoDataLen);
2879
0
      unlikely(!Res)) {
2880
0
    return Res.error();
2881
0
  }
2882
0
  return __WASI_ERRNO_SUCCESS;
2883
0
}
2884
2885
Expect<uint32_t> WasiSockSendToV2::body(const Runtime::CallingFrame &Frame,
2886
                                        int32_t Fd, uint32_t SiDataPtr,
2887
                                        uint32_t SiDataLen, uint32_t AddressPtr,
2888
                                        int32_t Port, uint32_t SiFlags,
2889
0
                                        uint32_t /* Out */ SoDataLenPtr) {
2890
  // Check memory instance from module.
2891
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2892
0
  if (MemInst == nullptr) {
2893
0
    return __WASI_ERRNO_FAULT;
2894
0
  }
2895
2896
0
  __wasi_address_t *InnerAddress =
2897
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
2898
0
  if (InnerAddress == nullptr) {
2899
0
    return __WASI_ERRNO_FAULT;
2900
0
  }
2901
2902
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
2903
0
  auto Address = MemInst->getSpan<const uint8_t>(
2904
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
2905
0
  if (Address.size() != InnerAddressBufLen) {
2906
0
    return __WASI_ERRNO_FAULT;
2907
0
  }
2908
2909
0
  __wasi_address_family_t WasiAddressFamily;
2910
0
  switch (Address.size()) {
2911
0
  case 4:
2912
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET4;
2913
0
    break;
2914
0
  case 16:
2915
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET6;
2916
0
    break;
2917
0
  case 128: {
2918
0
    auto &Storage =
2919
0
        *reinterpret_cast<const WASI::WasiAddrStorage *>(Address.data());
2920
0
    WasiAddressFamily = Storage.getAddressFamily();
2921
0
    Address = Storage.getAddress();
2922
0
    break;
2923
0
  }
2924
0
  default:
2925
0
    return __WASI_ERRNO_INVAL;
2926
0
  }
2927
2928
0
  __wasi_siflags_t WasiSiFlags;
2929
0
  if (auto Res = cast<__wasi_siflags_t>(SiFlags); unlikely(!Res)) {
2930
0
    return Res.error();
2931
0
  } else {
2932
0
    WasiSiFlags = *Res;
2933
0
  }
2934
2935
0
  const __wasi_size_t WasiSiDataLen = SiDataLen;
2936
0
  if (unlikely(WasiSiDataLen > WASI::kIOVMax)) {
2937
0
    return __WASI_ERRNO_INVAL;
2938
0
  }
2939
2940
  // Check for invalid address.
2941
0
  const auto SiDataArray =
2942
0
      MemInst->getSpan<__wasi_ciovec_t>(SiDataPtr, WasiSiDataLen);
2943
0
  if (unlikely(SiDataArray.size() != WasiSiDataLen)) {
2944
0
    return __WASI_ERRNO_FAULT;
2945
0
  }
2946
2947
0
  auto *const SoDataLen = MemInst->getPointer<__wasi_size_t *>(SoDataLenPtr);
2948
0
  if (unlikely(SoDataLen == nullptr)) {
2949
0
    return __WASI_ERRNO_FAULT;
2950
0
  }
2951
2952
0
  __wasi_size_t TotalSize = 0;
2953
0
  StaticVector<Span<const uint8_t>, WASI::kIOVMax> WasiSiData;
2954
2955
0
  for (auto &SiData : SiDataArray) {
2956
    // Capping total size.
2957
0
    const __wasi_size_t Space =
2958
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
2959
0
    const uint32_t SiDataBufLen = EndianValue(SiData.buf_len).le();
2960
0
    const __wasi_size_t BufLen =
2961
0
        unlikely(SiDataBufLen > Space) ? Space : SiDataBufLen;
2962
0
    TotalSize += BufLen;
2963
2964
    // Check for invalid address.
2965
0
    const auto SiDataArr =
2966
0
        MemInst->getSpan<uint8_t>(EndianValue(SiData.buf).le(), BufLen);
2967
0
    if (unlikely(SiDataArr.size() != BufLen)) {
2968
0
      return __WASI_ERRNO_FAULT;
2969
0
    }
2970
0
    WasiSiData.emplace_back_unchecked(SiDataArr);
2971
0
  }
2972
2973
0
  const __wasi_fd_t WasiFd = Fd;
2974
0
  if (auto Res =
2975
0
          Env.sockSendTo(WasiFd, WasiSiData, WasiSiFlags, WasiAddressFamily,
2976
0
                         Address, static_cast<uint16_t>(Port), *SoDataLen);
2977
0
      unlikely(!Res)) {
2978
0
    return Res.error();
2979
0
  }
2980
2981
0
  return __WASI_ERRNO_SUCCESS;
2982
0
}
2983
2984
Expect<uint32_t> WasiSockGetOpt::body(const Runtime::CallingFrame &Frame,
2985
                                      int32_t Fd, uint32_t SockOptLevel,
2986
                                      uint32_t SockOptName, uint32_t FlagPtr,
2987
0
                                      uint32_t FlagSizePtr) {
2988
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2989
0
  if (MemInst == nullptr) {
2990
0
    return __WASI_ERRNO_FAULT;
2991
0
  }
2992
2993
0
  __wasi_sock_opt_level_t WasiSockOptLevel;
2994
0
  if (auto Res = cast<__wasi_sock_opt_level_t>(SockOptLevel); unlikely(!Res)) {
2995
0
    return Res.error();
2996
0
  } else {
2997
0
    WasiSockOptLevel = *Res;
2998
0
  }
2999
3000
0
  __wasi_sock_opt_so_t WasiSockOptName;
3001
0
  if (auto Res = cast<__wasi_sock_opt_so_t>(SockOptName); unlikely(!Res)) {
3002
0
    return Res.error();
3003
0
  } else {
3004
0
    WasiSockOptName = *Res;
3005
0
  }
3006
3007
0
  auto *const SysFlagSizePtr = MemInst->getPointer<uint32_t *>(FlagSizePtr);
3008
0
  if (SysFlagSizePtr == nullptr) {
3009
0
    return __WASI_ERRNO_FAULT;
3010
0
  }
3011
3012
0
  auto Flag =
3013
0
      MemInst->getSpan<uint8_t>(FlagPtr, EndianValue(*SysFlagSizePtr).le());
3014
0
  if (Flag.size() != EndianValue(*SysFlagSizePtr).le()) {
3015
0
    return __WASI_ERRNO_FAULT;
3016
0
  }
3017
3018
0
  const __wasi_fd_t WasiFd = Fd;
3019
3020
0
  if (auto Res =
3021
0
          Env.sockGetOpt(WasiFd, WasiSockOptLevel, WasiSockOptName, Flag);
3022
0
      unlikely(!Res)) {
3023
0
    return Res.error();
3024
0
  }
3025
0
  *SysFlagSizePtr = EndianValue(static_cast<uint32_t>(Flag.size())).le();
3026
0
  return __WASI_ERRNO_SUCCESS;
3027
0
}
3028
3029
Expect<uint32_t>
3030
WasiSockGetLocalAddrV2::body(const Runtime::CallingFrame &Frame, int32_t Fd,
3031
0
                             uint32_t AddressPtr, uint32_t PortPtr) {
3032
0
  auto *MemInst = Frame.getMemoryByIndex(0);
3033
0
  if (MemInst == nullptr) {
3034
0
    return __WASI_ERRNO_FAULT;
3035
0
  }
3036
0
  __wasi_address_t *InnerAddress =
3037
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
3038
0
  if (InnerAddress == nullptr) {
3039
0
    return __WASI_ERRNO_FAULT;
3040
0
  }
3041
3042
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
3043
0
  auto Address = MemInst->getSpan<uint8_t>(EndianValue(InnerAddress->buf).le(),
3044
0
                                           InnerAddressBufLen);
3045
0
  if (Address.size() != InnerAddressBufLen) {
3046
0
    return __WASI_ERRNO_FAULT;
3047
0
  }
3048
3049
0
  uint32_t *const RoPort = MemInst->getPointer<uint32_t *>(PortPtr);
3050
0
  if (RoPort == nullptr) {
3051
0
    return __WASI_ERRNO_FAULT;
3052
0
  }
3053
3054
0
  if (Address.size() != 128) {
3055
0
    return __WASI_ERRNO_INVAL;
3056
0
  }
3057
3058
0
  const __wasi_fd_t WasiFd = Fd;
3059
0
  WASI::WasiAddrStorage &Storage =
3060
0
      *reinterpret_cast<WASI::WasiAddrStorage *>(Address.data());
3061
0
  Address = Storage.getAddress();
3062
0
  __wasi_address_family_t WasiAddressFamily;
3063
0
  uint16_t Port;
3064
3065
0
  if (auto Res =
3066
0
          Env.sockGetLocalAddr(WasiFd, &WasiAddressFamily, Address, &Port);
3067
0
      unlikely(!Res)) {
3068
0
    return Res.error();
3069
0
  }
3070
3071
0
  Storage.setAddressFamily(WasiAddressFamily);
3072
0
  *RoPort = EndianValue(static_cast<uint32_t>(Port)).le();
3073
0
  return __WASI_ERRNO_SUCCESS;
3074
0
}
3075
3076
Expect<uint32_t> WasiSockGetPeerAddrV2::body(const Runtime::CallingFrame &Frame,
3077
                                             int32_t Fd, uint32_t AddressPtr,
3078
0
                                             uint32_t PortPtr) {
3079
0
  auto *MemInst = Frame.getMemoryByIndex(0);
3080
0
  if (MemInst == nullptr) {
3081
0
    return __WASI_ERRNO_FAULT;
3082
0
  }
3083
0
  __wasi_address_t *InnerAddress =
3084
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
3085
0
  if (InnerAddress == nullptr) {
3086
0
    return __WASI_ERRNO_FAULT;
3087
0
  }
3088
3089
0
  auto Address =
3090
0
      MemInst->getSpan<uint8_t>(InnerAddress->buf, InnerAddress->buf_len);
3091
0
  if (Address.size() != InnerAddress->buf_len) {
3092
0
    return __WASI_ERRNO_FAULT;
3093
0
  }
3094
3095
0
  uint32_t *const RoPort = MemInst->getPointer<uint32_t *>(PortPtr);
3096
0
  if (RoPort == nullptr) {
3097
0
    return __WASI_ERRNO_FAULT;
3098
0
  }
3099
3100
0
  if (Address.size() != 128) {
3101
0
    return __WASI_ERRNO_INVAL;
3102
0
  }
3103
3104
0
  const __wasi_fd_t WasiFd = Fd;
3105
0
  WASI::WasiAddrStorage &Storage =
3106
0
      *reinterpret_cast<WASI::WasiAddrStorage *>(Address.data());
3107
0
  Address = Storage.getAddress();
3108
0
  __wasi_address_family_t WasiAddressFamily;
3109
0
  uint16_t Port;
3110
3111
0
  if (auto Res =
3112
0
          Env.sockGetPeerAddr(WasiFd, &WasiAddressFamily, Address, &Port);
3113
0
      unlikely(!Res)) {
3114
0
    return Res.error();
3115
0
  }
3116
0
  Storage.setAddressFamily(WasiAddressFamily);
3117
0
  *RoPort = EndianValue(static_cast<uint32_t>(Port)).le();
3118
0
  return __WASI_ERRNO_SUCCESS;
3119
0
}
3120
} // namespace Host
3121
} // namespace WasmEdge