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