xref: /third_party/node/deps/uvwasi/src/wasi_serdes.c (revision 1cb0ef41)
11cb0ef41Sopenharmony_ci#include "wasi_serdes.h"
21cb0ef41Sopenharmony_ci#include "wasi_types.h"
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_civoid uvwasi_serdes_write_uint64_t(void* ptr,
51cb0ef41Sopenharmony_ci                                  size_t offset,
61cb0ef41Sopenharmony_ci                                  uint64_t value) {
71cb0ef41Sopenharmony_ci  uvwasi_serdes_write_uint32_t(ptr, offset, (uint32_t) value);
81cb0ef41Sopenharmony_ci  uvwasi_serdes_write_uint32_t(ptr, offset + 4, value >> 32);
91cb0ef41Sopenharmony_ci}
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_civoid uvwasi_serdes_write_uint32_t(void* ptr,
121cb0ef41Sopenharmony_ci                                  size_t offset,
131cb0ef41Sopenharmony_ci                                  uint32_t value) {
141cb0ef41Sopenharmony_ci  uvwasi_serdes_write_uint16_t(ptr, offset, (uint16_t) value);
151cb0ef41Sopenharmony_ci  uvwasi_serdes_write_uint16_t(ptr, offset + 2, value >> 16);
161cb0ef41Sopenharmony_ci}
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_civoid uvwasi_serdes_write_uint16_t(void* ptr,
191cb0ef41Sopenharmony_ci                                  size_t offset,
201cb0ef41Sopenharmony_ci                                  uint16_t value) {
211cb0ef41Sopenharmony_ci  uvwasi_serdes_write_uint8_t(ptr, offset, (uint8_t) value);
221cb0ef41Sopenharmony_ci  uvwasi_serdes_write_uint8_t(ptr, offset + 1, value >> 8);
231cb0ef41Sopenharmony_ci}
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_civoid uvwasi_serdes_write_uint8_t(void* ptr,
261cb0ef41Sopenharmony_ci                                 size_t offset,
271cb0ef41Sopenharmony_ci                                 uint8_t value) {
281cb0ef41Sopenharmony_ci  ((uint8_t*) ptr)[offset] = value;
291cb0ef41Sopenharmony_ci}
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ciuint64_t uvwasi_serdes_read_uint64_t(const void* ptr, size_t offset) {
321cb0ef41Sopenharmony_ci  uint64_t low = uvwasi_serdes_read_uint32_t(ptr, offset);
331cb0ef41Sopenharmony_ci  uint64_t high = uvwasi_serdes_read_uint32_t(ptr, offset + 4);
341cb0ef41Sopenharmony_ci  return low | (high << 32);
351cb0ef41Sopenharmony_ci}
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ciuint32_t uvwasi_serdes_read_uint32_t(const void* ptr, size_t offset) {
381cb0ef41Sopenharmony_ci  uint32_t low = uvwasi_serdes_read_uint16_t(ptr, offset);
391cb0ef41Sopenharmony_ci  uint32_t high = uvwasi_serdes_read_uint16_t(ptr, offset + 2);
401cb0ef41Sopenharmony_ci  return low | (high << 16);
411cb0ef41Sopenharmony_ci}
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ciuint16_t uvwasi_serdes_read_uint16_t(const void* ptr, size_t offset) {
441cb0ef41Sopenharmony_ci  uint16_t low = uvwasi_serdes_read_uint8_t(ptr, offset);
451cb0ef41Sopenharmony_ci  uint16_t high = uvwasi_serdes_read_uint8_t(ptr, offset + 1);
461cb0ef41Sopenharmony_ci  return low | (high << 8);
471cb0ef41Sopenharmony_ci}
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ciuint8_t uvwasi_serdes_read_uint8_t(const void* ptr,  size_t offset) {
501cb0ef41Sopenharmony_ci  return ((const uint8_t*) ptr)[offset];
511cb0ef41Sopenharmony_ci}
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci#define TYPE_SWITCH switch (value->type)
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci#define ALL_TYPES(STRUCT, FIELD, ALIAS)                                       \
561cb0ef41Sopenharmony_ci                                                                              \
571cb0ef41Sopenharmony_ci  ALIAS(advice_t,        uint8_t)                                             \
581cb0ef41Sopenharmony_ci  ALIAS(clockid_t,       uint32_t)                                            \
591cb0ef41Sopenharmony_ci  ALIAS(device_t,        uint64_t)                                            \
601cb0ef41Sopenharmony_ci  ALIAS(dircookie_t,     uint64_t)                                            \
611cb0ef41Sopenharmony_ci  ALIAS(errno_t,         uint16_t)                                            \
621cb0ef41Sopenharmony_ci  ALIAS(eventrwflags_t,  uint16_t)                                            \
631cb0ef41Sopenharmony_ci  ALIAS(eventtype_t,     uint8_t)                                             \
641cb0ef41Sopenharmony_ci  ALIAS(exitcode_t,      uint32_t)                                            \
651cb0ef41Sopenharmony_ci  ALIAS(fd_t,            uint32_t)                                            \
661cb0ef41Sopenharmony_ci  ALIAS(fdflags_t,       uint16_t)                                            \
671cb0ef41Sopenharmony_ci  ALIAS(filesize_t,      uint64_t)                                            \
681cb0ef41Sopenharmony_ci  ALIAS(filetype_t,      uint8_t)                                             \
691cb0ef41Sopenharmony_ci  ALIAS(fstflags_t,      uint16_t)                                            \
701cb0ef41Sopenharmony_ci  ALIAS(inode_t,         uint64_t)                                            \
711cb0ef41Sopenharmony_ci  ALIAS(linkcount_t,     uint64_t)                                            \
721cb0ef41Sopenharmony_ci  ALIAS(lookupflags_t,   uint32_t)                                            \
731cb0ef41Sopenharmony_ci  ALIAS(oflags_t,        uint16_t)                                            \
741cb0ef41Sopenharmony_ci  ALIAS(preopentype_t,   uint8_t)                                             \
751cb0ef41Sopenharmony_ci  ALIAS(riflags_t,       uint16_t)                                            \
761cb0ef41Sopenharmony_ci  ALIAS(rights_t,        uint64_t)                                            \
771cb0ef41Sopenharmony_ci  ALIAS(roflags_t,       uint16_t)                                            \
781cb0ef41Sopenharmony_ci  ALIAS(sdflags_t,       uint8_t)                                             \
791cb0ef41Sopenharmony_ci  ALIAS(siflags_t,       uint16_t)                                            \
801cb0ef41Sopenharmony_ci  ALIAS(signal_t,        uint8_t)                                             \
811cb0ef41Sopenharmony_ci  ALIAS(size_t,          uint32_t)                                            \
821cb0ef41Sopenharmony_ci  ALIAS(subclockflags_t, uint16_t)                                            \
831cb0ef41Sopenharmony_ci  ALIAS(timestamp_t,     uint64_t)                                            \
841cb0ef41Sopenharmony_ci  ALIAS(userdata_t,      uint64_t)                                            \
851cb0ef41Sopenharmony_ci  ALIAS(whence_t,        uint8_t)                                             \
861cb0ef41Sopenharmony_ci                                                                              \
871cb0ef41Sopenharmony_ci  STRUCT(dirent_t) {                                                          \
881cb0ef41Sopenharmony_ci    FIELD( 0, dircookie_t, d_next);                                           \
891cb0ef41Sopenharmony_ci    FIELD( 8, inode_t,     d_ino);                                            \
901cb0ef41Sopenharmony_ci    FIELD(16, uint32_t,    d_namlen);                                         \
911cb0ef41Sopenharmony_ci    FIELD(20, filetype_t,  d_type);                                           \
921cb0ef41Sopenharmony_ci  }                                                                           \
931cb0ef41Sopenharmony_ci                                                                              \
941cb0ef41Sopenharmony_ci  STRUCT(fdstat_t) {                                                          \
951cb0ef41Sopenharmony_ci    FIELD( 0, filetype_t, fs_filetype);                                       \
961cb0ef41Sopenharmony_ci    FIELD( 2, fdflags_t,  fs_flags);                                          \
971cb0ef41Sopenharmony_ci    FIELD( 8, rights_t,   fs_rights_base);                                    \
981cb0ef41Sopenharmony_ci    FIELD(16, rights_t,   fs_rights_inheriting);                              \
991cb0ef41Sopenharmony_ci  }                                                                           \
1001cb0ef41Sopenharmony_ci                                                                              \
1011cb0ef41Sopenharmony_ci  STRUCT(filestat_t) {                                                        \
1021cb0ef41Sopenharmony_ci    FIELD( 0, device_t,    st_dev);                                           \
1031cb0ef41Sopenharmony_ci    FIELD( 8, inode_t,     st_ino);                                           \
1041cb0ef41Sopenharmony_ci    FIELD(16, filetype_t,  st_filetype);                                      \
1051cb0ef41Sopenharmony_ci    FIELD(24, linkcount_t, st_nlink);                                         \
1061cb0ef41Sopenharmony_ci    FIELD(32, filesize_t,  st_size);                                          \
1071cb0ef41Sopenharmony_ci    FIELD(40, timestamp_t, st_atim);                                          \
1081cb0ef41Sopenharmony_ci    FIELD(48, timestamp_t, st_mtim);                                          \
1091cb0ef41Sopenharmony_ci    FIELD(56, timestamp_t, st_ctim);                                          \
1101cb0ef41Sopenharmony_ci  }                                                                           \
1111cb0ef41Sopenharmony_ci                                                                              \
1121cb0ef41Sopenharmony_ci  STRUCT(prestat_t) {                                                         \
1131cb0ef41Sopenharmony_ci    FIELD(0, preopentype_t, pr_type);                                         \
1141cb0ef41Sopenharmony_ci    FIELD(4, uint32_t,      u.dir.pr_name_len);                               \
1151cb0ef41Sopenharmony_ci  }                                                                           \
1161cb0ef41Sopenharmony_ci                                                                              \
1171cb0ef41Sopenharmony_ci  STRUCT(event_t) {                                                           \
1181cb0ef41Sopenharmony_ci    FIELD( 0, userdata_t,  userdata);                                         \
1191cb0ef41Sopenharmony_ci    FIELD( 8, errno_t,     error);                                            \
1201cb0ef41Sopenharmony_ci    FIELD(10, eventtype_t, type);                                             \
1211cb0ef41Sopenharmony_ci    TYPE_SWITCH {                                                             \
1221cb0ef41Sopenharmony_ci      case UVWASI_EVENTTYPE_FD_READ:                                          \
1231cb0ef41Sopenharmony_ci      case UVWASI_EVENTTYPE_FD_WRITE:                                         \
1241cb0ef41Sopenharmony_ci        FIELD(16, filesize_t,     u.fd_readwrite.nbytes);                     \
1251cb0ef41Sopenharmony_ci        FIELD(24, eventrwflags_t, u.fd_readwrite.flags);                      \
1261cb0ef41Sopenharmony_ci    }                                                                         \
1271cb0ef41Sopenharmony_ci  }                                                                           \
1281cb0ef41Sopenharmony_ci                                                                              \
1291cb0ef41Sopenharmony_ci  STRUCT(subscription_t) {                                                    \
1301cb0ef41Sopenharmony_ci    FIELD(0, userdata_t,  userdata);                                          \
1311cb0ef41Sopenharmony_ci    FIELD(8, eventtype_t, type);                                              \
1321cb0ef41Sopenharmony_ci    TYPE_SWITCH {                                                             \
1331cb0ef41Sopenharmony_ci      case UVWASI_EVENTTYPE_CLOCK:                                            \
1341cb0ef41Sopenharmony_ci        FIELD(16, clockid_t,       u.clock.clock_id);                         \
1351cb0ef41Sopenharmony_ci        FIELD(24, timestamp_t,     u.clock.timeout);                          \
1361cb0ef41Sopenharmony_ci        FIELD(32, timestamp_t,     u.clock.precision);                        \
1371cb0ef41Sopenharmony_ci        FIELD(40, subclockflags_t, u.clock.flags);                            \
1381cb0ef41Sopenharmony_ci        break;                                                                \
1391cb0ef41Sopenharmony_ci      case UVWASI_EVENTTYPE_FD_READ:                                          \
1401cb0ef41Sopenharmony_ci      case UVWASI_EVENTTYPE_FD_WRITE:                                         \
1411cb0ef41Sopenharmony_ci        FIELD(16, fd_t, u.fd_readwrite.fd);                                   \
1421cb0ef41Sopenharmony_ci    }                                                                         \
1431cb0ef41Sopenharmony_ci  }                                                                           \
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci#define WRITE_STRUCT(name)                                                    \
1461cb0ef41Sopenharmony_ci  void uvwasi_serdes_write_##name(void* ptr,                                  \
1471cb0ef41Sopenharmony_ci                                  size_t offset,                              \
1481cb0ef41Sopenharmony_ci                                  const uvwasi_##name* value)                 \
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci#define READ_STRUCT(name)                                                     \
1511cb0ef41Sopenharmony_ci  void uvwasi_serdes_read_##name(const void* ptr,                             \
1521cb0ef41Sopenharmony_ci                                 size_t offset,                               \
1531cb0ef41Sopenharmony_ci                                 uvwasi_##name* value)                        \
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci#define WRITE_FIELD(field_offset, type, field)                                \
1561cb0ef41Sopenharmony_ci  do {                                                                        \
1571cb0ef41Sopenharmony_ci    uvwasi_serdes_write_##type(ptr, offset + field_offset, value->field);     \
1581cb0ef41Sopenharmony_ci  } while (0)                                                                 \
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci#define READ_FIELD(field_offset, type, field)                                 \
1611cb0ef41Sopenharmony_ci  do {                                                                        \
1621cb0ef41Sopenharmony_ci    value->field = uvwasi_serdes_read_##type(ptr, offset + field_offset);     \
1631cb0ef41Sopenharmony_ci  } while (0)                                                                 \
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci#define WRITE_ALIAS(new_name, old_name)                                       \
1661cb0ef41Sopenharmony_ci  void uvwasi_serdes_write_##new_name(void* ptr,                              \
1671cb0ef41Sopenharmony_ci                                      size_t offset,                          \
1681cb0ef41Sopenharmony_ci                                      uvwasi_##new_name value) {              \
1691cb0ef41Sopenharmony_ci    uvwasi_serdes_write_##old_name(ptr, offset, value);                       \
1701cb0ef41Sopenharmony_ci  }                                                                           \
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci#define READ_ALIAS(new_name, old_name)                                        \
1731cb0ef41Sopenharmony_ci  uvwasi_##new_name uvwasi_serdes_read_##new_name(const void* ptr,            \
1741cb0ef41Sopenharmony_ci                                                  size_t offset) {            \
1751cb0ef41Sopenharmony_ci    return uvwasi_serdes_read_##old_name(ptr, offset);                        \
1761cb0ef41Sopenharmony_ci  }                                                                           \
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ciALL_TYPES(WRITE_STRUCT, WRITE_FIELD, WRITE_ALIAS)
1791cb0ef41Sopenharmony_ciALL_TYPES(READ_STRUCT, READ_FIELD, READ_ALIAS)
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ciuvwasi_errno_t uvwasi_serdes_read_ciovec_t(const void* ptr,
1831cb0ef41Sopenharmony_ci                                           size_t end,
1841cb0ef41Sopenharmony_ci                                           size_t offset,
1851cb0ef41Sopenharmony_ci                                           uvwasi_ciovec_t* value) {
1861cb0ef41Sopenharmony_ci  uint32_t buf_ptr;
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci  buf_ptr = uvwasi_serdes_read_uint32_t(ptr, offset);
1891cb0ef41Sopenharmony_ci  value->buf_len = uvwasi_serdes_read_size_t(ptr, offset + 4);
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci  if (!uvwasi_serdes_check_bounds(buf_ptr, end, value->buf_len))
1921cb0ef41Sopenharmony_ci    return UVWASI_EOVERFLOW;
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  value->buf = ((uint8_t*) ptr + buf_ptr);
1951cb0ef41Sopenharmony_ci  return UVWASI_ESUCCESS;
1961cb0ef41Sopenharmony_ci}
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ciuvwasi_errno_t uvwasi_serdes_read_iovec_t(const void* ptr,
2001cb0ef41Sopenharmony_ci                                          size_t end,
2011cb0ef41Sopenharmony_ci                                          size_t offset,
2021cb0ef41Sopenharmony_ci                                          uvwasi_iovec_t* value) {
2031cb0ef41Sopenharmony_ci  uint32_t buf_ptr;
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  buf_ptr = uvwasi_serdes_read_uint32_t(ptr, offset);
2061cb0ef41Sopenharmony_ci  value->buf_len = uvwasi_serdes_read_size_t(ptr, offset + 4);
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci  if (!uvwasi_serdes_check_bounds(buf_ptr, end, value->buf_len))
2091cb0ef41Sopenharmony_ci    return UVWASI_EOVERFLOW;
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci  value->buf = ((uint8_t*) ptr + buf_ptr);
2121cb0ef41Sopenharmony_ci  return UVWASI_ESUCCESS;
2131cb0ef41Sopenharmony_ci}
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ciuvwasi_errno_t uvwasi_serdes_readv_ciovec_t(const void* ptr,
2171cb0ef41Sopenharmony_ci                                            size_t end,
2181cb0ef41Sopenharmony_ci                                            size_t offset,
2191cb0ef41Sopenharmony_ci                                            uvwasi_ciovec_t* iovs,
2201cb0ef41Sopenharmony_ci                                            uvwasi_size_t iovs_len) {
2211cb0ef41Sopenharmony_ci  uvwasi_errno_t err;
2221cb0ef41Sopenharmony_ci  uvwasi_size_t i;
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci  for (i = 0; i < iovs_len; i++) {
2251cb0ef41Sopenharmony_ci    err = uvwasi_serdes_read_ciovec_t(ptr, end, offset, &iovs[i]);
2261cb0ef41Sopenharmony_ci    if (err != UVWASI_ESUCCESS)
2271cb0ef41Sopenharmony_ci      return err;
2281cb0ef41Sopenharmony_ci    offset += UVWASI_SERDES_SIZE_ciovec_t;
2291cb0ef41Sopenharmony_ci  }
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci  return UVWASI_ESUCCESS;
2321cb0ef41Sopenharmony_ci}
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ciuvwasi_errno_t uvwasi_serdes_readv_iovec_t(const void* ptr,
2361cb0ef41Sopenharmony_ci                                           size_t end,
2371cb0ef41Sopenharmony_ci                                           size_t offset,
2381cb0ef41Sopenharmony_ci                                           uvwasi_iovec_t* iovs,
2391cb0ef41Sopenharmony_ci                                           uvwasi_size_t iovs_len) {
2401cb0ef41Sopenharmony_ci  uvwasi_errno_t err;
2411cb0ef41Sopenharmony_ci  uvwasi_size_t i;
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  for (i = 0; i < iovs_len; i++) {
2441cb0ef41Sopenharmony_ci    err = uvwasi_serdes_read_iovec_t(ptr, end, offset, &iovs[i]);
2451cb0ef41Sopenharmony_ci    if (err != UVWASI_ESUCCESS)
2461cb0ef41Sopenharmony_ci      return err;
2471cb0ef41Sopenharmony_ci    offset += UVWASI_SERDES_SIZE_iovec_t;
2481cb0ef41Sopenharmony_ci  }
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci  return UVWASI_ESUCCESS;
2511cb0ef41Sopenharmony_ci}
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ciint uvwasi_serdes_check_bounds(size_t offset, size_t end, size_t size) {
2551cb0ef41Sopenharmony_ci  return end > offset && size <= (end - offset);
2561cb0ef41Sopenharmony_ci}
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ciint uvwasi_serdes_check_array_bounds(size_t offset,
2601cb0ef41Sopenharmony_ci                                     size_t end,
2611cb0ef41Sopenharmony_ci                                     size_t size,
2621cb0ef41Sopenharmony_ci                                     size_t count) {
2631cb0ef41Sopenharmony_ci  return end > offset &&
2641cb0ef41Sopenharmony_ci         ((count * size) / size == count) &&
2651cb0ef41Sopenharmony_ci         (count * size <= end - offset);
2661cb0ef41Sopenharmony_ci}
267