Coverage Report

Created: 2025-11-24 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/lib/host/wasi/wasifunc.cpp
Line
Count
Source
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
374
0
template <typename T> inline bool isMisaligned(uint32_t Ptr) noexcept {
375
0
  return (Ptr & (alignof(T) - 1)) != 0;
376
0
}
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<unsigned int>(unsigned int)
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<unsigned long>(unsigned int)
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<__wasi_fdstat_t>(unsigned int)
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<__wasi_filestat_t>(unsigned int)
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<__wasi_iovec_t>(unsigned int)
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<__wasi_prestat_t>(unsigned int)
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<__wasi_ciovec_t>(unsigned int)
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<int>(unsigned int)
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<__wasi_subscription_t>(unsigned int)
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<__wasi_event_t>(unsigned int)
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<__wasi_address_t>(unsigned int)
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<__wasi_roflags_t>(unsigned int)
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<__wasi_addrinfo_t>(unsigned int)
Unexecuted instantiation: wasifunc.cpp:bool WasmEdge::Host::(anonymous namespace)::isMisaligned<unsigned short>(unsigned int)
377
} // namespace
378
379
Expect<uint32_t> WasiArgsGet::body(const Runtime::CallingFrame &Frame,
380
0
                                   uint32_t ArgvPtr, uint32_t ArgvBufPtr) {
381
  // Alignment checks
382
0
  if (unlikely(isMisaligned<uint8_t_ptr>(ArgvPtr))) {
383
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
384
0
  }
385
  // ArgvBufPtr should be aligned to at least 1 byte (which is always true)
386
387
  // Check memory instance from module.
388
0
  auto *MemInst = Frame.getMemoryByIndex(0);
389
0
  if (MemInst == nullptr) {
390
0
    return __WASI_ERRNO_FAULT;
391
0
  }
392
393
  // Store **Argv.
394
0
  const auto &Arguments = Env.getArguments();
395
0
  const uint32_t ArgvSize = static_cast<uint32_t>(Arguments.size());
396
0
  const uint32_t ArgvBufSize = calculateBufferSize(Arguments);
397
398
  // Check for invalid address.
399
0
  const auto Argv = MemInst->getSpan<uint8_t_ptr>(ArgvPtr, ArgvSize);
400
0
  if (unlikely(Argv.size() != ArgvSize)) {
401
0
    return __WASI_ERRNO_FAULT;
402
0
  }
403
0
  const auto ArgvBuf = MemInst->getSpan<uint8_t>(ArgvBufPtr, ArgvBufSize);
404
0
  if (unlikely(ArgvBuf.size() != ArgvBufSize)) {
405
0
    return __WASI_ERRNO_FAULT;
406
0
  }
407
408
0
  if (!Argv.empty()) {
409
0
    Argv[0] = ArgvBufPtr;
410
0
  }
411
412
0
  if (auto Res = Env.argsGet(Argv, ArgvBuf); unlikely(!Res)) {
413
0
    return Res.error();
414
0
  }
415
416
0
  return __WASI_ERRNO_SUCCESS;
417
0
}
418
419
Expect<uint32_t> WasiArgsSizesGet::body(const Runtime::CallingFrame &Frame,
420
                                        uint32_t /* Out */ ArgcPtr,
421
0
                                        uint32_t /* Out */ ArgvBufSizePtr) {
422
  // Alignment checks
423
0
  if (unlikely(isMisaligned<__wasi_size_t>(ArgcPtr))) {
424
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
425
0
  }
426
0
  if (unlikely(isMisaligned<__wasi_size_t>(ArgvBufSizePtr))) {
427
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
428
0
  }
429
430
  // Check memory instance from module.
431
0
  auto *MemInst = Frame.getMemoryByIndex(0);
432
0
  if (MemInst == nullptr) {
433
0
    return __WASI_ERRNO_FAULT;
434
0
  }
435
436
  // Check for invalid address.
437
0
  auto *const __restrict__ Argc = MemInst->getPointer<__wasi_size_t *>(ArgcPtr);
438
0
  if (unlikely(Argc == nullptr)) {
439
0
    return __WASI_ERRNO_FAULT;
440
0
  }
441
0
  auto *const __restrict__ ArgvBufSize =
442
0
      MemInst->getPointer<__wasi_size_t *>(ArgvBufSizePtr);
443
0
  if (unlikely(ArgvBufSize == nullptr)) {
444
0
    return __WASI_ERRNO_FAULT;
445
0
  }
446
447
0
  if (auto Res = Env.argsSizesGet(*Argc, *ArgvBufSize); unlikely(!Res)) {
448
0
    return Res.error();
449
0
  }
450
0
  return __WASI_ERRNO_SUCCESS;
451
0
}
452
453
Expect<uint32_t> WasiEnvironGet::body(const Runtime::CallingFrame &Frame,
454
0
                                      uint32_t EnvPtr, uint32_t EnvBufPtr) {
455
  // Alignment checks
456
0
  if (unlikely(isMisaligned<uint8_t_ptr>(EnvPtr))) {
457
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
458
0
  }
459
  // EnvBufPtr should be aligned to at least 1 byte (which is always true)
460
461
  // Check memory instance from module.
462
0
  auto *MemInst = Frame.getMemoryByIndex(0);
463
0
  if (MemInst == nullptr) {
464
0
    return __WASI_ERRNO_FAULT;
465
0
  }
466
467
  // Store **Env.
468
0
  const auto &EnvironVariables = Env.getEnvironVariables();
469
0
  const uint32_t EnvSize = static_cast<uint32_t>(EnvironVariables.size());
470
0
  const uint32_t EnvBufSize = calculateBufferSize(EnvironVariables);
471
472
  // Check for invalid address.
473
0
  const auto EnvSpan = MemInst->getSpan<uint8_t_ptr>(EnvPtr, EnvSize);
474
0
  if (unlikely(EnvSpan.size() != EnvSize)) {
475
0
    return __WASI_ERRNO_FAULT;
476
0
  }
477
0
  const auto EnvBuf = MemInst->getSpan<uint8_t>(EnvBufPtr, EnvBufSize);
478
0
  if (unlikely(EnvBuf.size() != EnvBufSize)) {
479
0
    return __WASI_ERRNO_FAULT;
480
0
  }
481
482
0
  if (!EnvSpan.empty()) {
483
0
    EnvSpan[0] = EnvBufPtr;
484
0
  }
485
486
0
  if (auto Res = this->Env.environGet(EnvSpan, EnvBuf); unlikely(!Res)) {
487
0
    return Res.error();
488
0
  }
489
490
0
  return __WASI_ERRNO_SUCCESS;
491
0
}
492
493
Expect<uint32_t> WasiEnvironSizesGet::body(const Runtime::CallingFrame &Frame,
494
                                           uint32_t /* Out */ EnvCntPtr,
495
0
                                           uint32_t /* Out */ EnvBufSizePtr) {
496
  // Alignment checks
497
0
  if (unlikely(isMisaligned<__wasi_size_t>(EnvCntPtr))) {
498
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
499
0
  }
500
0
  if (unlikely(isMisaligned<__wasi_size_t>(EnvBufSizePtr))) {
501
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
502
0
  }
503
504
  // Check memory instance from module.
505
0
  auto *MemInst = Frame.getMemoryByIndex(0);
506
0
  if (MemInst == nullptr) {
507
0
    return __WASI_ERRNO_FAULT;
508
0
  }
509
510
  // Check for invalid address.
511
0
  auto *const __restrict__ Envc =
512
0
      MemInst->getPointer<__wasi_size_t *>(EnvCntPtr);
513
0
  if (unlikely(Envc == nullptr)) {
514
0
    return __WASI_ERRNO_FAULT;
515
0
  }
516
0
  auto *const __restrict__ EnvBufSize =
517
0
      MemInst->getPointer<__wasi_size_t *>(EnvBufSizePtr);
518
0
  if (unlikely(EnvBufSize == nullptr)) {
519
0
    return __WASI_ERRNO_FAULT;
520
0
  }
521
522
0
  if (auto Res = Env.environSizesGet(*Envc, *EnvBufSize); unlikely(!Res)) {
523
0
    return Res.error();
524
0
  }
525
0
  return __WASI_ERRNO_SUCCESS;
526
0
}
527
528
Expect<uint32_t> WasiClockResGet::body(const Runtime::CallingFrame &Frame,
529
                                       uint32_t ClockId,
530
0
                                       uint32_t /* Out */ ResolutionPtr) {
531
  // Alignment checks
532
0
  if (unlikely(isMisaligned<__wasi_timestamp_t>(ResolutionPtr))) {
533
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
534
0
  }
535
536
  // Check memory instance from module.
537
0
  auto *MemInst = Frame.getMemoryByIndex(0);
538
0
  if (MemInst == nullptr) {
539
0
    return __WASI_ERRNO_FAULT;
540
0
  }
541
542
0
  auto *const Resolution =
543
0
      MemInst->getPointer<__wasi_timestamp_t *>(ResolutionPtr);
544
0
  if (unlikely(Resolution == nullptr)) {
545
0
    return __WASI_ERRNO_FAULT;
546
0
  }
547
548
0
  __wasi_clockid_t WasiClockId;
549
0
  if (auto Res = cast<__wasi_clockid_t>(ClockId); unlikely(!Res)) {
550
0
    return Res.error();
551
0
  } else {
552
0
    WasiClockId = *Res;
553
0
  }
554
555
0
  if (auto Res = Env.clockResGet(WasiClockId, *Resolution); unlikely(!Res)) {
556
0
    return Res.error();
557
0
  }
558
0
  return __WASI_ERRNO_SUCCESS;
559
0
}
560
561
Expect<uint32_t> WasiClockTimeGet::body(const Runtime::CallingFrame &Frame,
562
                                        uint32_t ClockId, uint64_t Precision,
563
0
                                        uint32_t /* Out */ TimePtr) {
564
  // Alignment checks
565
0
  if (unlikely(isMisaligned<__wasi_timestamp_t>(TimePtr))) {
566
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
567
0
  }
568
569
  // Check memory instance from module.
570
0
  auto *MemInst = Frame.getMemoryByIndex(0);
571
0
  if (MemInst == nullptr) {
572
0
    return __WASI_ERRNO_FAULT;
573
0
  }
574
575
0
  auto *const Time = MemInst->getPointer<__wasi_timestamp_t *>(TimePtr);
576
0
  if (unlikely(Time == nullptr)) {
577
0
    return __WASI_ERRNO_FAULT;
578
0
  }
579
580
0
  __wasi_clockid_t WasiClockId;
581
0
  if (auto Res = cast<__wasi_clockid_t>(ClockId); unlikely(!Res)) {
582
0
    return Res.error();
583
0
  } else {
584
0
    WasiClockId = *Res;
585
0
  }
586
587
0
  const __wasi_timestamp_t WasiPrecision = Precision;
588
589
0
  if (auto Res = Env.clockTimeGet(WasiClockId, WasiPrecision, *Time);
590
0
      unlikely(!Res)) {
591
0
    return Res.error();
592
0
  }
593
0
  return __WASI_ERRNO_SUCCESS;
594
0
}
595
596
Expect<uint32_t> WasiFdAdvise::body(const Runtime::CallingFrame &, int32_t Fd,
597
                                    uint64_t Offset, uint64_t Len,
598
0
                                    uint32_t Advice) {
599
0
  __wasi_advice_t WasiAdvice;
600
0
  if (auto Res = cast<__wasi_advice_t>(Advice); unlikely(!Res)) {
601
0
    return Res.error();
602
0
  } else {
603
0
    WasiAdvice = *Res;
604
0
  }
605
606
0
  const __wasi_fd_t WasiFd = Fd;
607
0
  const __wasi_filesize_t WasiOffset = Offset;
608
0
  const __wasi_filesize_t WasiLen = Len;
609
610
0
  if (auto Res = Env.fdAdvise(WasiFd, WasiOffset, WasiLen, WasiAdvice);
611
0
      unlikely(!Res)) {
612
0
    return Res.error();
613
0
  }
614
0
  return __WASI_ERRNO_SUCCESS;
615
0
}
616
617
Expect<uint32_t> WasiFdAllocate::body(const Runtime::CallingFrame &, int32_t Fd,
618
0
                                      uint64_t Offset, uint64_t Len) {
619
0
  const __wasi_fd_t WasiFd = Fd;
620
0
  const __wasi_filesize_t WasiOffset = Offset;
621
0
  const __wasi_filesize_t WasiLen = Len;
622
623
0
  if (auto Res = Env.fdAllocate(WasiFd, WasiOffset, WasiLen); unlikely(!Res)) {
624
0
    return Res.error();
625
0
  }
626
0
  return __WASI_ERRNO_SUCCESS;
627
0
}
628
629
0
Expect<uint32_t> WasiFdClose::body(const Runtime::CallingFrame &, int32_t Fd) {
630
0
  const __wasi_fd_t WasiFd = Fd;
631
632
0
  if (auto Res = Env.fdClose(WasiFd); unlikely(!Res)) {
633
0
    return Res.error();
634
0
  }
635
0
  return __WASI_ERRNO_SUCCESS;
636
0
}
637
638
Expect<uint32_t> WasiFdDatasync::body(const Runtime::CallingFrame &,
639
0
                                      int32_t Fd) {
640
0
  const __wasi_fd_t WasiFd = Fd;
641
642
0
  if (auto Res = Env.fdDatasync(WasiFd); unlikely(!Res)) {
643
0
    return Res.error();
644
0
  }
645
0
  return __WASI_ERRNO_SUCCESS;
646
0
}
647
648
Expect<uint32_t> WasiFdFdstatGet::body(const Runtime::CallingFrame &Frame,
649
                                       int32_t Fd,
650
0
                                       uint32_t /* Out */ FdStatPtr) {
651
  // Alignment checks
652
0
  if (unlikely(isMisaligned<__wasi_fdstat_t>(FdStatPtr))) {
653
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
654
0
  }
655
656
  // Check memory instance from module.
657
0
  auto *MemInst = Frame.getMemoryByIndex(0);
658
0
  if (MemInst == nullptr) {
659
0
    return __WASI_ERRNO_FAULT;
660
0
  }
661
662
0
  auto *const FdStat = MemInst->getPointer<__wasi_fdstat_t *>(FdStatPtr);
663
0
  if (unlikely(FdStat == nullptr)) {
664
0
    return __WASI_ERRNO_FAULT;
665
0
  }
666
667
0
  const __wasi_fd_t WasiFd = Fd;
668
669
0
  if (auto Res = Env.fdFdstatGet(WasiFd, *FdStat); unlikely(!Res)) {
670
0
    return Res.error();
671
0
  }
672
0
  return __WASI_ERRNO_SUCCESS;
673
0
}
674
675
Expect<uint32_t> WasiFdFdstatSetFlags::body(const Runtime::CallingFrame &,
676
0
                                            int32_t Fd, uint32_t FsFlags) {
677
0
  __wasi_fdflags_t WasiFdFlags;
678
0
  if (auto Res = cast<__wasi_fdflags_t>(FsFlags); unlikely(!Res)) {
679
0
    return Res.error();
680
0
  } else {
681
0
    WasiFdFlags = *Res;
682
0
  }
683
684
0
  const __wasi_fd_t WasiFd = Fd;
685
686
0
  if (auto Res = Env.fdFdstatSetFlags(WasiFd, WasiFdFlags); unlikely(!Res)) {
687
0
    return Res.error();
688
0
  }
689
0
  return __WASI_ERRNO_SUCCESS;
690
0
}
691
692
Expect<uint32_t> WasiFdFdstatSetRights::body(const Runtime::CallingFrame &,
693
                                             int32_t Fd, uint64_t FsRightsBase,
694
0
                                             uint64_t FsRightsInheriting) {
695
0
  __wasi_rights_t WasiFsRightsBase;
696
0
  if (auto Res = cast<__wasi_rights_t>(FsRightsBase); unlikely(!Res)) {
697
0
    return Res.error();
698
0
  } else {
699
0
    WasiFsRightsBase = *Res;
700
0
  }
701
702
0
  __wasi_rights_t WasiFsRightsInheriting;
703
0
  if (auto Res = cast<__wasi_rights_t>(FsRightsInheriting); unlikely(!Res)) {
704
0
    return Res.error();
705
0
  } else {
706
0
    WasiFsRightsInheriting = *Res;
707
0
  }
708
709
0
  const __wasi_fd_t WasiFd = Fd;
710
711
0
  if (auto Res = Env.fdFdstatSetRights(WasiFd, WasiFsRightsBase,
712
0
                                       WasiFsRightsInheriting);
713
0
      unlikely(!Res)) {
714
0
    return Res.error();
715
0
  }
716
0
  return __WASI_ERRNO_SUCCESS;
717
0
}
718
719
Expect<uint32_t> WasiFdFilestatGet::body(const Runtime::CallingFrame &Frame,
720
                                         int32_t Fd,
721
0
                                         uint32_t /* Out */ FilestatPtr) {
722
  // Alignment checks
723
0
  if (unlikely(isMisaligned<__wasi_filestat_t>(FilestatPtr))) {
724
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
725
0
  }
726
727
  // Check memory instance from module.
728
0
  auto *MemInst = Frame.getMemoryByIndex(0);
729
0
  if (MemInst == nullptr) {
730
0
    return __WASI_ERRNO_FAULT;
731
0
  }
732
733
0
  auto *const Filestat = MemInst->getPointer<__wasi_filestat_t *>(FilestatPtr);
734
0
  if (unlikely(Filestat == nullptr)) {
735
0
    return __WASI_ERRNO_FAULT;
736
0
  }
737
738
0
  const __wasi_fd_t WasiFd = Fd;
739
740
0
  if (auto Res = Env.fdFilestatGet(WasiFd, *Filestat); unlikely(!Res)) {
741
0
    return Res.error();
742
0
  }
743
0
  return __WASI_ERRNO_SUCCESS;
744
0
}
745
746
Expect<uint32_t> WasiFdFilestatSetSize::body(const Runtime::CallingFrame &,
747
0
                                             int32_t Fd, uint64_t Size) {
748
0
  const __wasi_fd_t WasiFd = Fd;
749
0
  const __wasi_filesize_t WasiSize = Size;
750
751
0
  if (auto Res = Env.fdFilestatSetSize(WasiFd, WasiSize); unlikely(!Res)) {
752
0
    return Res.error();
753
0
  }
754
0
  return __WASI_ERRNO_SUCCESS;
755
0
}
756
757
Expect<uint32_t> WasiFdFilestatSetTimes::body(const Runtime::CallingFrame &,
758
                                              int32_t Fd, uint64_t ATim,
759
                                              uint64_t MTim,
760
0
                                              uint32_t FstFlags) {
761
0
  __wasi_fstflags_t WasiFstFlags;
762
0
  if (auto Res = cast<__wasi_fstflags_t>(FstFlags); unlikely(!Res)) {
763
0
    return Res.error();
764
0
  } else {
765
0
    WasiFstFlags = *Res;
766
0
  }
767
768
0
  const __wasi_fd_t WasiFd = Fd;
769
0
  const __wasi_timestamp_t WasiATim = ATim;
770
0
  const __wasi_timestamp_t WasiMTim = MTim;
771
772
0
  if (auto Res =
773
0
          Env.fdFilestatSetTimes(WasiFd, WasiATim, WasiMTim, WasiFstFlags);
774
0
      unlikely(!Res)) {
775
0
    return Res.error();
776
0
  }
777
0
  return __WASI_ERRNO_SUCCESS;
778
0
}
779
780
Expect<uint32_t> WasiFdPread::body(const Runtime::CallingFrame &Frame,
781
                                   int32_t Fd, uint32_t IOVsPtr,
782
                                   uint32_t IOVsLen, uint64_t Offset,
783
0
                                   uint32_t /* Out */ NReadPtr) {
784
  // Alignment checks
785
0
  if (unlikely(isMisaligned<__wasi_iovec_t>(IOVsPtr))) {
786
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
787
0
  }
788
789
0
  if (unlikely(isMisaligned<__wasi_size_t>(NReadPtr))) {
790
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
791
0
  }
792
793
  // Check memory instance from module.
794
0
  auto *MemInst = Frame.getMemoryByIndex(0);
795
0
  if (MemInst == nullptr) {
796
0
    return __WASI_ERRNO_FAULT;
797
0
  }
798
799
0
  const __wasi_size_t WasiIOVsLen = IOVsLen;
800
0
  if (unlikely(WasiIOVsLen > WASI::kIOVMax)) {
801
0
    return __WASI_ERRNO_INVAL;
802
0
  }
803
804
  // Check for invalid address.
805
0
  const auto IOVsArray = MemInst->getSpan<__wasi_iovec_t>(IOVsPtr, WasiIOVsLen);
806
0
  if (unlikely(IOVsArray.size() != WasiIOVsLen)) {
807
0
    return __WASI_ERRNO_FAULT;
808
0
  }
809
810
0
  auto *const NRead = MemInst->getPointer<__wasi_size_t *>(NReadPtr);
811
0
  if (unlikely(NRead == nullptr)) {
812
0
    return __WASI_ERRNO_FAULT;
813
0
  }
814
815
0
  __wasi_size_t TotalSize = 0;
816
0
  StaticVector<Span<uint8_t>, WASI::kIOVMax> WasiIOVs;
817
818
0
  for (auto &IOV : IOVsArray) {
819
    // Capping total size.
820
0
    const __wasi_size_t Space =
821
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
822
0
    const EndianValue<uint32_t> IOVBufLen = IOV.buf_len;
823
0
    const __wasi_size_t BufLen =
824
0
        unlikely(IOVBufLen.le() > Space) ? Space : IOVBufLen.le();
825
0
    TotalSize += BufLen;
826
827
    // Check for invalid address.
828
0
    const auto ReadArr =
829
0
        MemInst->getSpan<uint8_t>(EndianValue(IOV.buf).le(), BufLen);
830
0
    if (unlikely(ReadArr.size() != BufLen)) {
831
0
      return __WASI_ERRNO_FAULT;
832
0
    }
833
0
    WasiIOVs.emplace_back_unchecked(ReadArr);
834
0
  }
835
836
0
  const __wasi_fd_t WasiFd = Fd;
837
0
  const __wasi_filesize_t WasiOffset = Offset;
838
839
0
  if (auto Res = Env.fdPread(WasiFd, WasiIOVs, WasiOffset, *NRead);
840
0
      unlikely(!Res)) {
841
0
    return Res.error();
842
0
  }
843
0
  return __WASI_ERRNO_SUCCESS;
844
0
}
845
846
Expect<uint32_t> WasiFdPrestatDirName::body(const Runtime::CallingFrame &Frame,
847
                                            int32_t Fd, uint32_t PathBufPtr,
848
0
                                            uint32_t PathLen) {
849
  // Alignment checks
850
  // PathBufPtr should be aligned to at least 1 byte (which is always true)
851
852
  // Check memory instance from module.
853
0
  auto *MemInst = Frame.getMemoryByIndex(0);
854
0
  if (MemInst == nullptr) {
855
0
    return __WASI_ERRNO_FAULT;
856
0
  }
857
858
0
  const auto PathBuf = MemInst->getSpan<uint8_t>(PathBufPtr, PathLen);
859
0
  if (unlikely(PathBuf.size() != PathLen)) {
860
0
    return __WASI_ERRNO_FAULT;
861
0
  }
862
863
0
  const __wasi_fd_t WasiFd = Fd;
864
865
0
  if (auto Res = Env.fdPrestatDirName(WasiFd, PathBuf); unlikely(!Res)) {
866
0
    return Res.error();
867
0
  }
868
0
  return __WASI_ERRNO_SUCCESS;
869
0
}
870
871
Expect<uint32_t> WasiFdPrestatGet::body(const Runtime::CallingFrame &Frame,
872
                                        int32_t Fd,
873
0
                                        uint32_t /* Out */ PreStatPtr) {
874
  // Alignment checks
875
0
  if (unlikely(isMisaligned<__wasi_prestat_t>(PreStatPtr))) {
876
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
877
0
  }
878
879
  // Check memory instance from module.
880
0
  auto *MemInst = Frame.getMemoryByIndex(0);
881
0
  if (MemInst == nullptr) {
882
0
    return __WASI_ERRNO_FAULT;
883
0
  }
884
885
0
  __wasi_prestat_t *const PreStat =
886
0
      MemInst->getPointer<__wasi_prestat_t *>(PreStatPtr);
887
0
  if (unlikely(PreStat == nullptr)) {
888
0
    return __WASI_ERRNO_FAULT;
889
0
  }
890
891
0
  const __wasi_fd_t WasiFd = Fd;
892
893
0
  if (auto Res = Env.fdPrestatGet(WasiFd, *PreStat); unlikely(!Res)) {
894
0
    return Res.error();
895
0
  }
896
0
  return __WASI_ERRNO_SUCCESS;
897
0
}
898
899
Expect<uint32_t> WasiFdPwrite::body(const Runtime::CallingFrame &Frame,
900
                                    int32_t Fd, uint32_t IOVsPtr,
901
                                    uint32_t IOVsLen, uint64_t Offset,
902
0
                                    uint32_t /* Out */ NWrittenPtr) {
903
  // Alignment checks
904
0
  if (unlikely(isMisaligned<__wasi_ciovec_t>(IOVsPtr))) {
905
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
906
0
  }
907
908
0
  if (unlikely(isMisaligned<__wasi_size_t>(NWrittenPtr))) {
909
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
910
0
  }
911
912
  // Check memory instance from module.
913
0
  auto *MemInst = Frame.getMemoryByIndex(0);
914
0
  if (MemInst == nullptr) {
915
0
    return __WASI_ERRNO_FAULT;
916
0
  }
917
918
0
  const __wasi_size_t WasiIOVsLen = IOVsLen;
919
0
  if (unlikely(WasiIOVsLen > WASI::kIOVMax)) {
920
0
    return __WASI_ERRNO_INVAL;
921
0
  }
922
923
  // Check for invalid address.
924
0
  const auto IOVsArray =
925
0
      MemInst->getSpan<__wasi_ciovec_t>(IOVsPtr, WasiIOVsLen);
926
0
  if (unlikely(IOVsArray.size() != WasiIOVsLen)) {
927
0
    return __WASI_ERRNO_FAULT;
928
0
  }
929
930
  // Check for invalid address.
931
0
  auto *const NWritten = MemInst->getPointer<__wasi_size_t *>(NWrittenPtr);
932
0
  if (unlikely(NWritten == nullptr)) {
933
0
    return __WASI_ERRNO_FAULT;
934
0
  }
935
936
0
  __wasi_size_t TotalSize = 0;
937
0
  StaticVector<Span<const uint8_t>, WASI::kIOVMax> WasiIOVs;
938
939
0
  for (auto &IOV : IOVsArray) {
940
    // Capping total size.
941
0
    const __wasi_size_t Space =
942
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
943
944
0
    const EndianValue<uint32_t> IOVBufLen = IOV.buf_len;
945
0
    const __wasi_size_t BufLen =
946
0
        unlikely(IOVBufLen.le() > Space) ? Space : IOVBufLen.le();
947
0
    TotalSize += BufLen;
948
949
    // Check for invalid address.
950
0
    const auto WriteArr =
951
0
        MemInst->getSpan<const uint8_t>(EndianValue(IOV.buf).le(), BufLen);
952
0
    if (unlikely(WriteArr.size() != BufLen)) {
953
0
      return __WASI_ERRNO_FAULT;
954
0
    }
955
0
    WasiIOVs.emplace_back_unchecked(WriteArr);
956
0
  }
957
958
0
  const __wasi_fd_t WasiFd = Fd;
959
0
  const __wasi_filesize_t WasiOffset = Offset;
960
961
0
  if (auto Res = Env.fdPwrite(WasiFd, WasiIOVs, WasiOffset, *NWritten);
962
0
      unlikely(!Res)) {
963
0
    return Res.error();
964
0
  }
965
0
  return __WASI_ERRNO_SUCCESS;
966
0
}
967
968
Expect<uint32_t> WasiFdRead::body(const Runtime::CallingFrame &Frame,
969
                                  int32_t Fd, uint32_t IOVsPtr,
970
                                  uint32_t IOVsLen,
971
0
                                  uint32_t /* Out */ NReadPtr) {
972
  // Alignment checks
973
0
  if (unlikely(isMisaligned<__wasi_iovec_t>(IOVsPtr))) {
974
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
975
0
  }
976
977
0
  if (unlikely(isMisaligned<__wasi_size_t>(NReadPtr))) {
978
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
979
0
  }
980
981
  // Check memory instance from module.
982
0
  auto *MemInst = Frame.getMemoryByIndex(0);
983
0
  if (MemInst == nullptr) {
984
0
    return __WASI_ERRNO_FAULT;
985
0
  }
986
987
0
  const __wasi_size_t WasiIOVsLen = IOVsLen;
988
0
  if (unlikely(WasiIOVsLen > WASI::kIOVMax)) {
989
0
    return __WASI_ERRNO_INVAL;
990
0
  }
991
992
  // Check for invalid address.
993
0
  const auto IOVsArray = MemInst->getSpan<__wasi_iovec_t>(IOVsPtr, WasiIOVsLen);
994
0
  if (unlikely(IOVsArray.size() != WasiIOVsLen)) {
995
0
    return __WASI_ERRNO_FAULT;
996
0
  }
997
998
0
  auto *const NRead = MemInst->getPointer<__wasi_size_t *>(NReadPtr);
999
0
  if (unlikely(NRead == nullptr)) {
1000
0
    return __WASI_ERRNO_FAULT;
1001
0
  }
1002
1003
0
  __wasi_size_t TotalSize = 0;
1004
0
  StaticVector<Span<uint8_t>, WASI::kIOVMax> WasiIOVs;
1005
1006
0
  for (auto &IOV : IOVsArray) {
1007
    // Capping total size.
1008
0
    const __wasi_size_t Space =
1009
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
1010
0
    const EndianValue<uint32_t> IOVBufLen = IOV.buf_len;
1011
0
    const __wasi_size_t BufLen =
1012
0
        unlikely(IOVBufLen.le() > Space) ? Space : IOVBufLen.le();
1013
0
    TotalSize += BufLen;
1014
1015
    // Check for invalid address.
1016
0
    const auto ReadArr =
1017
0
        MemInst->getSpan<uint8_t>(EndianValue(IOV.buf).le(), BufLen);
1018
0
    if (unlikely(ReadArr.size() != BufLen)) {
1019
0
      return __WASI_ERRNO_FAULT;
1020
0
    }
1021
0
    WasiIOVs.emplace_back_unchecked(ReadArr);
1022
0
  }
1023
1024
0
  const __wasi_fd_t WasiFd = Fd;
1025
1026
0
  if (auto Res = Env.fdRead(WasiFd, WasiIOVs, *NRead); unlikely(!Res)) {
1027
0
    return Res.error();
1028
0
  }
1029
0
  return __WASI_ERRNO_SUCCESS;
1030
0
}
1031
1032
Expect<uint32_t> WasiFdReadDir::body(const Runtime::CallingFrame &Frame,
1033
                                     int32_t Fd, uint32_t BufPtr,
1034
                                     uint32_t BufLen, uint64_t Cookie,
1035
0
                                     uint32_t /* Out */ NReadPtr) {
1036
  // Alignment checks
1037
0
  if (unlikely(isMisaligned<__wasi_size_t>(NReadPtr))) {
1038
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1039
0
  }
1040
  // BufPtr should be aligned to at least 1 byte (which is always true)
1041
1042
  // Check memory instance from module.
1043
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1044
0
  if (MemInst == nullptr) {
1045
0
    return __WASI_ERRNO_FAULT;
1046
0
  }
1047
1048
0
  const __wasi_size_t WasiBufLen = BufLen;
1049
1050
  // Check for invalid address.
1051
0
  const auto Buf = MemInst->getSpan<uint8_t>(BufPtr, WasiBufLen);
1052
0
  if (unlikely(Buf.size() != WasiBufLen)) {
1053
0
    return __WASI_ERRNO_FAULT;
1054
0
  }
1055
1056
0
  auto *const NRead = MemInst->getPointer<__wasi_size_t *>(NReadPtr);
1057
0
  if (unlikely(NRead == nullptr)) {
1058
0
    return __WASI_ERRNO_FAULT;
1059
0
  }
1060
1061
0
  const __wasi_fd_t WasiFd = Fd;
1062
0
  const __wasi_dircookie_t WasiCookie = Cookie;
1063
1064
0
  if (auto Res = Env.fdReaddir(WasiFd, Buf, WasiCookie, *NRead);
1065
0
      unlikely(!Res)) {
1066
0
    return Res.error();
1067
0
  }
1068
0
  return __WASI_ERRNO_SUCCESS;
1069
0
}
1070
1071
Expect<uint32_t> WasiFdRenumber::body(const Runtime::CallingFrame &, int32_t Fd,
1072
0
                                      int32_t ToFd) {
1073
0
  const __wasi_fd_t WasiFd = Fd;
1074
0
  const __wasi_fd_t WasiToFd = ToFd;
1075
1076
0
  if (auto Res = Env.fdRenumber(WasiFd, WasiToFd); unlikely(!Res)) {
1077
0
    return Res.error();
1078
0
  }
1079
0
  return __WASI_ERRNO_SUCCESS;
1080
0
}
1081
1082
Expect<int32_t> WasiFdSeek::body(const Runtime::CallingFrame &Frame, int32_t Fd,
1083
                                 int64_t Offset, uint32_t Whence,
1084
0
                                 uint32_t /* Out */ NewOffsetPtr) {
1085
  // Alignment checks
1086
0
  if (unlikely(isMisaligned<__wasi_filesize_t>(NewOffsetPtr))) {
1087
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1088
0
  }
1089
1090
  // Check memory instance from module.
1091
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1092
0
  if (MemInst == nullptr) {
1093
0
    return __WASI_ERRNO_FAULT;
1094
0
  }
1095
1096
0
  __wasi_whence_t WasiWhence;
1097
0
  if (auto Res = cast<__wasi_whence_t>(Whence); unlikely(!Res)) {
1098
0
    return Res.error();
1099
0
  } else {
1100
0
    WasiWhence = *Res;
1101
0
  }
1102
1103
  // Check for invalid address.
1104
0
  auto *NewOffset = MemInst->getPointer<__wasi_filesize_t *>(NewOffsetPtr);
1105
0
  if (unlikely(NewOffset == nullptr)) {
1106
0
    return __WASI_ERRNO_FAULT;
1107
0
  }
1108
1109
0
  const __wasi_fd_t WasiFd = Fd;
1110
0
  const __wasi_filedelta_t WasiOffset = Offset;
1111
1112
0
  if (auto Res = Env.fdSeek(WasiFd, WasiOffset, WasiWhence, *NewOffset);
1113
0
      unlikely(!Res)) {
1114
0
    return Res.error();
1115
0
  }
1116
0
  return __WASI_ERRNO_SUCCESS;
1117
0
}
1118
1119
0
Expect<uint32_t> WasiFdSync::body(const Runtime::CallingFrame &, int32_t Fd) {
1120
0
  const __wasi_fd_t WasiFd = Fd;
1121
1122
0
  if (auto Res = Env.fdSync(WasiFd); unlikely(!Res)) {
1123
0
    return Res.error();
1124
0
  }
1125
0
  return __WASI_ERRNO_SUCCESS;
1126
0
}
1127
1128
Expect<uint32_t> WasiFdTell::body(const Runtime::CallingFrame &Frame,
1129
0
                                  int32_t Fd, uint32_t /* Out */ OffsetPtr) {
1130
  // Alignment checks
1131
0
  if (unlikely(isMisaligned<__wasi_filesize_t>(OffsetPtr))) {
1132
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1133
0
  }
1134
1135
  // Check memory instance from module.
1136
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1137
0
  if (MemInst == nullptr) {
1138
0
    return __WASI_ERRNO_FAULT;
1139
0
  }
1140
1141
  // Check for invalid address.
1142
0
  __wasi_filesize_t *Offset =
1143
0
      MemInst->getPointer<__wasi_filesize_t *>(OffsetPtr);
1144
0
  if (unlikely(Offset == nullptr)) {
1145
0
    return __WASI_ERRNO_FAULT;
1146
0
  }
1147
1148
0
  const __wasi_fd_t WasiFd = Fd;
1149
1150
0
  if (auto Res = Env.fdTell(WasiFd, *Offset); unlikely(!Res)) {
1151
0
    return Res.error();
1152
0
  }
1153
0
  return __WASI_ERRNO_SUCCESS;
1154
0
}
1155
1156
Expect<uint32_t> WasiFdWrite::body(const Runtime::CallingFrame &Frame,
1157
                                   int32_t Fd, uint32_t IOVsPtr,
1158
                                   uint32_t IOVsLen,
1159
0
                                   uint32_t /* Out */ NWrittenPtr) {
1160
  // Alignment checks
1161
0
  if (unlikely(isMisaligned<__wasi_ciovec_t>(IOVsPtr))) {
1162
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1163
0
  }
1164
1165
0
  if (unlikely(isMisaligned<__wasi_size_t>(NWrittenPtr))) {
1166
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1167
0
  }
1168
1169
  // Check memory instance from module.
1170
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1171
0
  if (MemInst == nullptr) {
1172
0
    return __WASI_ERRNO_FAULT;
1173
0
  }
1174
1175
0
  const __wasi_size_t WasiIOVsLen = IOVsLen;
1176
0
  if (unlikely(WasiIOVsLen > WASI::kIOVMax)) {
1177
0
    return __WASI_ERRNO_INVAL;
1178
0
  }
1179
1180
  // Check for invalid address.
1181
0
  const auto IOVsArray =
1182
0
      MemInst->getSpan<__wasi_ciovec_t>(IOVsPtr, WasiIOVsLen);
1183
0
  if (unlikely(IOVsArray.size() != WasiIOVsLen)) {
1184
0
    return __WASI_ERRNO_FAULT;
1185
0
  }
1186
1187
  // Check for invalid address.
1188
0
  auto *const NWritten = MemInst->getPointer<__wasi_size_t *>(NWrittenPtr);
1189
0
  if (unlikely(NWritten == nullptr)) {
1190
0
    return __WASI_ERRNO_FAULT;
1191
0
  }
1192
1193
0
  __wasi_size_t TotalSize = 0;
1194
0
  StaticVector<Span<const uint8_t>, WASI::kIOVMax> WasiIOVs;
1195
1196
0
  for (auto &IOV : IOVsArray) {
1197
    // Capping total size.
1198
0
    const __wasi_size_t Space =
1199
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
1200
0
    const EndianValue<uint32_t> IOVBufLen = IOV.buf_len;
1201
0
    const __wasi_size_t BufLen =
1202
0
        unlikely(IOVBufLen.le() > Space) ? Space : IOVBufLen.le();
1203
0
    TotalSize += BufLen;
1204
1205
    // Check for invalid address.
1206
0
    const auto WriteArr =
1207
0
        MemInst->getSpan<const uint8_t>(EndianValue(IOV.buf).le(), BufLen);
1208
0
    if (unlikely(WriteArr.size() != BufLen)) {
1209
0
      return __WASI_ERRNO_FAULT;
1210
0
    }
1211
0
    WasiIOVs.emplace_back_unchecked(WriteArr);
1212
0
  }
1213
1214
0
  const __wasi_fd_t WasiFd = Fd;
1215
1216
0
  if (auto Res = Env.fdWrite(WasiFd, WasiIOVs, *NWritten); unlikely(!Res)) {
1217
0
    return Res.error();
1218
0
  }
1219
0
  return __WASI_ERRNO_SUCCESS;
1220
0
}
1221
1222
Expect<uint32_t>
1223
WasiPathCreateDirectory::body(const Runtime::CallingFrame &Frame, int32_t Fd,
1224
0
                              uint32_t PathPtr, uint32_t PathLen) {
1225
  // PathPtr should be aligned to at least 1 byte (which is always true)
1226
  // Check memory instance from module.
1227
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1228
0
  if (MemInst == nullptr) {
1229
0
    return __WASI_ERRNO_FAULT;
1230
0
  }
1231
1232
0
  const __wasi_size_t WasiPathLen = PathLen;
1233
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1234
0
  if (unlikely(Path.size() != WasiPathLen)) {
1235
0
    return __WASI_ERRNO_FAULT;
1236
0
  }
1237
1238
0
  const __wasi_fd_t WasiFd = Fd;
1239
1240
0
  if (auto Res = Env.pathCreateDirectory(WasiFd, Path); unlikely(!Res)) {
1241
0
    return Res.error();
1242
0
  }
1243
0
  return __WASI_ERRNO_SUCCESS;
1244
0
}
1245
1246
Expect<uint32_t> WasiPathFilestatGet::body(const Runtime::CallingFrame &Frame,
1247
                                           int32_t Fd, uint32_t Flags,
1248
                                           uint32_t PathPtr, uint32_t PathLen,
1249
0
                                           uint32_t /* Out */ FilestatPtr) {
1250
  // Alignment checks
1251
0
  if (unlikely(isMisaligned<__wasi_filestat_t>(FilestatPtr))) {
1252
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1253
0
  }
1254
  // PathPtr should be aligned to at least 1 byte (which is always true)
1255
1256
  // Check memory instance from module.
1257
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1258
0
  if (MemInst == nullptr) {
1259
0
    return __WASI_ERRNO_FAULT;
1260
0
  }
1261
1262
0
  __wasi_lookupflags_t WasiFlags;
1263
0
  if (auto Res = cast<__wasi_lookupflags_t>(Flags); unlikely(!Res)) {
1264
0
    return Res.error();
1265
0
  } else {
1266
0
    WasiFlags = *Res;
1267
0
  }
1268
1269
0
  auto *const Filestat = MemInst->getPointer<__wasi_filestat_t *>(FilestatPtr);
1270
0
  if (unlikely(Filestat == nullptr)) {
1271
0
    return __WASI_ERRNO_FAULT;
1272
0
  }
1273
1274
0
  const __wasi_size_t WasiPathLen = PathLen;
1275
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1276
0
  if (unlikely(Path.size() != WasiPathLen)) {
1277
0
    return __WASI_ERRNO_FAULT;
1278
0
  }
1279
1280
0
  const __wasi_fd_t WasiFd = Fd;
1281
1282
0
  if (auto Res = Env.pathFilestatGet(WasiFd, Path, WasiFlags, *Filestat);
1283
0
      unlikely(!Res)) {
1284
0
    return Res.error();
1285
0
  }
1286
0
  return __WASI_ERRNO_SUCCESS;
1287
0
}
1288
1289
Expect<uint32_t>
1290
WasiPathFilestatSetTimes::body(const Runtime::CallingFrame &Frame, int32_t Fd,
1291
                               uint32_t Flags, uint32_t PathPtr,
1292
                               uint32_t PathLen, uint64_t ATim, uint64_t MTim,
1293
0
                               uint32_t FstFlags) {
1294
  // PathPtr should be aligned to at least 1 byte (which is always true)
1295
1296
  // Check memory instance from module.
1297
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1298
0
  if (MemInst == nullptr) {
1299
0
    return __WASI_ERRNO_FAULT;
1300
0
  }
1301
1302
0
  __wasi_lookupflags_t WasiFlags;
1303
0
  if (auto Res = cast<__wasi_lookupflags_t>(Flags); unlikely(!Res)) {
1304
0
    return Res.error();
1305
0
  } else {
1306
0
    WasiFlags = *Res;
1307
0
  }
1308
1309
0
  __wasi_fstflags_t WasiFstFlags;
1310
0
  if (auto Res = cast<__wasi_fstflags_t>(FstFlags); unlikely(!Res)) {
1311
0
    return Res.error();
1312
0
  } else {
1313
0
    WasiFstFlags = *Res;
1314
0
  }
1315
1316
0
  const __wasi_size_t WasiPathLen = PathLen;
1317
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1318
0
  if (unlikely(Path.size() != WasiPathLen)) {
1319
0
    return __WASI_ERRNO_FAULT;
1320
0
  }
1321
1322
0
  const __wasi_fd_t WasiFd = Fd;
1323
0
  const __wasi_timestamp_t WasiATim = ATim;
1324
0
  const __wasi_timestamp_t WasiMTim = MTim;
1325
1326
0
  if (auto Res = Env.pathFilestatSetTimes(WasiFd, Path, WasiFlags, WasiATim,
1327
0
                                          WasiMTim, WasiFstFlags);
1328
0
      unlikely(!Res)) {
1329
0
    return Res.error();
1330
0
  }
1331
0
  return __WASI_ERRNO_SUCCESS;
1332
0
}
1333
1334
Expect<uint32_t> WasiPathLink::body(const Runtime::CallingFrame &Frame,
1335
                                    int32_t OldFd, uint32_t OldFlags,
1336
                                    uint32_t OldPathPtr, uint32_t OldPathLen,
1337
                                    int32_t NewFd, uint32_t NewPathPtr,
1338
0
                                    uint32_t NewPathLen) {
1339
  // OldPathPtr and NewPathPtr should be aligned to at least 1 byte (which is
1340
  // always true)
1341
1342
  // Check memory instance from module.
1343
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1344
0
  if (MemInst == nullptr) {
1345
0
    return __WASI_ERRNO_FAULT;
1346
0
  }
1347
1348
0
  __wasi_lookupflags_t WasiOldFlags;
1349
0
  if (auto Res = cast<__wasi_lookupflags_t>(OldFlags); unlikely(!Res)) {
1350
0
    return Res.error();
1351
0
  } else {
1352
0
    WasiOldFlags = *Res;
1353
0
  }
1354
1355
0
  const __wasi_size_t WasiOldPathLen = OldPathLen;
1356
0
  const auto OldPath = MemInst->getStringView(OldPathPtr, WasiOldPathLen);
1357
0
  if (unlikely(OldPath.size() != WasiOldPathLen)) {
1358
0
    return __WASI_ERRNO_FAULT;
1359
0
  }
1360
1361
0
  const __wasi_size_t WasiNewPathLen = NewPathLen;
1362
0
  const auto NewPath = MemInst->getStringView(NewPathPtr, WasiNewPathLen);
1363
0
  if (unlikely(NewPath.size() != WasiNewPathLen)) {
1364
0
    return __WASI_ERRNO_FAULT;
1365
0
  }
1366
1367
0
  const __wasi_fd_t WasiOldFd = OldFd;
1368
0
  const __wasi_fd_t WasinewFd = NewFd;
1369
1370
0
  if (auto Res =
1371
0
          Env.pathLink(WasiOldFd, OldPath, WasinewFd, NewPath, WasiOldFlags);
1372
0
      unlikely(!Res)) {
1373
0
    return Res.error();
1374
0
  }
1375
0
  return __WASI_ERRNO_SUCCESS;
1376
0
}
1377
1378
Expect<uint32_t> WasiPathOpen::body(
1379
    const Runtime::CallingFrame &Frame, int32_t DirFd, uint32_t DirFlags,
1380
    uint32_t PathPtr, uint32_t PathLen, uint32_t OFlags, uint64_t FsRightsBase,
1381
0
    uint64_t FsRightsInheriting, uint32_t FsFlags, uint32_t /* Out */ FdPtr) {
1382
  // Alignment checks
1383
0
  if (unlikely(isMisaligned<__wasi_fd_t>(FdPtr))) {
1384
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1385
0
  }
1386
  // PathPtr should be aligned to at least 1 byte (which is always true)
1387
1388
  // Check memory instance from module.
1389
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1390
0
  if (MemInst == nullptr) {
1391
0
    return __WASI_ERRNO_FAULT;
1392
0
  }
1393
1394
0
  __wasi_lookupflags_t WasiDirFlags;
1395
0
  if (auto Res = cast<__wasi_lookupflags_t>(DirFlags); unlikely(!Res)) {
1396
0
    return Res.error();
1397
0
  } else {
1398
0
    WasiDirFlags = *Res;
1399
0
  }
1400
1401
0
  __wasi_oflags_t WasiOFlags;
1402
0
  if (auto Res = cast<__wasi_oflags_t>(OFlags); unlikely(!Res)) {
1403
0
    return Res.error();
1404
0
  } else {
1405
0
    WasiOFlags = *Res;
1406
0
  }
1407
1408
0
  __wasi_rights_t WasiFsRightsBase;
1409
0
  if (auto Res = cast<__wasi_rights_t>(FsRightsBase); unlikely(!Res)) {
1410
0
    return Res.error();
1411
0
  } else {
1412
0
    WasiFsRightsBase = *Res;
1413
0
  }
1414
1415
0
  __wasi_rights_t WasiFsRightsInheriting;
1416
0
  if (auto Res = cast<__wasi_rights_t>(FsRightsInheriting); unlikely(!Res)) {
1417
0
    return Res.error();
1418
0
  } else {
1419
0
    WasiFsRightsInheriting = *Res;
1420
0
  }
1421
1422
0
  __wasi_fdflags_t WasiFsFlags;
1423
0
  if (auto Res = cast<__wasi_fdflags_t>(FsFlags); unlikely(!Res)) {
1424
0
    return Res.error();
1425
0
  } else {
1426
0
    WasiFsFlags = *Res;
1427
0
  }
1428
1429
0
  const __wasi_size_t WasiPathLen = PathLen;
1430
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1431
0
  if (unlikely(Path.size() != WasiPathLen)) {
1432
0
    return __WASI_ERRNO_FAULT;
1433
0
  }
1434
1435
0
  auto *const Fd = MemInst->getPointer<__wasi_fd_t *>(FdPtr);
1436
0
  if (unlikely(Fd == nullptr)) {
1437
0
    return __WASI_ERRNO_FAULT;
1438
0
  }
1439
1440
  // Open directory and read/write rights should fail with isdir
1441
0
  if ((WasiOFlags & __WASI_OFLAGS_DIRECTORY) &&
1442
0
      (WasiFsRightsBase & __WASI_RIGHTS_FD_READ) &&
1443
0
      (WasiFsRightsBase & __WASI_RIGHTS_FD_WRITE)) {
1444
0
    return __WASI_ERRNO_ISDIR;
1445
0
  }
1446
1447
0
  const __wasi_fd_t WasiDirFd = DirFd;
1448
1449
0
  if (auto Res =
1450
0
          Env.pathOpen(WasiDirFd, Path, WasiDirFlags, WasiOFlags,
1451
0
                       WasiFsRightsBase, WasiFsRightsInheriting, WasiFsFlags);
1452
0
      unlikely(!Res)) {
1453
0
    return Res.error();
1454
0
  } else {
1455
0
    *Fd = EndianValue(*Res).le();
1456
0
  }
1457
0
  return __WASI_ERRNO_SUCCESS;
1458
0
}
1459
1460
Expect<uint32_t> WasiPathReadLink::body(const Runtime::CallingFrame &Frame,
1461
                                        int32_t Fd, uint32_t PathPtr,
1462
                                        uint32_t PathLen, uint32_t BufPtr,
1463
                                        uint32_t BufLen,
1464
0
                                        uint32_t /* Out */ NReadPtr) {
1465
  // Alignment checks
1466
0
  if (unlikely(isMisaligned<__wasi_size_t>(NReadPtr))) {
1467
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1468
0
  }
1469
  // BufPtr and PathPtr should be aligned to at least 1 byte (which is always
1470
  // true)
1471
1472
  // Check memory instance from module.
1473
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1474
0
  if (MemInst == nullptr) {
1475
0
    return __WASI_ERRNO_FAULT;
1476
0
  }
1477
1478
0
  const __wasi_size_t WasiPathLen = PathLen;
1479
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1480
0
  if (unlikely(Path.size() != WasiPathLen)) {
1481
0
    return __WASI_ERRNO_FAULT;
1482
0
  }
1483
1484
0
  const __wasi_size_t WasiBufLen = BufLen;
1485
1486
0
  const auto Buf = MemInst->getSpan<char>(BufPtr, WasiBufLen);
1487
0
  if (unlikely(Buf.size() != WasiBufLen)) {
1488
0
    return __WASI_ERRNO_FAULT;
1489
0
  }
1490
1491
0
  auto *const NRead = MemInst->getPointer<__wasi_size_t *>(NReadPtr);
1492
0
  if (unlikely(NRead == nullptr)) {
1493
0
    return __WASI_ERRNO_FAULT;
1494
0
  }
1495
1496
0
  const __wasi_fd_t WasiFd = Fd;
1497
1498
0
  if (auto Res = Env.pathReadlink(WasiFd, Path, Buf, *NRead); unlikely(!Res)) {
1499
0
    return Res.error();
1500
0
  }
1501
0
  return __WASI_ERRNO_SUCCESS;
1502
0
}
1503
1504
Expect<uint32_t>
1505
WasiPathRemoveDirectory::body(const Runtime::CallingFrame &Frame, int32_t Fd,
1506
0
                              uint32_t PathPtr, uint32_t PathLen) {
1507
  // Alignment checks
1508
  // PathPtr should be aligned to at least 1 byte (which is always true)
1509
1510
  // Check memory instance from module.
1511
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1512
0
  if (MemInst == nullptr) {
1513
0
    return __WASI_ERRNO_FAULT;
1514
0
  }
1515
1516
0
  const __wasi_size_t WasiPathLen = PathLen;
1517
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1518
0
  if (unlikely(Path.size() != WasiPathLen)) {
1519
0
    return __WASI_ERRNO_FAULT;
1520
0
  }
1521
1522
0
  const __wasi_fd_t WasiFd = Fd;
1523
1524
0
  if (auto Res = Env.pathRemoveDirectory(WasiFd, Path); unlikely(!Res)) {
1525
0
    return Res.error();
1526
0
  }
1527
0
  return __WASI_ERRNO_SUCCESS;
1528
0
}
1529
1530
Expect<uint32_t> WasiPathRename::body(const Runtime::CallingFrame &Frame,
1531
                                      int32_t Fd, uint32_t OldPathPtr,
1532
                                      uint32_t OldPathLen, int32_t NewFd,
1533
                                      uint32_t NewPathPtr,
1534
0
                                      uint32_t NewPathLen) {
1535
  // Alignment checks
1536
  // OldPathPtr and NewPathPtr should be aligned to at least 1 byte (which is
1537
  // always true).
1538
1539
  // Check memory instance from module.
1540
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1541
0
  if (MemInst == nullptr) {
1542
0
    return __WASI_ERRNO_FAULT;
1543
0
  }
1544
1545
0
  const __wasi_size_t WasiOldPathLen = OldPathLen;
1546
0
  const auto OldPath = MemInst->getStringView(OldPathPtr, WasiOldPathLen);
1547
0
  if (unlikely(OldPath.size() != WasiOldPathLen)) {
1548
0
    return __WASI_ERRNO_FAULT;
1549
0
  }
1550
1551
0
  const __wasi_size_t WasiNewPathLen = NewPathLen;
1552
0
  const auto NewPath = MemInst->getStringView(NewPathPtr, WasiNewPathLen);
1553
0
  if (unlikely(NewPath.size() != WasiNewPathLen)) {
1554
0
    return __WASI_ERRNO_FAULT;
1555
0
  }
1556
1557
0
  const __wasi_fd_t WasiFd = Fd;
1558
0
  const __wasi_fd_t WasiNewFd = NewFd;
1559
1560
0
  if (auto Res = Env.pathRename(WasiFd, OldPath, WasiNewFd, NewPath);
1561
0
      unlikely(!Res)) {
1562
0
    return Res.error();
1563
0
  }
1564
0
  return __WASI_ERRNO_SUCCESS;
1565
0
}
1566
1567
Expect<uint32_t> WasiPathSymlink::body(const Runtime::CallingFrame &Frame,
1568
                                       uint32_t OldPathPtr, uint32_t OldPathLen,
1569
                                       int32_t Fd, uint32_t NewPathPtr,
1570
0
                                       uint32_t NewPathLen) {
1571
  // Alignment checks
1572
  // OldPathPtr and NewPathPtr should be aligned to at least 1 byte (which is
1573
  // always true)
1574
1575
  // Check memory instance from module.
1576
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1577
0
  if (MemInst == nullptr) {
1578
0
    return __WASI_ERRNO_FAULT;
1579
0
  }
1580
1581
0
  const __wasi_size_t WasiOldPathLen = OldPathLen;
1582
0
  const auto OldPath = MemInst->getStringView(OldPathPtr, WasiOldPathLen);
1583
0
  if (unlikely(OldPath.size() != WasiOldPathLen)) {
1584
0
    return __WASI_ERRNO_FAULT;
1585
0
  }
1586
1587
0
  const __wasi_size_t WasiNewPathLen = NewPathLen;
1588
0
  const auto NewPath = MemInst->getStringView(NewPathPtr, WasiNewPathLen);
1589
0
  if (unlikely(NewPath.size() != WasiNewPathLen)) {
1590
0
    return __WASI_ERRNO_FAULT;
1591
0
  }
1592
1593
0
  if (OldPath.empty() || NewPath.empty()) {
1594
0
    return __WASI_ERRNO_NOENT;
1595
0
  }
1596
1597
0
  const __wasi_fd_t WasiFd = Fd;
1598
1599
0
  if (auto Res = Env.pathSymlink(OldPath, WasiFd, NewPath); unlikely(!Res)) {
1600
0
    return Res.error();
1601
0
  }
1602
0
  return __WASI_ERRNO_SUCCESS;
1603
0
}
1604
1605
Expect<uint32_t> WasiPathUnlinkFile::body(const Runtime::CallingFrame &Frame,
1606
                                          int32_t Fd, uint32_t PathPtr,
1607
0
                                          uint32_t PathLen) {
1608
  // Alignment checks
1609
  // PathPtr should be aligned to at least 1 byte (which is always true)
1610
1611
  // Check memory instance from module.
1612
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1613
0
  if (MemInst == nullptr) {
1614
0
    return __WASI_ERRNO_FAULT;
1615
0
  }
1616
1617
0
  const __wasi_size_t WasiPathLen = PathLen;
1618
0
  const auto Path = MemInst->getStringView(PathPtr, WasiPathLen);
1619
0
  if (unlikely(Path.size() != WasiPathLen)) {
1620
0
    return __WASI_ERRNO_FAULT;
1621
0
  }
1622
1623
0
  const __wasi_fd_t WasiFd = Fd;
1624
1625
0
  if (auto Res = Env.pathUnlinkFile(WasiFd, Path); unlikely(!Res)) {
1626
0
    return Res.error();
1627
0
  }
1628
0
  return __WASI_ERRNO_SUCCESS;
1629
0
}
1630
template <WASI::TriggerType Trigger>
1631
Expect<uint32_t> WasiPollOneoff<Trigger>::body(
1632
    const Runtime::CallingFrame &Frame, uint32_t InPtr, uint32_t OutPtr,
1633
0
    uint32_t NSubscriptions, uint32_t /* Out */ NEventsPtr) {
1634
  // Alignment checks
1635
0
  if (unlikely(isMisaligned<__wasi_subscription_t>(InPtr))) {
1636
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1637
0
  }
1638
0
  if (unlikely(isMisaligned<__wasi_event_t>(OutPtr))) {
1639
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1640
0
  }
1641
0
  if (unlikely(isMisaligned<__wasi_size_t>(NEventsPtr))) {
1642
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1643
0
  }
1644
  // Check memory instance from module.
1645
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1646
0
  if (MemInst == nullptr) {
1647
0
    return __WASI_ERRNO_FAULT;
1648
0
  }
1649
1650
0
  const EndianValue<__wasi_size_t> WasiNSub = NSubscriptions;
1651
1652
0
  const auto Subs =
1653
0
      MemInst->getSpan<const __wasi_subscription_t>(InPtr, WasiNSub.raw());
1654
0
  if (unlikely(Subs.size() != WasiNSub.raw())) {
1655
0
    return __WASI_ERRNO_FAULT;
1656
0
  }
1657
1658
0
  const auto Events = MemInst->getSpan<__wasi_event_t>(OutPtr, WasiNSub.raw());
1659
0
  if (unlikely(Events.size() != WasiNSub.raw())) {
1660
0
    return __WASI_ERRNO_FAULT;
1661
0
  }
1662
1663
0
  auto *const NEvents = MemInst->getPointer<__wasi_size_t *>(NEventsPtr);
1664
0
  if (unlikely(NEvents == nullptr)) {
1665
0
    return __WASI_ERRNO_FAULT;
1666
0
  }
1667
1668
  // Validate contents
1669
0
  if (auto Poll = this->Env.acquirePoller(Events); unlikely(!Poll)) {
1670
0
    for (__wasi_size_t I = 0; I < WasiNSub.raw(); ++I) {
1671
0
      Events[I].userdata = Subs[I].userdata;
1672
0
      Events[I].error = Poll.error();
1673
0
      Events[I].type = Subs[I].u.tag;
1674
0
    }
1675
0
    *NEvents = WasiNSub.le();
1676
0
    return Poll.error();
1677
0
  } else {
1678
0
    auto &Poller = *Poll;
1679
0
    for (auto &Sub : Subs) {
1680
0
      const EndianValue<__wasi_userdata_t> WasiUserData = Sub.userdata;
1681
1682
0
      __wasi_eventtype_t Type;
1683
0
      if (auto Res = cast<__wasi_eventtype_t>(Sub.u.tag); unlikely(!Res)) {
1684
0
        Poller.error(WasiUserData.le(), Res.error(), Sub.u.tag);
1685
0
        continue;
1686
0
      } else {
1687
0
        Type = *Res;
1688
0
      }
1689
1690
0
      switch (Type) {
1691
0
      case __WASI_EVENTTYPE_CLOCK: {
1692
0
        __wasi_clockid_t WasiClockId;
1693
0
        if (auto Res =
1694
0
                cast<__wasi_clockid_t>(EndianValue(Sub.u.u.clock.id).le());
1695
0
            unlikely(!Res)) {
1696
0
          Poller.error(WasiUserData.le(), Res.error(), Type);
1697
0
          continue;
1698
0
        } else {
1699
0
          WasiClockId = *Res;
1700
0
        }
1701
1702
0
        __wasi_subclockflags_t WasiFlags;
1703
0
        if (auto Res = cast<__wasi_subclockflags_t>(
1704
0
                EndianValue(Sub.u.u.clock.flags).le());
1705
0
            unlikely(!Res)) {
1706
0
          Poller.error(WasiUserData.le(), Res.error(), Type);
1707
0
          continue;
1708
0
        } else {
1709
0
          WasiFlags = *Res;
1710
0
        }
1711
1712
0
        const EndianValue<__wasi_timestamp_t> WasiTimeout =
1713
0
            Sub.u.u.clock.timeout;
1714
0
        const EndianValue<__wasi_timestamp_t> WasiPrecision =
1715
0
            Sub.u.u.clock.precision;
1716
1717
0
        Poller.clock(WasiClockId, WasiTimeout.le(), WasiPrecision.le(),
1718
0
                     WasiFlags, WasiUserData.le());
1719
0
        continue;
1720
0
      }
1721
0
      case __WASI_EVENTTYPE_FD_READ: {
1722
0
        const EndianValue<__wasi_fd_t> WasiFd = Sub.u.u.fd_read.file_descriptor;
1723
0
        Poller.read(WasiFd.le(), Trigger, WasiUserData.le());
1724
0
        continue;
1725
0
      }
1726
0
      case __WASI_EVENTTYPE_FD_WRITE: {
1727
0
        const EndianValue<__wasi_fd_t> WasiFd =
1728
0
            Sub.u.u.fd_write.file_descriptor;
1729
0
        Poller.write(WasiFd.le(), Trigger, WasiUserData.le());
1730
0
        continue;
1731
0
      }
1732
0
      default:
1733
0
        assumingUnreachable();
1734
0
      }
1735
0
    }
1736
0
    Poller.wait();
1737
0
    *NEvents = EndianValue<__wasi_size_t>(Poller.result()).le();
1738
0
    Poller.reset();
1739
0
    this->Env.releasePoller(std::move(Poller));
1740
0
  }
1741
1742
0
  return __WASI_ERRNO_SUCCESS;
1743
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)
1744
1745
template class WasiPollOneoff<WASI::TriggerType::Level>;
1746
template class WasiPollOneoff<WASI::TriggerType::Edge>;
1747
1748
Expect<void> WasiProcExit::body(const Runtime::CallingFrame &,
1749
0
                                uint32_t ExitCode) {
1750
0
  Env.procExit(ExitCode);
1751
0
  return Unexpect(ErrCode::Value::Terminated);
1752
0
}
1753
1754
Expect<uint32_t> WasiProcRaise::body(const Runtime::CallingFrame &,
1755
0
                                     uint32_t Signal) {
1756
0
  __wasi_signal_t WasiSignal;
1757
0
  if (auto Res = cast<__wasi_signal_t>(Signal); unlikely(!Res)) {
1758
0
    return Res.error();
1759
0
  } else {
1760
0
    WasiSignal = *Res;
1761
0
  }
1762
1763
0
  if (auto Res = Env.procRaise(WasiSignal); unlikely(!Res)) {
1764
0
    return Res.error();
1765
0
  }
1766
0
  return __WASI_ERRNO_SUCCESS;
1767
0
}
1768
1769
0
Expect<uint32_t> WasiSchedYield::body(const Runtime::CallingFrame &) {
1770
0
  if (auto Res = Env.schedYield(); unlikely(!Res)) {
1771
0
    return Res.error();
1772
0
  }
1773
0
  return __WASI_ERRNO_SUCCESS;
1774
0
}
1775
1776
Expect<uint32_t> WasiRandomGet::body(const Runtime::CallingFrame &Frame,
1777
0
                                     uint32_t BufPtr, uint32_t BufLen) {
1778
  // Alignment checks
1779
  // BufPtr should be aligned to at least 1 byte (which is always true)
1780
1781
  // Check memory instance from module.
1782
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1783
0
  if (MemInst == nullptr) {
1784
0
    return __WASI_ERRNO_FAULT;
1785
0
  }
1786
1787
0
  const __wasi_size_t WasiBufLen = BufLen;
1788
1789
0
  const auto Buf = MemInst->getSpan<uint8_t>(BufPtr, WasiBufLen);
1790
0
  if (unlikely(Buf.size() != WasiBufLen)) {
1791
0
    return __WASI_ERRNO_FAULT;
1792
0
  }
1793
1794
0
  if (auto Res = Env.randomGet(Buf); unlikely(!Res)) {
1795
0
    return Res.error();
1796
0
  }
1797
0
  return __WASI_ERRNO_SUCCESS;
1798
0
}
1799
1800
Expect<uint32_t> WasiSockOpenV1::body(const Runtime::CallingFrame &Frame,
1801
                                      uint32_t AddressFamily, uint32_t SockType,
1802
0
                                      uint32_t /* Out */ RoFdPtr) {
1803
  // Alignment checks
1804
0
  if (unlikely(isMisaligned<__wasi_fd_t>(RoFdPtr))) {
1805
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1806
0
  }
1807
1808
  // Check memory instance from module.
1809
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1810
0
  if (MemInst == nullptr) {
1811
0
    return __WASI_ERRNO_FAULT;
1812
0
  }
1813
1814
0
  __wasi_fd_t *const RoFd = MemInst->getPointer<__wasi_fd_t *>(RoFdPtr);
1815
0
  if (RoFd == nullptr) {
1816
0
    return __WASI_ERRNO_FAULT;
1817
0
  }
1818
1819
0
  __wasi_address_family_t WasiAddressFamily;
1820
0
  if (auto Res = cast<__wasi_address_family_t>(AddressFamily); unlikely(!Res)) {
1821
0
    return Res.error();
1822
0
  } else {
1823
0
    WasiAddressFamily = *Res;
1824
0
  }
1825
1826
0
  if (!AllowAFUNIX(Frame, WasiAddressFamily)) {
1827
0
    return __WASI_ERRNO_NOSYS;
1828
0
  }
1829
1830
0
  __wasi_sock_type_t WasiSockType;
1831
0
  if (auto Res = cast<__wasi_sock_type_t>(SockType); unlikely(!Res)) {
1832
0
    return Res.error();
1833
0
  } else {
1834
0
    WasiSockType = *Res;
1835
0
  }
1836
1837
0
  if (auto Res = Env.sockOpen(WasiAddressFamily, WasiSockType);
1838
0
      unlikely(!Res)) {
1839
0
    return Res.error();
1840
0
  } else {
1841
0
    *RoFd = EndianValue(*Res).le();
1842
0
  }
1843
1844
0
  return __WASI_ERRNO_SUCCESS;
1845
0
}
1846
1847
Expect<uint32_t> WasiSockBindV1::body(const Runtime::CallingFrame &Frame,
1848
                                      int32_t Fd, uint32_t AddressPtr,
1849
0
                                      uint32_t Port) {
1850
  // Alignment checks
1851
0
  if (unlikely(isMisaligned<__wasi_address_t>(AddressPtr))) {
1852
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1853
0
  }
1854
1855
  // Check memory instance from module.
1856
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1857
0
  if (MemInst == nullptr) {
1858
0
    return __WASI_ERRNO_FAULT;
1859
0
  }
1860
0
  __wasi_address_t *InnerAddress =
1861
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
1862
0
  if (InnerAddress == nullptr) {
1863
0
    return __WASI_ERRNO_FAULT;
1864
0
  }
1865
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
1866
0
  const auto Address = MemInst->getSpan<const uint8_t>(
1867
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
1868
0
  if (Address.size() != InnerAddressBufLen) {
1869
0
    return __WASI_ERRNO_FAULT;
1870
0
  }
1871
1872
0
  __wasi_address_family_t WasiAddressFamily;
1873
0
  switch (Address.size()) {
1874
0
  case 4:
1875
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET4;
1876
0
    break;
1877
0
  case 16:
1878
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET6;
1879
0
    break;
1880
0
  default:
1881
0
    return __WASI_ERRNO_INVAL;
1882
0
  }
1883
1884
0
  const __wasi_fd_t WasiFd = Fd;
1885
1886
0
  if (auto Res = Env.sockBind(WasiFd, WasiAddressFamily, Address,
1887
0
                              static_cast<uint16_t>(Port));
1888
0
      unlikely(!Res)) {
1889
0
    return Res.error();
1890
0
  }
1891
0
  return __WASI_ERRNO_SUCCESS;
1892
0
}
1893
1894
Expect<uint32_t> WasiSockListenV1::body(const Runtime::CallingFrame &,
1895
0
                                        int32_t Fd, int32_t Backlog) {
1896
0
  const __wasi_fd_t WasiFd = Fd;
1897
0
  if (auto Res = Env.sockListen(WasiFd, Backlog); unlikely(!Res)) {
1898
0
    return Res.error();
1899
0
  }
1900
0
  return __WASI_ERRNO_SUCCESS;
1901
0
}
1902
1903
Expect<uint32_t> WasiSockAcceptV1::body(const Runtime::CallingFrame &Frame,
1904
                                        int32_t Fd,
1905
0
                                        uint32_t /* Out */ RoFdPtr) {
1906
  // Alignment checks
1907
0
  if (unlikely(isMisaligned<__wasi_fd_t>(RoFdPtr))) {
1908
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1909
0
  }
1910
1911
  // Check memory instance from module.
1912
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1913
0
  if (MemInst == nullptr) {
1914
0
    return __WASI_ERRNO_FAULT;
1915
0
  }
1916
0
  __wasi_fd_t *const RoFd = MemInst->getPointer<__wasi_fd_t *>(RoFdPtr);
1917
0
  if (RoFd == nullptr) {
1918
0
    return __WASI_ERRNO_FAULT;
1919
0
  }
1920
0
  const __wasi_fd_t WasiFd = Fd;
1921
0
  const __wasi_fdflags_t WasiFdFlags = static_cast<__wasi_fdflags_t>(0);
1922
0
  if (auto Res = Env.sockAccept(WasiFd, WasiFdFlags); unlikely(!Res)) {
1923
0
    return Res.error();
1924
0
  } else {
1925
0
    *RoFd = EndianValue(*Res).le();
1926
0
  }
1927
1928
0
  return __WASI_ERRNO_SUCCESS;
1929
0
}
1930
1931
Expect<uint32_t> WasiSockAcceptV2::body(const Runtime::CallingFrame &Frame,
1932
                                        int32_t Fd, uint32_t FsFlags,
1933
0
                                        uint32_t /* Out */ RoFdPtr) {
1934
  // Alignment checks
1935
0
  if (unlikely(isMisaligned<__wasi_fd_t>(RoFdPtr))) {
1936
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1937
0
  }
1938
1939
  // Check memory instance from module.
1940
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1941
0
  if (MemInst == nullptr) {
1942
0
    return __WASI_ERRNO_FAULT;
1943
0
  }
1944
0
  __wasi_fd_t *const RoFd = MemInst->getPointer<__wasi_fd_t *>(RoFdPtr);
1945
0
  if (RoFd == nullptr) {
1946
0
    return __WASI_ERRNO_FAULT;
1947
0
  }
1948
0
  const __wasi_fd_t WasiFd = Fd;
1949
1950
0
  __wasi_fdflags_t WasiFdFlags;
1951
0
  if (auto Res = cast<__wasi_fdflags_t>(FsFlags); unlikely(!Res)) {
1952
0
    return Res.error();
1953
0
  } else {
1954
0
    WasiFdFlags = *Res;
1955
0
  }
1956
1957
0
  if (auto Res = Env.sockAccept(WasiFd, WasiFdFlags); unlikely(!Res)) {
1958
0
    return Res.error();
1959
0
  } else {
1960
0
    *RoFd = EndianValue(*Res).le();
1961
0
  }
1962
1963
0
  return __WASI_ERRNO_SUCCESS;
1964
0
}
1965
1966
Expect<uint32_t> WasiSockConnectV1::body(const Runtime::CallingFrame &Frame,
1967
                                         int32_t Fd, uint32_t AddressPtr,
1968
0
                                         uint32_t Port) {
1969
  // Alignment checks
1970
0
  if (unlikely(isMisaligned<__wasi_address_t>(AddressPtr))) {
1971
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
1972
0
  }
1973
  // Check memory instance from module.
1974
0
  auto *MemInst = Frame.getMemoryByIndex(0);
1975
0
  if (MemInst == nullptr) {
1976
0
    return __WASI_ERRNO_FAULT;
1977
0
  }
1978
0
  __wasi_address_t *InnerAddress =
1979
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
1980
0
  if (InnerAddress == nullptr) {
1981
0
    return __WASI_ERRNO_FAULT;
1982
0
  }
1983
1984
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
1985
0
  const auto Address = MemInst->getSpan<uint8_t>(
1986
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
1987
0
  if (Address.size() != InnerAddressBufLen) {
1988
0
    return __WASI_ERRNO_FAULT;
1989
0
  }
1990
1991
0
  __wasi_address_family_t WasiAddressFamily;
1992
0
  switch (Address.size()) {
1993
0
  case 4:
1994
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET4;
1995
0
    break;
1996
0
  case 16:
1997
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET6;
1998
0
    break;
1999
0
  default:
2000
0
    return __WASI_ERRNO_INVAL;
2001
0
  }
2002
2003
0
  const __wasi_fd_t WasiFd = Fd;
2004
0
  if (auto Res = Env.sockConnect(WasiFd, WasiAddressFamily, Address,
2005
0
                                 static_cast<uint16_t>(Port));
2006
0
      unlikely(!Res)) {
2007
0
    return Res.error();
2008
0
  }
2009
2010
0
  return __WASI_ERRNO_SUCCESS;
2011
0
}
2012
2013
Expect<uint32_t> WasiSockRecvV1::body(const Runtime::CallingFrame &Frame,
2014
                                      int32_t Fd, uint32_t RiDataPtr,
2015
                                      uint32_t RiDataLen, uint32_t RiFlags,
2016
                                      uint32_t /* Out */ RoDataLenPtr,
2017
0
                                      uint32_t /* Out */ RoFlagsPtr) {
2018
  // Alignment checks
2019
0
  if (unlikely(isMisaligned<__wasi_iovec_t>(RiDataPtr))) {
2020
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2021
0
  }
2022
2023
0
  if (unlikely(isMisaligned<__wasi_size_t>(RoDataLenPtr))) {
2024
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2025
0
  }
2026
2027
0
  if (unlikely(isMisaligned<__wasi_roflags_t>(RoFlagsPtr))) {
2028
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2029
0
  }
2030
2031
  // Check memory instance from module.
2032
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2033
0
  if (MemInst == nullptr) {
2034
0
    return __WASI_ERRNO_FAULT;
2035
0
  }
2036
2037
0
  __wasi_riflags_t WasiRiFlags;
2038
0
  if (auto Res = cast<__wasi_riflags_t>(RiFlags); unlikely(!Res)) {
2039
0
    return Res.error();
2040
0
  } else {
2041
0
    WasiRiFlags = EndianValue(*Res).le();
2042
0
  }
2043
2044
0
  const __wasi_size_t WasiRiDataLen = RiDataLen;
2045
0
  if (unlikely(WasiRiDataLen > WASI::kIOVMax)) {
2046
0
    return __WASI_ERRNO_INVAL;
2047
0
  }
2048
2049
  // Check for invalid address.
2050
0
  const auto RiDataArray =
2051
0
      MemInst->getSpan<__wasi_iovec_t>(RiDataPtr, WasiRiDataLen);
2052
0
  if (unlikely(RiDataArray.size() != WasiRiDataLen)) {
2053
0
    return __WASI_ERRNO_FAULT;
2054
0
  }
2055
2056
0
  auto *const RoDataLen = MemInst->getPointer<__wasi_size_t *>(RoDataLenPtr);
2057
0
  if (unlikely(RoDataLen == nullptr)) {
2058
0
    return __WASI_ERRNO_FAULT;
2059
0
  }
2060
2061
0
  auto *const RoFlags = MemInst->getPointer<__wasi_roflags_t *>(RoFlagsPtr);
2062
0
  if (unlikely(RoFlags == nullptr)) {
2063
0
    return __WASI_ERRNO_FAULT;
2064
0
  }
2065
0
  __wasi_size_t TotalSize = 0;
2066
0
  StaticVector<Span<uint8_t>, WASI::kIOVMax> WasiRiData;
2067
2068
0
  for (auto &RiData : RiDataArray) {
2069
    // Capping total size.
2070
0
    const __wasi_size_t Space =
2071
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
2072
0
    const uint32_t RiDataBufLen = EndianValue(RiData.buf_len).le();
2073
0
    const __wasi_size_t BufLen =
2074
0
        unlikely(RiDataBufLen > Space) ? Space : RiDataBufLen;
2075
0
    TotalSize += BufLen;
2076
2077
    // Check for invalid address.
2078
0
    const auto RiDataArr =
2079
0
        MemInst->getSpan<uint8_t>(EndianValue(RiData.buf).le(), BufLen);
2080
    // Check for invalid address.
2081
0
    if (unlikely(RiDataArr.size() != BufLen)) {
2082
0
      return __WASI_ERRNO_FAULT;
2083
0
    }
2084
0
    WasiRiData.emplace_back_unchecked(RiDataArr);
2085
0
  }
2086
2087
0
  const __wasi_fd_t WasiFd = Fd;
2088
2089
0
  if (auto Res =
2090
0
          Env.sockRecv(WasiFd, WasiRiData, WasiRiFlags, *RoDataLen, *RoFlags);
2091
0
      unlikely(!Res)) {
2092
0
    return Res.error();
2093
0
  }
2094
2095
0
  return __WASI_ERRNO_SUCCESS;
2096
0
}
2097
2098
Expect<uint32_t> WasiSockRecvFromV1::body(const Runtime::CallingFrame &Frame,
2099
                                          int32_t Fd, uint32_t RiDataPtr,
2100
                                          uint32_t RiDataLen,
2101
                                          uint32_t AddressPtr, uint32_t RiFlags,
2102
                                          uint32_t /* Out */ RoDataLenPtr,
2103
0
                                          uint32_t /* Out */ RoFlagsPtr) {
2104
  // Alignment checks
2105
0
  if (unlikely(isMisaligned<__wasi_address_t>(AddressPtr))) {
2106
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2107
0
  }
2108
2109
0
  if (unlikely(isMisaligned<__wasi_iovec_t>(RiDataPtr))) {
2110
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2111
0
  }
2112
2113
0
  if (unlikely(isMisaligned<__wasi_size_t>(RoDataLenPtr))) {
2114
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2115
0
  }
2116
2117
0
  if (unlikely(isMisaligned<__wasi_roflags_t>(RoFlagsPtr))) {
2118
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2119
0
  }
2120
2121
  // Check memory instance from module.
2122
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2123
0
  if (MemInst == nullptr) {
2124
0
    return __WASI_ERRNO_FAULT;
2125
0
  }
2126
2127
0
  __wasi_address_t *InnerAddress =
2128
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
2129
0
  if (InnerAddress == nullptr) {
2130
0
    return __WASI_ERRNO_FAULT;
2131
0
  }
2132
2133
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
2134
0
  const auto Address = MemInst->getSpan<uint8_t>(
2135
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
2136
0
  if (Address.size() != InnerAddressBufLen) {
2137
0
    return __WASI_ERRNO_FAULT;
2138
0
  }
2139
2140
0
  __wasi_riflags_t WasiRiFlags;
2141
0
  if (auto Res = cast<__wasi_riflags_t>(RiFlags); unlikely(!Res)) {
2142
0
    return Res.error();
2143
0
  } else {
2144
0
    WasiRiFlags = *Res;
2145
0
  }
2146
2147
0
  const __wasi_size_t WasiRiDataLen = RiDataLen;
2148
0
  if (unlikely(WasiRiDataLen > WASI::kIOVMax)) {
2149
0
    return __WASI_ERRNO_INVAL;
2150
0
  }
2151
2152
0
  const auto RiDataArray =
2153
0
      MemInst->getSpan<__wasi_iovec_t>(RiDataPtr, WasiRiDataLen);
2154
0
  if (unlikely(RiDataArray.size() != WasiRiDataLen)) {
2155
0
    return __WASI_ERRNO_FAULT;
2156
0
  }
2157
2158
0
  auto *const RoDataLen = MemInst->getPointer<__wasi_size_t *>(RoDataLenPtr);
2159
0
  if (unlikely(RoDataLen == nullptr)) {
2160
0
    return __WASI_ERRNO_FAULT;
2161
0
  }
2162
2163
0
  auto *const RoFlags = MemInst->getPointer<__wasi_roflags_t *>(RoFlagsPtr);
2164
0
  if (unlikely(RoFlags == nullptr)) {
2165
0
    return __WASI_ERRNO_FAULT;
2166
0
  }
2167
0
  __wasi_size_t TotalSize = 0;
2168
0
  StaticVector<Span<uint8_t>, WASI::kIOVMax> WasiRiData;
2169
0
  for (auto &RiData : RiDataArray) {
2170
    // Capping total size.
2171
0
    const __wasi_size_t Space =
2172
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
2173
0
    const uint32_t RiDataBufLen = EndianValue(RiData.buf_len).le();
2174
0
    const __wasi_size_t BufLen =
2175
0
        unlikely(RiDataBufLen > Space) ? Space : RiDataBufLen;
2176
2177
    // Check for invalid address.
2178
0
    const auto RiDataArr =
2179
0
        MemInst->getSpan<uint8_t>(EndianValue(RiData.buf).le(), BufLen);
2180
    // Check for invalid address.
2181
0
    if (unlikely(RiDataArr.size() != BufLen)) {
2182
0
      return __WASI_ERRNO_FAULT;
2183
0
    }
2184
0
    WasiRiData.emplace_back_unchecked(RiDataArr);
2185
0
  }
2186
2187
0
  const __wasi_fd_t WasiFd = Fd;
2188
2189
0
  if (auto Res = Env.sockRecvFrom(WasiFd, WasiRiData, WasiRiFlags, nullptr,
2190
0
                                  Address, nullptr, *RoDataLen, *RoFlags);
2191
0
      unlikely(!Res)) {
2192
0
    return Res.error();
2193
0
  }
2194
2195
0
  return __WASI_ERRNO_SUCCESS;
2196
0
}
2197
2198
Expect<uint32_t> WasiSockSendV1::body(const Runtime::CallingFrame &Frame,
2199
                                      int32_t Fd, uint32_t SiDataPtr,
2200
                                      uint32_t SiDataLen, uint32_t SiFlags,
2201
0
                                      uint32_t /* Out */ SoDataLenPtr) {
2202
  // Alignment checks
2203
0
  if (unlikely(isMisaligned<__wasi_ciovec_t>(SiDataPtr))) {
2204
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2205
0
  }
2206
2207
0
  if (unlikely(isMisaligned<__wasi_size_t>(SoDataLenPtr))) {
2208
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2209
0
  }
2210
2211
  // Check memory instance from module.
2212
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2213
0
  if (MemInst == nullptr) {
2214
0
    return __WASI_ERRNO_FAULT;
2215
0
  }
2216
2217
0
  __wasi_siflags_t WasiSiFlags;
2218
0
  if (auto Res = cast<__wasi_siflags_t>(SiFlags); unlikely(!Res)) {
2219
0
    return Res.error();
2220
0
  } else {
2221
0
    WasiSiFlags = *Res;
2222
0
  }
2223
2224
0
  const __wasi_size_t WasiSiDataLen = SiDataLen;
2225
0
  if (unlikely(WasiSiDataLen > WASI::kIOVMax)) {
2226
0
    return __WASI_ERRNO_INVAL;
2227
0
  }
2228
2229
  // Check for invalid address.
2230
0
  const auto SiDataArray =
2231
0
      MemInst->getSpan<__wasi_ciovec_t>(SiDataPtr, WasiSiDataLen);
2232
0
  if (unlikely(SiDataArray.size() != WasiSiDataLen)) {
2233
0
    return __WASI_ERRNO_FAULT;
2234
0
  }
2235
2236
0
  auto *const SoDataLen = MemInst->getPointer<__wasi_size_t *>(SoDataLenPtr);
2237
0
  if (unlikely(SoDataLen == nullptr)) {
2238
0
    return __WASI_ERRNO_FAULT;
2239
0
  }
2240
2241
0
  __wasi_size_t TotalSize = 0;
2242
0
  StaticVector<Span<const uint8_t>, WASI::kIOVMax> WasiSiData;
2243
2244
0
  for (auto &SiData : SiDataArray) {
2245
    // Capping total size.
2246
0
    const __wasi_size_t Space =
2247
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
2248
0
    const uint32_t SiDataBufLen = EndianValue(SiData.buf_len).le();
2249
0
    const __wasi_size_t BufLen =
2250
0
        unlikely(SiDataBufLen > Space) ? Space : SiDataBufLen;
2251
0
    TotalSize += BufLen;
2252
2253
    // Check for invalid address.
2254
0
    const auto SiDataArr =
2255
0
        MemInst->getSpan<uint8_t>(EndianValue(SiData.buf).le(), BufLen);
2256
0
    if (unlikely(SiDataArr.size() != BufLen)) {
2257
0
      return __WASI_ERRNO_FAULT;
2258
0
    }
2259
0
    WasiSiData.emplace_back_unchecked(SiDataArr);
2260
0
  }
2261
2262
0
  const __wasi_fd_t WasiFd = Fd;
2263
2264
0
  if (auto Res = Env.sockSend(WasiFd, WasiSiData, WasiSiFlags, *SoDataLen);
2265
0
      unlikely(!Res)) {
2266
0
    return Res.error();
2267
0
  }
2268
0
  return __WASI_ERRNO_SUCCESS;
2269
0
}
2270
2271
Expect<uint32_t> WasiSockSendToV1::body(const Runtime::CallingFrame &Frame,
2272
                                        int32_t Fd, uint32_t SiDataPtr,
2273
                                        uint32_t SiDataLen, uint32_t AddressPtr,
2274
                                        int32_t Port, uint32_t SiFlags,
2275
0
                                        uint32_t /* Out */ SoDataLenPtr) {
2276
  // Alignment checks
2277
0
  if (unlikely(isMisaligned<__wasi_address_t>(AddressPtr))) {
2278
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2279
0
  }
2280
2281
0
  if (unlikely(isMisaligned<__wasi_ciovec_t>(SiDataPtr))) {
2282
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2283
0
  }
2284
2285
0
  if (unlikely(isMisaligned<__wasi_size_t>(SoDataLenPtr))) {
2286
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2287
0
  }
2288
2289
  // Check memory instance from module.
2290
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2291
0
  if (MemInst == nullptr) {
2292
0
    return __WASI_ERRNO_FAULT;
2293
0
  }
2294
2295
0
  __wasi_address_t *InnerAddress =
2296
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
2297
0
  if (InnerAddress == nullptr) {
2298
0
    return __WASI_ERRNO_FAULT;
2299
0
  }
2300
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
2301
0
  const auto Address = MemInst->getSpan<uint8_t>(
2302
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
2303
0
  if (Address.size() != InnerAddressBufLen) {
2304
0
    return __WASI_ERRNO_FAULT;
2305
0
  }
2306
2307
0
  __wasi_address_family_t WasiAddressFamily;
2308
0
  switch (Address.size()) {
2309
0
  case 4:
2310
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET4;
2311
0
    break;
2312
0
  case 16:
2313
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET6;
2314
0
    break;
2315
0
  default:
2316
0
    return __WASI_ERRNO_INVAL;
2317
0
  }
2318
2319
0
  __wasi_siflags_t WasiSiFlags;
2320
0
  if (auto Res = cast<__wasi_siflags_t>(SiFlags); unlikely(!Res)) {
2321
0
    return Res.error();
2322
0
  } else {
2323
0
    WasiSiFlags = *Res;
2324
0
  }
2325
2326
0
  const __wasi_size_t WasiSiDataLen = SiDataLen;
2327
0
  if (unlikely(WasiSiDataLen > WASI::kIOVMax)) {
2328
0
    return __WASI_ERRNO_INVAL;
2329
0
  }
2330
2331
  // Check for invalid address.
2332
0
  const auto SiDataArray =
2333
0
      MemInst->getSpan<__wasi_ciovec_t>(SiDataPtr, WasiSiDataLen);
2334
0
  if (unlikely(SiDataArray.size() != WasiSiDataLen)) {
2335
0
    return __WASI_ERRNO_FAULT;
2336
0
  }
2337
2338
0
  auto *const SoDataLen = MemInst->getPointer<__wasi_size_t *>(SoDataLenPtr);
2339
0
  if (unlikely(SoDataLen == nullptr)) {
2340
0
    return __WASI_ERRNO_FAULT;
2341
0
  }
2342
2343
0
  __wasi_size_t TotalSize = 0;
2344
0
  StaticVector<Span<const uint8_t>, WASI::kIOVMax> WasiSiData;
2345
2346
0
  for (auto &SiData : SiDataArray) {
2347
    // Capping total size.
2348
0
    const __wasi_size_t Space =
2349
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
2350
0
    const uint32_t SiDataBufLen = EndianValue(SiData.buf_len).le();
2351
0
    const __wasi_size_t BufLen =
2352
0
        unlikely(SiDataBufLen > Space) ? Space : SiDataBufLen;
2353
0
    TotalSize += BufLen;
2354
2355
    // Check for invalid address.
2356
0
    const auto SiDataArr =
2357
0
        MemInst->getSpan<uint8_t>(EndianValue(SiData.buf).le(), BufLen);
2358
0
    if (unlikely(SiDataArr.size() != BufLen)) {
2359
0
      return __WASI_ERRNO_FAULT;
2360
0
    }
2361
0
    WasiSiData.emplace_back_unchecked(SiDataArr);
2362
0
  }
2363
2364
0
  const __wasi_fd_t WasiFd = Fd;
2365
2366
0
  if (auto Res =
2367
0
          Env.sockSendTo(WasiFd, WasiSiData, WasiSiFlags, WasiAddressFamily,
2368
0
                         Address, static_cast<uint16_t>(Port), *SoDataLen);
2369
0
      unlikely(!Res)) {
2370
0
    return Res.error();
2371
0
  }
2372
2373
0
  return __WASI_ERRNO_SUCCESS;
2374
0
}
2375
2376
Expect<uint32_t> WasiSockShutdown::body(const Runtime::CallingFrame &,
2377
0
                                        int32_t Fd, uint32_t SdFlags) {
2378
0
  __wasi_sdflags_t WasiSdFlags;
2379
0
  if (auto Res = cast<__wasi_sdflags_t>(SdFlags); unlikely(!Res)) {
2380
0
    return Res.error();
2381
0
  } else {
2382
0
    WasiSdFlags = *Res;
2383
0
  }
2384
2385
0
  const __wasi_fd_t WasiFd = Fd;
2386
2387
0
  if (auto Res = Env.sockShutdown(WasiFd, WasiSdFlags); unlikely(!Res)) {
2388
0
    return Res.error();
2389
0
  }
2390
0
  return __WASI_ERRNO_SUCCESS;
2391
0
}
2392
2393
Expect<uint32_t> WasiSockSetOpt::body(const Runtime::CallingFrame &Frame,
2394
                                      int32_t Fd, uint32_t SockOptLevel,
2395
                                      uint32_t SockOptName, uint32_t FlagPtr,
2396
0
                                      uint32_t FlagSize) {
2397
  // Alignment checks
2398
  // FlagPtr should be aligned to at least 1 byte (which is always true)
2399
2400
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2401
0
  if (MemInst == nullptr) {
2402
0
    return __WASI_ERRNO_FAULT;
2403
0
  }
2404
2405
0
  __wasi_sock_opt_level_t WasiSockOptLevel;
2406
0
  if (auto Res = cast<__wasi_sock_opt_level_t>(SockOptLevel); unlikely(!Res)) {
2407
0
    return Res.error();
2408
0
  } else {
2409
0
    WasiSockOptLevel = *Res;
2410
0
  }
2411
2412
0
  __wasi_sock_opt_so_t WasiSockOptName;
2413
0
  if (auto Res = cast<__wasi_sock_opt_so_t>(SockOptName); unlikely(!Res)) {
2414
0
    return Res.error();
2415
0
  } else {
2416
0
    WasiSockOptName = *Res;
2417
0
  }
2418
2419
0
  const auto Flag = MemInst->getSpan<uint8_t>(FlagPtr, FlagSize);
2420
0
  if (Flag.size() != FlagSize) {
2421
0
    return __WASI_ERRNO_FAULT;
2422
0
  }
2423
2424
0
  const __wasi_fd_t WasiFd = Fd;
2425
2426
0
  if (auto Res =
2427
0
          Env.sockSetOpt(WasiFd, WasiSockOptLevel, WasiSockOptName, Flag);
2428
0
      unlikely(!Res)) {
2429
0
    return Res.error();
2430
0
  }
2431
2432
0
  return __WASI_ERRNO_SUCCESS;
2433
0
}
2434
2435
Expect<uint32_t> WasiSockGetAddrinfo::body(
2436
    const Runtime::CallingFrame &Frame, uint32_t NodePtr, uint32_t NodeLen,
2437
    uint32_t ServicePtr, uint32_t ServiceLen, uint32_t HintsPtr,
2438
0
    uint32_t ResPtr, uint32_t MaxResLength, uint32_t ResLengthPtr) {
2439
  // Alignment checks
2440
  // NodePtr, ServicePtr should be aligned to at least 1 byte (which is always
2441
  // true)
2442
2443
0
  if (unlikely(isMisaligned<__wasi_addrinfo_t>(HintsPtr))) {
2444
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2445
0
  }
2446
0
  if (unlikely(isMisaligned<uint8_t_ptr>(ResPtr))) {
2447
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2448
0
  }
2449
0
  if (unlikely(isMisaligned<__wasi_size_t>(ResLengthPtr))) {
2450
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2451
0
  }
2452
2453
  // Check memory instance from module.
2454
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2455
0
  if (MemInst == nullptr) {
2456
0
    return __WASI_ERRNO_FAULT;
2457
0
  }
2458
2459
0
  const auto Node = MemInst->getStringView(NodePtr, NodeLen);
2460
0
  if (Node.size() != NodeLen) {
2461
0
    return __WASI_ERRNO_FAULT;
2462
0
  }
2463
2464
0
  const auto Service = MemInst->getStringView(ServicePtr, ServiceLen);
2465
0
  if (Service.size() != ServiceLen) {
2466
0
    return __WASI_ERRNO_FAULT;
2467
0
  }
2468
2469
0
  auto *Hint = MemInst->getPointer<const __wasi_addrinfo_t *>(HintsPtr);
2470
0
  if (Hint == nullptr) {
2471
0
    return __WASI_ERRNO_FAULT;
2472
0
  }
2473
2474
0
  auto *const ResBuf = MemInst->getPointer<const uint8_t_ptr *>(ResPtr);
2475
0
  if (ResBuf == nullptr) {
2476
0
    return __WASI_ERRNO_FAULT;
2477
0
  }
2478
2479
0
  auto *const ResLength = MemInst->getPointer<__wasi_size_t *>(ResLengthPtr);
2480
0
  if (ResLength == nullptr) {
2481
0
    return __WASI_ERRNO_FAULT;
2482
0
  }
2483
2484
  // service and node can not be empty at the same time
2485
0
  if (Service.empty() && Node.empty()) {
2486
0
    return __WASI_ERRNO_AINONAME;
2487
0
  }
2488
2489
0
  if (MaxResLength < 1) {
2490
0
    return __WASI_ERRNO_AIMEMORY;
2491
0
  }
2492
2493
0
  if (Hint->ai_flags &
2494
0
      ~(__WASI_AIFLAGS_AI_PASSIVE | __WASI_AIFLAGS_AI_CANONNAME |
2495
0
        __WASI_AIFLAGS_AI_NUMERICHOST | __WASI_AIFLAGS_AI_NUMERICSERV |
2496
0
        __WASI_AIFLAGS_AI_ADDRCONFIG | __WASI_AIFLAGS_AI_V4MAPPED |
2497
0
        __WASI_AIFLAGS_AI_ALL)) {
2498
0
    return __WASI_ERRNO_AIBADFLAG;
2499
0
  }
2500
0
  if (Hint->ai_flags & __WASI_AIFLAGS_AI_CANONNAME && Node.empty()) {
2501
0
    return __WASI_ERRNO_AIBADFLAG;
2502
0
  }
2503
0
  switch (Hint->ai_family) {
2504
0
  case __WASI_ADDRESS_FAMILY_UNSPEC:
2505
0
  case __WASI_ADDRESS_FAMILY_INET4:
2506
0
  case __WASI_ADDRESS_FAMILY_INET6:
2507
0
    break;
2508
0
  default:
2509
0
    return __WASI_ERRNO_AIFAMILY;
2510
0
  }
2511
0
  switch (Hint->ai_protocol) {
2512
0
  case __WASI_PROTOCOL_IPPROTO_IP:
2513
0
  case __WASI_PROTOCOL_IPPROTO_TCP:
2514
0
  case __WASI_PROTOCOL_IPPROTO_UDP:
2515
0
    break;
2516
0
  default:
2517
0
    return __WASI_ERRNO_NOSYS;
2518
0
  }
2519
0
  switch (Hint->ai_socktype) {
2520
0
  case __WASI_SOCK_TYPE_SOCK_ANY:
2521
0
  case __WASI_SOCK_TYPE_SOCK_DGRAM:
2522
0
  case __WASI_SOCK_TYPE_SOCK_STREAM:
2523
0
    break;
2524
0
  default:
2525
0
    return __WASI_ERRNO_NOSYS;
2526
0
  }
2527
2528
0
  auto Body = [&]() -> WASI::WasiExpect<void> {
2529
0
    auto initWasiAddrinfoArray =
2530
0
        [&MemInst](uint8_t_ptr Base, uint32_t Length,
2531
0
                   Span<__wasi_addrinfo_t *> WasiAddrinfoArray) noexcept
2532
0
        -> WASI::WasiExpect<void> {
2533
0
      for (uint32_t Item = 0; Item < Length; Item++) {
2534
0
        auto *const TmpAddrinfo =
2535
0
            MemInst->getPointer<__wasi_addrinfo_t *>(Base);
2536
0
        if (TmpAddrinfo == nullptr) {
2537
0
          return WASI::WasiUnexpect(__WASI_ERRNO_FAULT);
2538
0
        }
2539
0
        WasiAddrinfoArray[Item] = TmpAddrinfo;
2540
0
        Base = TmpAddrinfo->ai_next;
2541
0
      }
2542
0
      return {};
2543
0
    };
2544
2545
0
    auto initAiAddrArray =
2546
0
        [&MemInst](Span<__wasi_addrinfo_t *> WasiAddrinfoArray,
2547
0
                   Span<__wasi_sockaddr_t *> WasiSockAddrArray) noexcept
2548
0
        -> WASI::WasiExpect<void> {
2549
0
      for (uint32_t Item = 0; Item < WasiAddrinfoArray.size(); Item++) {
2550
0
        auto *const Addr = MemInst->getPointer<__wasi_sockaddr_t *>(
2551
0
            WasiAddrinfoArray[Item]->ai_addr);
2552
0
        if (Addr == nullptr) {
2553
0
          return WASI::WasiUnexpect(__WASI_ERRNO_FAULT);
2554
0
        }
2555
0
        WasiSockAddrArray[Item] = Addr;
2556
0
      }
2557
0
      return {};
2558
0
    };
2559
2560
0
    auto initAiAddrSaDataArray =
2561
0
        [&MemInst](Span<__wasi_sockaddr_t *> WasiSockAddrArray,
2562
0
                   Span<char *> AiSockAddrSaDataArray) noexcept
2563
0
        -> WASI::WasiExpect<void> {
2564
0
      for (uint32_t Item = 0; Item < WasiSockAddrArray.size(); Item++) {
2565
0
        const auto WasiSockAddr =
2566
0
            MemInst->getSpan<char>(WasiSockAddrArray[Item]->sa_data,
2567
0
                                   WasiSockAddrArray[Item]->sa_data_len);
2568
0
        if (WasiSockAddr.size() != WasiSockAddrArray[Item]->sa_data_len) {
2569
0
          return WASI::WasiUnexpect(__WASI_ERRNO_FAULT);
2570
0
        }
2571
0
        AiSockAddrSaDataArray[Item] = WasiSockAddr.data();
2572
0
      }
2573
0
      return {};
2574
0
    };
2575
2576
0
    auto initAiCanonnameArray =
2577
0
        [&MemInst](Span<__wasi_addrinfo_t *> WasiAddrinfoArray,
2578
0
                   Span<char *> WasiAddrinfoCanonnameArray) noexcept
2579
0
        -> WASI::WasiExpect<void> {
2580
0
      for (uint32_t Item = 0; Item < WasiAddrinfoArray.size(); Item++) {
2581
0
        const auto CanonName =
2582
0
            MemInst->getSpan<char>(WasiAddrinfoArray[Item]->ai_canonname,
2583
0
                                   WasiAddrinfoArray[Item]->ai_canonname_len);
2584
0
        if (CanonName.size() != WasiAddrinfoArray[Item]->ai_canonname_len) {
2585
0
          return WASI::WasiUnexpect(__WASI_ERRNO_FAULT);
2586
0
        }
2587
0
        WasiAddrinfoCanonnameArray[Item] = CanonName.data();
2588
0
      }
2589
0
      return {};
2590
0
    };
2591
2592
0
    std::vector<__wasi_addrinfo_t *> WasiAddrinfoArray(MaxResLength, nullptr);
2593
0
    std::vector<__wasi_sockaddr_t *> WasiSockAddrArray(MaxResLength, nullptr);
2594
0
    std::vector<char *> AiAddrSaDataArray(MaxResLength, nullptr);
2595
0
    std::vector<char *> AiCanonnameArray(MaxResLength, nullptr);
2596
2597
0
    EXPECTED_TRY(
2598
0
        initWasiAddrinfoArray(*ResBuf, MaxResLength, WasiAddrinfoArray));
2599
0
    EXPECTED_TRY(initAiAddrArray(WasiAddrinfoArray, WasiSockAddrArray));
2600
0
    EXPECTED_TRY(initAiAddrSaDataArray(WasiSockAddrArray, AiAddrSaDataArray));
2601
0
    EXPECTED_TRY(initAiCanonnameArray(WasiAddrinfoArray, AiCanonnameArray));
2602
2603
0
    EXPECTED_TRY(Env.getAddrInfo(
2604
0
        Node, Service, *Hint, MaxResLength, WasiAddrinfoArray,
2605
0
        WasiSockAddrArray, AiAddrSaDataArray, AiCanonnameArray, *ResLength));
2606
0
    return {};
2607
0
  };
2608
0
  if (auto Res = Body(); unlikely(!Res)) {
2609
0
    return Res.error();
2610
0
  }
2611
2612
0
  return __WASI_ERRNO_SUCCESS;
2613
0
}
2614
2615
Expect<uint32_t>
2616
WasiSockGetLocalAddrV1::body(const Runtime::CallingFrame &Frame, int32_t Fd,
2617
                             uint32_t AddressPtr, uint32_t AddressTypePtr,
2618
0
                             uint32_t PortPtr) {
2619
  // Alignment checks
2620
0
  if (unlikely(isMisaligned<__wasi_address_t>(AddressPtr))) {
2621
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2622
0
  }
2623
2624
0
  if (unlikely(isMisaligned<uint32_t>(AddressTypePtr))) {
2625
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2626
0
  }
2627
2628
0
  if (unlikely(isMisaligned<uint32_t>(PortPtr))) {
2629
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2630
0
  }
2631
2632
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2633
0
  if (MemInst == nullptr) {
2634
0
    return __WASI_ERRNO_FAULT;
2635
0
  }
2636
0
  __wasi_address_t *InnerAddress =
2637
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
2638
0
  if (InnerAddress == nullptr) {
2639
0
    return __WASI_ERRNO_FAULT;
2640
0
  }
2641
2642
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
2643
0
  const auto Address = MemInst->getSpan<uint8_t>(
2644
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
2645
0
  if (Address.size() != InnerAddressBufLen) {
2646
0
    return __WASI_ERRNO_FAULT;
2647
0
  }
2648
2649
0
  switch (Address.size()) {
2650
0
  case 4:
2651
0
    break;
2652
0
  case 16:
2653
0
    break;
2654
0
  default:
2655
0
    return __WASI_ERRNO_INVAL;
2656
0
  }
2657
2658
0
  uint32_t *const RoAddressType =
2659
0
      MemInst->getPointer<uint32_t *>(AddressTypePtr);
2660
0
  if (RoAddressType == nullptr) {
2661
0
    return __WASI_ERRNO_FAULT;
2662
0
  }
2663
0
  __wasi_address_family_t AddressType;
2664
2665
0
  uint32_t *const RoPort = MemInst->getPointer<uint32_t *>(PortPtr);
2666
0
  if (RoPort == nullptr) {
2667
0
    return __WASI_ERRNO_FAULT;
2668
0
  }
2669
2670
0
  uint16_t Port;
2671
0
  const __wasi_fd_t WasiFd = Fd;
2672
2673
0
  if (auto Res = Env.sockGetLocalAddr(WasiFd, &AddressType, Address, &Port);
2674
0
      unlikely(!Res)) {
2675
0
    return Res.error();
2676
0
  }
2677
0
  *RoPort = EndianValue(Port).le();
2678
  // XXX: This is a workaround
2679
  // The correct one should be `*RoAddressType = AddressType;`
2680
  // However, due to this bugfix will break the existing applications.
2681
  // So we changed back to the old way.
2682
0
  switch (AddressType) {
2683
0
  case __WASI_ADDRESS_FAMILY_INET4:
2684
0
    *RoAddressType = EndianValue(4U).le();
2685
0
    break;
2686
0
  case __WASI_ADDRESS_FAMILY_INET6:
2687
0
    *RoAddressType = EndianValue(6U).le();
2688
0
    break;
2689
0
  default:
2690
0
    assumingUnreachable();
2691
0
  }
2692
0
  return __WASI_ERRNO_SUCCESS;
2693
0
}
2694
2695
Expect<uint32_t> WasiSockGetPeerAddrV1::body(const Runtime::CallingFrame &Frame,
2696
                                             int32_t Fd, uint32_t AddressPtr,
2697
                                             uint32_t AddressTypePtr,
2698
0
                                             uint32_t PortPtr) {
2699
  // Alignment checks
2700
0
  if (unlikely(isMisaligned<__wasi_address_t>(AddressPtr))) {
2701
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2702
0
  }
2703
2704
0
  if (unlikely(isMisaligned<uint32_t>(AddressTypePtr))) {
2705
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2706
0
  }
2707
2708
0
  if (unlikely(isMisaligned<uint32_t>(PortPtr))) {
2709
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2710
0
  }
2711
2712
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2713
0
  if (MemInst == nullptr) {
2714
0
    return __WASI_ERRNO_FAULT;
2715
0
  }
2716
0
  __wasi_address_t *InnerAddress =
2717
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
2718
0
  if (InnerAddress == nullptr) {
2719
0
    return __WASI_ERRNO_FAULT;
2720
0
  }
2721
2722
0
  const auto Address =
2723
0
      MemInst->getSpan<uint8_t>(EndianValue(InnerAddress->buf).le(),
2724
0
                                EndianValue(InnerAddress->buf_len).le());
2725
0
  if (Address.size() != EndianValue(InnerAddress->buf_len).le()) {
2726
0
    return __WASI_ERRNO_FAULT;
2727
0
  }
2728
2729
0
  switch (Address.size()) {
2730
0
  case 4:
2731
0
    break;
2732
0
  case 16:
2733
0
    break;
2734
0
  default:
2735
0
    return __WASI_ERRNO_INVAL;
2736
0
  }
2737
2738
0
  uint32_t *const RoAddressType =
2739
0
      MemInst->getPointer<uint32_t *>(AddressTypePtr);
2740
0
  if (RoAddressType == nullptr) {
2741
0
    return __WASI_ERRNO_FAULT;
2742
0
  }
2743
0
  __wasi_address_family_t AddressType;
2744
2745
0
  uint32_t *const RoPort = MemInst->getPointer<uint32_t *>(PortPtr);
2746
0
  if (RoPort == nullptr) {
2747
0
    return __WASI_ERRNO_FAULT;
2748
0
  }
2749
0
  EndianValue<uint16_t> Port;
2750
2751
0
  const __wasi_fd_t WasiFd = Fd;
2752
2753
0
  if (auto Res =
2754
0
          Env.sockGetPeerAddr(WasiFd, &AddressType, Address, &Port.raw());
2755
0
      unlikely(!Res)) {
2756
0
    return Res.error();
2757
0
  }
2758
0
  *RoPort = Port.le();
2759
  // XXX: This is a workaround
2760
  // The correct one should be `*RoAddressType = AddressType;`
2761
  // However, due to this bugfix will break the existing applications.
2762
  // So we changed back to the old way.
2763
0
  switch (AddressType) {
2764
0
  case __WASI_ADDRESS_FAMILY_INET4:
2765
0
    *RoAddressType = EndianValue(4U).le();
2766
0
    break;
2767
0
  case __WASI_ADDRESS_FAMILY_INET6:
2768
0
    *RoAddressType = EndianValue(6U).le();
2769
0
    break;
2770
0
  default:
2771
0
    assumingUnreachable();
2772
0
  }
2773
0
  return __WASI_ERRNO_SUCCESS;
2774
0
}
2775
2776
Expect<uint32_t> WasiSockOpenV2::body(const Runtime::CallingFrame &Frame,
2777
                                      uint32_t AddressFamily, uint32_t SockType,
2778
0
                                      uint32_t /* Out */ RoFdPtr) {
2779
  // Alignment checks
2780
0
  if (unlikely(isMisaligned<__wasi_fd_t>(RoFdPtr))) {
2781
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2782
0
  }
2783
2784
  // Check memory instance from module.
2785
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2786
0
  if (MemInst == nullptr) {
2787
0
    return __WASI_ERRNO_FAULT;
2788
0
  }
2789
2790
0
  __wasi_fd_t *const RoFd = MemInst->getPointer<__wasi_fd_t *>(RoFdPtr);
2791
0
  if (RoFd == nullptr) {
2792
0
    return __WASI_ERRNO_FAULT;
2793
0
  }
2794
2795
0
  __wasi_address_family_t WasiAddressFamily;
2796
0
  if (auto Res = cast<__wasi_address_family_t>(AddressFamily); unlikely(!Res)) {
2797
0
    return Res.error();
2798
0
  } else {
2799
0
    WasiAddressFamily = *Res;
2800
0
  }
2801
2802
0
  if (!AllowAFUNIX(Frame, WasiAddressFamily)) {
2803
0
    return __WASI_ERRNO_NOSYS;
2804
0
  }
2805
2806
0
  __wasi_sock_type_t WasiSockType;
2807
0
  if (auto Res = cast<__wasi_sock_type_t>(SockType); unlikely(!Res)) {
2808
0
    return Res.error();
2809
0
  } else {
2810
0
    WasiSockType = *Res;
2811
0
  }
2812
2813
0
  if (auto Res = Env.sockOpen(WasiAddressFamily, WasiSockType);
2814
0
      unlikely(!Res)) {
2815
0
    return Res.error();
2816
0
  } else {
2817
0
    *RoFd = EndianValue(*Res).le();
2818
0
  }
2819
2820
0
  return __WASI_ERRNO_SUCCESS;
2821
0
}
2822
2823
Expect<uint32_t> WasiSockBindV2::body(const Runtime::CallingFrame &Frame,
2824
                                      int32_t Fd, uint32_t AddressPtr,
2825
0
                                      uint32_t Port) {
2826
  // Alignment checks
2827
0
  if (unlikely(isMisaligned<__wasi_address_t>(AddressPtr))) {
2828
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2829
0
  }
2830
2831
  // Check memory instance from module.
2832
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2833
0
  if (MemInst == nullptr) {
2834
0
    return __WASI_ERRNO_FAULT;
2835
0
  }
2836
0
  auto *const InnerAddress =
2837
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
2838
0
  if (InnerAddress == nullptr) {
2839
0
    return __WASI_ERRNO_FAULT;
2840
0
  }
2841
2842
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
2843
0
  auto Address = MemInst->getSpan<const uint8_t>(
2844
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
2845
0
  if (Address.size() != InnerAddressBufLen) {
2846
0
    return __WASI_ERRNO_FAULT;
2847
0
  }
2848
2849
0
  __wasi_address_family_t WasiAddressFamily;
2850
0
  switch (Address.size()) {
2851
0
  case 4:
2852
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET4;
2853
0
    break;
2854
0
  case 16:
2855
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET6;
2856
0
    break;
2857
0
  case 128: {
2858
0
    auto &Storage =
2859
0
        *reinterpret_cast<const WASI::WasiAddrStorage *>(Address.data());
2860
0
    WasiAddressFamily = Storage.getAddressFamily();
2861
0
    Address = Storage.getAddress();
2862
0
    break;
2863
0
  }
2864
0
  default:
2865
0
    return __WASI_ERRNO_INVAL;
2866
0
  }
2867
2868
0
  const __wasi_fd_t WasiFd = Fd;
2869
0
  if (auto Res = Env.sockBind(WasiFd, WasiAddressFamily, Address,
2870
0
                              static_cast<uint16_t>(Port));
2871
0
      unlikely(!Res)) {
2872
0
    return Res.error();
2873
0
  }
2874
0
  return __WASI_ERRNO_SUCCESS;
2875
0
}
2876
2877
Expect<uint32_t> WasiSockListenV2::body(const Runtime::CallingFrame &,
2878
0
                                        int32_t Fd, int32_t Backlog) {
2879
0
  const __wasi_fd_t WasiFd = Fd;
2880
0
  if (auto Res = Env.sockListen(WasiFd, Backlog); unlikely(!Res)) {
2881
0
    return Res.error();
2882
0
  }
2883
0
  return __WASI_ERRNO_SUCCESS;
2884
0
}
2885
2886
Expect<uint32_t> WasiSockConnectV2::body(const Runtime::CallingFrame &Frame,
2887
                                         int32_t Fd, uint32_t AddressPtr,
2888
0
                                         uint32_t Port) {
2889
  // Alignment checks
2890
0
  if (unlikely(isMisaligned<__wasi_address_t>(AddressPtr))) {
2891
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2892
0
  }
2893
2894
  // Check memory instance from module.
2895
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2896
0
  if (MemInst == nullptr) {
2897
0
    return __WASI_ERRNO_FAULT;
2898
0
  }
2899
0
  __wasi_address_t *InnerAddress =
2900
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
2901
0
  if (InnerAddress == nullptr) {
2902
0
    return __WASI_ERRNO_FAULT;
2903
0
  }
2904
2905
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
2906
0
  auto Address = MemInst->getSpan<const uint8_t>(
2907
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
2908
0
  if (Address.size() != InnerAddressBufLen) {
2909
0
    return __WASI_ERRNO_FAULT;
2910
0
  }
2911
2912
0
  __wasi_address_family_t WasiAddressFamily;
2913
0
  switch (Address.size()) {
2914
0
  case 4:
2915
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET4;
2916
0
    break;
2917
0
  case 16:
2918
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET6;
2919
0
    break;
2920
0
  case 128: {
2921
0
    auto &Storage =
2922
0
        *reinterpret_cast<const WASI::WasiAddrStorage *>(Address.data());
2923
0
    WasiAddressFamily = Storage.getAddressFamily();
2924
0
    Address = Storage.getAddress();
2925
0
    break;
2926
0
  }
2927
0
  default:
2928
0
    return __WASI_ERRNO_INVAL;
2929
0
  }
2930
2931
0
  const __wasi_fd_t WasiFd = Fd;
2932
0
  if (auto Res = Env.sockConnect(WasiFd, WasiAddressFamily, Address,
2933
0
                                 static_cast<uint16_t>(Port));
2934
0
      unlikely(!Res)) {
2935
0
    return Res.error();
2936
0
  }
2937
2938
0
  return __WASI_ERRNO_SUCCESS;
2939
0
}
2940
2941
Expect<uint32_t> WasiSockRecvV2::body(const Runtime::CallingFrame &Frame,
2942
                                      int32_t Fd, uint32_t RiDataPtr,
2943
                                      uint32_t RiDataLen, uint32_t RiFlags,
2944
                                      uint32_t /* Out */ RoDataLenPtr,
2945
0
                                      uint32_t /* Out */ RoFlagsPtr) {
2946
  // Alignment checks
2947
0
  if (unlikely(isMisaligned<__wasi_iovec_t>(RiDataPtr))) {
2948
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2949
0
  }
2950
2951
0
  if (unlikely(isMisaligned<__wasi_size_t>(RoDataLenPtr))) {
2952
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2953
0
  }
2954
2955
0
  if (unlikely(isMisaligned<__wasi_roflags_t>(RoFlagsPtr))) {
2956
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
2957
0
  }
2958
2959
  // Check memory instance from module.
2960
0
  auto *MemInst = Frame.getMemoryByIndex(0);
2961
0
  if (MemInst == nullptr) {
2962
0
    return __WASI_ERRNO_FAULT;
2963
0
  }
2964
2965
0
  __wasi_riflags_t WasiRiFlags;
2966
0
  if (auto Res = cast<__wasi_riflags_t>(RiFlags); unlikely(!Res)) {
2967
0
    return Res.error();
2968
0
  } else {
2969
0
    WasiRiFlags = EndianValue(*Res).le();
2970
0
  }
2971
2972
0
  const __wasi_size_t WasiRiDataLen = RiDataLen;
2973
0
  if (unlikely(WasiRiDataLen > WASI::kIOVMax)) {
2974
0
    return __WASI_ERRNO_INVAL;
2975
0
  }
2976
2977
  // Check for invalid address.
2978
0
  const auto RiDataArray =
2979
0
      MemInst->getSpan<__wasi_iovec_t>(RiDataPtr, WasiRiDataLen);
2980
0
  if (unlikely(RiDataArray.size() != WasiRiDataLen)) {
2981
0
    return __WASI_ERRNO_FAULT;
2982
0
  }
2983
2984
0
  auto *const RoDataLen = MemInst->getPointer<__wasi_size_t *>(RoDataLenPtr);
2985
0
  if (unlikely(RoDataLen == nullptr)) {
2986
0
    return __WASI_ERRNO_FAULT;
2987
0
  }
2988
2989
0
  auto *const RoFlags = MemInst->getPointer<__wasi_roflags_t *>(RoFlagsPtr);
2990
0
  if (unlikely(RoFlags == nullptr)) {
2991
0
    return __WASI_ERRNO_FAULT;
2992
0
  }
2993
0
  __wasi_size_t TotalSize = 0;
2994
0
  StaticVector<Span<uint8_t>, WASI::kIOVMax> WasiRiData;
2995
2996
0
  for (auto &RiData : RiDataArray) {
2997
    // Capping total size.
2998
0
    const __wasi_size_t Space =
2999
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
3000
0
    const uint32_t RiDataBufLen = EndianValue(RiData.buf_len).le();
3001
0
    const __wasi_size_t BufLen =
3002
0
        unlikely(RiDataBufLen > Space) ? Space : RiDataBufLen;
3003
0
    TotalSize += BufLen;
3004
3005
    // Check for invalid address.
3006
0
    const auto RiDataArr =
3007
0
        MemInst->getSpan<uint8_t>(EndianValue(RiData.buf).le(), BufLen);
3008
0
    if (unlikely(RiDataArr.size() != BufLen)) {
3009
0
      return __WASI_ERRNO_FAULT;
3010
0
    }
3011
0
    WasiRiData.emplace_back_unchecked(RiDataArr);
3012
0
  }
3013
3014
0
  const __wasi_fd_t WasiFd = Fd;
3015
3016
0
  if (auto Res =
3017
0
          Env.sockRecv(WasiFd, WasiRiData, WasiRiFlags, *RoDataLen, *RoFlags);
3018
0
      unlikely(!Res)) {
3019
0
    return Res.error();
3020
0
  }
3021
0
  return __WASI_ERRNO_SUCCESS;
3022
0
}
3023
3024
Expect<uint32_t> WasiSockRecvFromV2::body(const Runtime::CallingFrame &Frame,
3025
                                          int32_t Fd, uint32_t RiDataPtr,
3026
                                          uint32_t RiDataLen,
3027
                                          uint32_t AddressPtr, uint32_t RiFlags,
3028
                                          uint32_t /* Out */ PortPtr,
3029
                                          uint32_t /* Out */ RoDataLenPtr,
3030
0
                                          uint32_t /* Out */ RoFlagsPtr) {
3031
  // Alignment checks
3032
0
  if (unlikely(isMisaligned<__wasi_iovec_t>(RiDataPtr))) {
3033
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3034
0
  }
3035
3036
0
  if (unlikely(isMisaligned<__wasi_address_t>(AddressPtr))) {
3037
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3038
0
  }
3039
3040
0
  if (unlikely(isMisaligned<uint16_t>(PortPtr))) {
3041
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3042
0
  }
3043
3044
0
  if (unlikely(isMisaligned<__wasi_size_t>(RoDataLenPtr))) {
3045
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3046
0
  }
3047
3048
0
  if (unlikely(isMisaligned<__wasi_roflags_t>(RoFlagsPtr))) {
3049
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3050
0
  }
3051
3052
  // Check memory instance from module.
3053
0
  auto *MemInst = Frame.getMemoryByIndex(0);
3054
0
  if (MemInst == nullptr) {
3055
0
    return __WASI_ERRNO_FAULT;
3056
0
  }
3057
3058
0
  __wasi_address_t *InnerAddress =
3059
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
3060
0
  if (InnerAddress == nullptr) {
3061
0
    return __WASI_ERRNO_FAULT;
3062
0
  }
3063
3064
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
3065
0
  auto Address = MemInst->getSpan<uint8_t>(EndianValue(InnerAddress->buf).le(),
3066
0
                                           InnerAddressBufLen);
3067
0
  if (Address.size() != InnerAddressBufLen) {
3068
0
    return __WASI_ERRNO_FAULT;
3069
0
  }
3070
3071
0
  __wasi_address_family_t WasiAddressFamily;
3072
0
  WASI::WasiAddrStorage *Storage = nullptr;
3073
0
  switch (Address.size()) {
3074
0
  case 4:
3075
0
  case 16:
3076
0
    break;
3077
0
  case 128:
3078
0
    Storage = reinterpret_cast<WASI::WasiAddrStorage *>(Address.data());
3079
0
    Address = Storage->getAddress();
3080
0
    break;
3081
0
  default:
3082
0
    return __WASI_ERRNO_INVAL;
3083
0
  }
3084
3085
0
  __wasi_riflags_t WasiRiFlags;
3086
0
  if (auto Res = cast<__wasi_riflags_t>(RiFlags); unlikely(!Res)) {
3087
0
    return Res.error();
3088
0
  } else {
3089
0
    WasiRiFlags = *Res;
3090
0
  }
3091
3092
0
  const __wasi_size_t WasiRiDataLen = RiDataLen;
3093
0
  if (unlikely(WasiRiDataLen > WASI::kIOVMax)) {
3094
0
    return __WASI_ERRNO_INVAL;
3095
0
  }
3096
3097
  // Check for invalid address.
3098
0
  uint16_t *const RoPort = MemInst->getPointer<uint16_t *>(PortPtr);
3099
0
  if (RoPort == nullptr) {
3100
0
    return __WASI_ERRNO_FAULT;
3101
0
  }
3102
3103
0
  const auto RiDataArray =
3104
0
      MemInst->getSpan<__wasi_iovec_t>(RiDataPtr, WasiRiDataLen);
3105
0
  if (unlikely(RiDataArray.size() != WasiRiDataLen)) {
3106
0
    return __WASI_ERRNO_FAULT;
3107
0
  }
3108
3109
0
  auto *const RoDataLen = MemInst->getPointer<__wasi_size_t *>(RoDataLenPtr);
3110
0
  if (unlikely(RoDataLen == nullptr)) {
3111
0
    return __WASI_ERRNO_FAULT;
3112
0
  }
3113
3114
0
  auto *const RoFlags = MemInst->getPointer<__wasi_roflags_t *>(RoFlagsPtr);
3115
0
  if (unlikely(RoFlags == nullptr)) {
3116
0
    return __WASI_ERRNO_FAULT;
3117
0
  }
3118
0
  __wasi_size_t TotalSize = 0;
3119
0
  StaticVector<Span<uint8_t>, WASI::kIOVMax> WasiRiData;
3120
3121
0
  for (auto &RiData : RiDataArray) {
3122
    // Capping total size.
3123
0
    const __wasi_size_t Space =
3124
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
3125
0
    const uint32_t RiDataBufLen = EndianValue(RiData.buf_len).le();
3126
0
    const __wasi_size_t BufLen =
3127
0
        unlikely(RiDataBufLen > Space) ? Space : RiDataBufLen;
3128
0
    TotalSize += BufLen;
3129
3130
    // Check for invalid address.
3131
0
    const auto RiDataArr =
3132
0
        MemInst->getSpan<uint8_t>(EndianValue(RiData.buf).le(), BufLen);
3133
0
    if (unlikely(RiDataArr.size() != BufLen)) {
3134
0
      return __WASI_ERRNO_FAULT;
3135
0
    }
3136
0
    WasiRiData.emplace_back_unchecked(RiDataArr);
3137
0
  }
3138
3139
0
  const __wasi_fd_t WasiFd = Fd;
3140
3141
0
  if (auto Res =
3142
0
          Env.sockRecvFrom(WasiFd, WasiRiData, WasiRiFlags, &WasiAddressFamily,
3143
0
                           Address, RoPort, *RoDataLen, *RoFlags);
3144
0
      unlikely(!Res)) {
3145
0
    return Res.error();
3146
0
  }
3147
0
  if (Storage) {
3148
0
    Storage->setAddressFamily(WasiAddressFamily);
3149
0
  }
3150
0
  return __WASI_ERRNO_SUCCESS;
3151
0
}
3152
3153
Expect<uint32_t> WasiSockSendV2::body(const Runtime::CallingFrame &Frame,
3154
                                      int32_t Fd, uint32_t SiDataPtr,
3155
                                      uint32_t SiDataLen, uint32_t SiFlags,
3156
0
                                      uint32_t /* Out */ SoDataLenPtr) {
3157
  // Alignment checks
3158
0
  if (unlikely(isMisaligned<__wasi_ciovec_t>(SiDataPtr))) {
3159
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3160
0
  }
3161
3162
0
  if (unlikely(isMisaligned<__wasi_size_t>(SoDataLenPtr))) {
3163
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3164
0
  }
3165
3166
  // Check memory instance from module.
3167
0
  auto *MemInst = Frame.getMemoryByIndex(0);
3168
0
  if (MemInst == nullptr) {
3169
0
    return __WASI_ERRNO_FAULT;
3170
0
  }
3171
3172
0
  __wasi_siflags_t WasiSiFlags;
3173
0
  if (auto Res = cast<__wasi_siflags_t>(SiFlags); unlikely(!Res)) {
3174
0
    return Res.error();
3175
0
  } else {
3176
0
    WasiSiFlags = *Res;
3177
0
  }
3178
3179
0
  const __wasi_size_t WasiSiDataLen = SiDataLen;
3180
0
  if (unlikely(WasiSiDataLen > WASI::kIOVMax)) {
3181
0
    return __WASI_ERRNO_INVAL;
3182
0
  }
3183
3184
  // Check for invalid address.
3185
0
  const auto SiDataArray =
3186
0
      MemInst->getSpan<__wasi_ciovec_t>(SiDataPtr, WasiSiDataLen);
3187
0
  if (unlikely(SiDataArray.size() != WasiSiDataLen)) {
3188
0
    return __WASI_ERRNO_FAULT;
3189
0
  }
3190
3191
0
  auto *const SoDataLen = MemInst->getPointer<__wasi_size_t *>(SoDataLenPtr);
3192
0
  if (unlikely(SoDataLen == nullptr)) {
3193
0
    return __WASI_ERRNO_FAULT;
3194
0
  }
3195
3196
0
  __wasi_size_t TotalSize = 0;
3197
0
  StaticVector<Span<const uint8_t>, WASI::kIOVMax> WasiSiData;
3198
3199
0
  for (auto &SiData : SiDataArray) {
3200
    // Capping total size.
3201
0
    const __wasi_size_t Space =
3202
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
3203
0
    const uint32_t SiDataBufLen = EndianValue(SiData.buf_len).le();
3204
0
    const __wasi_size_t BufLen =
3205
0
        unlikely(SiDataBufLen > Space) ? Space : SiDataBufLen;
3206
0
    TotalSize += BufLen;
3207
3208
    // Check for invalid address.
3209
0
    const auto SiDataArr =
3210
0
        MemInst->getSpan<uint8_t>(EndianValue(SiData.buf).le(), BufLen);
3211
0
    if (unlikely(SiDataArr.size() != BufLen)) {
3212
0
      return __WASI_ERRNO_FAULT;
3213
0
    }
3214
0
    WasiSiData.emplace_back_unchecked(SiDataArr);
3215
0
  }
3216
3217
0
  const __wasi_fd_t WasiFd = Fd;
3218
3219
0
  if (auto Res = Env.sockSend(WasiFd, WasiSiData, WasiSiFlags, *SoDataLen);
3220
0
      unlikely(!Res)) {
3221
0
    return Res.error();
3222
0
  }
3223
0
  return __WASI_ERRNO_SUCCESS;
3224
0
}
3225
3226
Expect<uint32_t> WasiSockSendToV2::body(const Runtime::CallingFrame &Frame,
3227
                                        int32_t Fd, uint32_t SiDataPtr,
3228
                                        uint32_t SiDataLen, uint32_t AddressPtr,
3229
                                        int32_t Port, uint32_t SiFlags,
3230
0
                                        uint32_t /* Out */ SoDataLenPtr) {
3231
  // Alignment checks
3232
0
  if (unlikely(isMisaligned<__wasi_ciovec_t>(SiDataPtr))) {
3233
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3234
0
  }
3235
3236
0
  if (unlikely(isMisaligned<__wasi_address_t>(AddressPtr))) {
3237
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3238
0
  }
3239
3240
0
  if (unlikely(isMisaligned<__wasi_size_t>(SoDataLenPtr))) {
3241
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3242
0
  }
3243
3244
  // Check memory instance from module.
3245
0
  auto *MemInst = Frame.getMemoryByIndex(0);
3246
0
  if (MemInst == nullptr) {
3247
0
    return __WASI_ERRNO_FAULT;
3248
0
  }
3249
3250
0
  __wasi_address_t *InnerAddress =
3251
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
3252
0
  if (InnerAddress == nullptr) {
3253
0
    return __WASI_ERRNO_FAULT;
3254
0
  }
3255
3256
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
3257
0
  auto Address = MemInst->getSpan<const uint8_t>(
3258
0
      EndianValue(InnerAddress->buf).le(), InnerAddressBufLen);
3259
0
  if (Address.size() != InnerAddressBufLen) {
3260
0
    return __WASI_ERRNO_FAULT;
3261
0
  }
3262
3263
0
  __wasi_address_family_t WasiAddressFamily;
3264
0
  switch (Address.size()) {
3265
0
  case 4:
3266
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET4;
3267
0
    break;
3268
0
  case 16:
3269
0
    WasiAddressFamily = __WASI_ADDRESS_FAMILY_INET6;
3270
0
    break;
3271
0
  case 128: {
3272
0
    auto &Storage =
3273
0
        *reinterpret_cast<const WASI::WasiAddrStorage *>(Address.data());
3274
0
    WasiAddressFamily = Storage.getAddressFamily();
3275
0
    Address = Storage.getAddress();
3276
0
    break;
3277
0
  }
3278
0
  default:
3279
0
    return __WASI_ERRNO_INVAL;
3280
0
  }
3281
3282
0
  __wasi_siflags_t WasiSiFlags;
3283
0
  if (auto Res = cast<__wasi_siflags_t>(SiFlags); unlikely(!Res)) {
3284
0
    return Res.error();
3285
0
  } else {
3286
0
    WasiSiFlags = *Res;
3287
0
  }
3288
3289
0
  const __wasi_size_t WasiSiDataLen = SiDataLen;
3290
0
  if (unlikely(WasiSiDataLen > WASI::kIOVMax)) {
3291
0
    return __WASI_ERRNO_INVAL;
3292
0
  }
3293
3294
  // Check for invalid address.
3295
0
  const auto SiDataArray =
3296
0
      MemInst->getSpan<__wasi_ciovec_t>(SiDataPtr, WasiSiDataLen);
3297
0
  if (unlikely(SiDataArray.size() != WasiSiDataLen)) {
3298
0
    return __WASI_ERRNO_FAULT;
3299
0
  }
3300
3301
0
  auto *const SoDataLen = MemInst->getPointer<__wasi_size_t *>(SoDataLenPtr);
3302
0
  if (unlikely(SoDataLen == nullptr)) {
3303
0
    return __WASI_ERRNO_FAULT;
3304
0
  }
3305
3306
0
  __wasi_size_t TotalSize = 0;
3307
0
  StaticVector<Span<const uint8_t>, WASI::kIOVMax> WasiSiData;
3308
3309
0
  for (auto &SiData : SiDataArray) {
3310
    // Capping total size.
3311
0
    const __wasi_size_t Space =
3312
0
        std::numeric_limits<__wasi_size_t>::max() - TotalSize;
3313
0
    const uint32_t SiDataBufLen = EndianValue(SiData.buf_len).le();
3314
0
    const __wasi_size_t BufLen =
3315
0
        unlikely(SiDataBufLen > Space) ? Space : SiDataBufLen;
3316
0
    TotalSize += BufLen;
3317
3318
    // Check for invalid address.
3319
0
    const auto SiDataArr =
3320
0
        MemInst->getSpan<uint8_t>(EndianValue(SiData.buf).le(), BufLen);
3321
0
    if (unlikely(SiDataArr.size() != BufLen)) {
3322
0
      return __WASI_ERRNO_FAULT;
3323
0
    }
3324
0
    WasiSiData.emplace_back_unchecked(SiDataArr);
3325
0
  }
3326
3327
0
  const __wasi_fd_t WasiFd = Fd;
3328
0
  if (auto Res =
3329
0
          Env.sockSendTo(WasiFd, WasiSiData, WasiSiFlags, WasiAddressFamily,
3330
0
                         Address, static_cast<uint16_t>(Port), *SoDataLen);
3331
0
      unlikely(!Res)) {
3332
0
    return Res.error();
3333
0
  }
3334
3335
0
  return __WASI_ERRNO_SUCCESS;
3336
0
}
3337
3338
Expect<uint32_t> WasiSockGetOpt::body(const Runtime::CallingFrame &Frame,
3339
                                      int32_t Fd, uint32_t SockOptLevel,
3340
                                      uint32_t SockOptName, uint32_t FlagPtr,
3341
0
                                      uint32_t FlagSizePtr) {
3342
  // Alignment checks
3343
  // no alignment requirement for FlagPtr as it's a byte array
3344
3345
0
  if (unlikely(isMisaligned<uint32_t>(FlagSizePtr))) {
3346
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3347
0
  }
3348
3349
0
  auto *MemInst = Frame.getMemoryByIndex(0);
3350
0
  if (MemInst == nullptr) {
3351
0
    return __WASI_ERRNO_FAULT;
3352
0
  }
3353
3354
0
  __wasi_sock_opt_level_t WasiSockOptLevel;
3355
0
  if (auto Res = cast<__wasi_sock_opt_level_t>(SockOptLevel); unlikely(!Res)) {
3356
0
    return Res.error();
3357
0
  } else {
3358
0
    WasiSockOptLevel = *Res;
3359
0
  }
3360
3361
0
  __wasi_sock_opt_so_t WasiSockOptName;
3362
0
  if (auto Res = cast<__wasi_sock_opt_so_t>(SockOptName); unlikely(!Res)) {
3363
0
    return Res.error();
3364
0
  } else {
3365
0
    WasiSockOptName = *Res;
3366
0
  }
3367
3368
0
  auto *const SysFlagSizePtr = MemInst->getPointer<uint32_t *>(FlagSizePtr);
3369
0
  if (SysFlagSizePtr == nullptr) {
3370
0
    return __WASI_ERRNO_FAULT;
3371
0
  }
3372
3373
0
  auto Flag =
3374
0
      MemInst->getSpan<uint8_t>(FlagPtr, EndianValue(*SysFlagSizePtr).le());
3375
0
  if (Flag.size() != EndianValue(*SysFlagSizePtr).le()) {
3376
0
    return __WASI_ERRNO_FAULT;
3377
0
  }
3378
3379
0
  const __wasi_fd_t WasiFd = Fd;
3380
3381
0
  if (auto Res =
3382
0
          Env.sockGetOpt(WasiFd, WasiSockOptLevel, WasiSockOptName, Flag);
3383
0
      unlikely(!Res)) {
3384
0
    return Res.error();
3385
0
  }
3386
0
  *SysFlagSizePtr = EndianValue(static_cast<uint32_t>(Flag.size())).le();
3387
0
  return __WASI_ERRNO_SUCCESS;
3388
0
}
3389
3390
Expect<uint32_t>
3391
WasiSockGetLocalAddrV2::body(const Runtime::CallingFrame &Frame, int32_t Fd,
3392
0
                             uint32_t AddressPtr, uint32_t PortPtr) {
3393
  // Alignment checks
3394
0
  if (unlikely(isMisaligned<__wasi_address_t>(AddressPtr))) {
3395
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3396
0
  }
3397
3398
0
  if (unlikely(isMisaligned<uint32_t>(PortPtr))) {
3399
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3400
0
  }
3401
3402
0
  auto *MemInst = Frame.getMemoryByIndex(0);
3403
0
  if (MemInst == nullptr) {
3404
0
    return __WASI_ERRNO_FAULT;
3405
0
  }
3406
0
  __wasi_address_t *InnerAddress =
3407
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
3408
0
  if (InnerAddress == nullptr) {
3409
0
    return __WASI_ERRNO_FAULT;
3410
0
  }
3411
3412
0
  const auto InnerAddressBufLen = EndianValue(InnerAddress->buf_len).le();
3413
0
  auto Address = MemInst->getSpan<uint8_t>(EndianValue(InnerAddress->buf).le(),
3414
0
                                           InnerAddressBufLen);
3415
0
  if (Address.size() != InnerAddressBufLen) {
3416
0
    return __WASI_ERRNO_FAULT;
3417
0
  }
3418
3419
0
  uint32_t *const RoPort = MemInst->getPointer<uint32_t *>(PortPtr);
3420
0
  if (RoPort == nullptr) {
3421
0
    return __WASI_ERRNO_FAULT;
3422
0
  }
3423
3424
0
  if (Address.size() != 128) {
3425
0
    return __WASI_ERRNO_INVAL;
3426
0
  }
3427
3428
0
  const __wasi_fd_t WasiFd = Fd;
3429
0
  WASI::WasiAddrStorage &Storage =
3430
0
      *reinterpret_cast<WASI::WasiAddrStorage *>(Address.data());
3431
0
  Address = Storage.getAddress();
3432
0
  __wasi_address_family_t WasiAddressFamily;
3433
0
  uint16_t Port;
3434
3435
0
  if (auto Res =
3436
0
          Env.sockGetLocalAddr(WasiFd, &WasiAddressFamily, Address, &Port);
3437
0
      unlikely(!Res)) {
3438
0
    return Res.error();
3439
0
  }
3440
3441
0
  Storage.setAddressFamily(WasiAddressFamily);
3442
0
  *RoPort = EndianValue(static_cast<uint32_t>(Port)).le();
3443
0
  return __WASI_ERRNO_SUCCESS;
3444
0
}
3445
3446
Expect<uint32_t> WasiSockGetPeerAddrV2::body(const Runtime::CallingFrame &Frame,
3447
                                             int32_t Fd, uint32_t AddressPtr,
3448
0
                                             uint32_t PortPtr) {
3449
  // Alignment checks
3450
0
  if (unlikely(isMisaligned<__wasi_address_t>(AddressPtr))) {
3451
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3452
0
  }
3453
3454
0
  if (unlikely(isMisaligned<uint32_t>(PortPtr))) {
3455
0
    return __WASI_ERRNO_ADDRNOTAVAIL;
3456
0
  }
3457
3458
0
  auto *MemInst = Frame.getMemoryByIndex(0);
3459
0
  if (MemInst == nullptr) {
3460
0
    return __WASI_ERRNO_FAULT;
3461
0
  }
3462
0
  __wasi_address_t *InnerAddress =
3463
0
      MemInst->getPointer<__wasi_address_t *>(AddressPtr);
3464
0
  if (InnerAddress == nullptr) {
3465
0
    return __WASI_ERRNO_FAULT;
3466
0
  }
3467
3468
0
  auto Address =
3469
0
      MemInst->getSpan<uint8_t>(InnerAddress->buf, InnerAddress->buf_len);
3470
0
  if (Address.size() != InnerAddress->buf_len) {
3471
0
    return __WASI_ERRNO_FAULT;
3472
0
  }
3473
3474
0
  uint32_t *const RoPort = MemInst->getPointer<uint32_t *>(PortPtr);
3475
0
  if (RoPort == nullptr) {
3476
0
    return __WASI_ERRNO_FAULT;
3477
0
  }
3478
3479
0
  if (Address.size() != 128) {
3480
0
    return __WASI_ERRNO_INVAL;
3481
0
  }
3482
3483
0
  const __wasi_fd_t WasiFd = Fd;
3484
0
  WASI::WasiAddrStorage &Storage =
3485
0
      *reinterpret_cast<WASI::WasiAddrStorage *>(Address.data());
3486
0
  Address = Storage.getAddress();
3487
0
  __wasi_address_family_t WasiAddressFamily;
3488
0
  uint16_t Port;
3489
3490
0
  if (auto Res =
3491
0
          Env.sockGetPeerAddr(WasiFd, &WasiAddressFamily, Address, &Port);
3492
0
      unlikely(!Res)) {
3493
0
    return Res.error();
3494
0
  }
3495
0
  Storage.setAddressFamily(WasiAddressFamily);
3496
0
  *RoPort = EndianValue(static_cast<uint32_t>(Port)).le();
3497
0
  return __WASI_ERRNO_SUCCESS;
3498
0
}
3499
} // namespace Host
3500
} // namespace WasmEdge