1#include "wasi_serdes.h" 2#include "wasi_types.h" 3 4void uvwasi_serdes_write_uint64_t(void* ptr, 5 size_t offset, 6 uint64_t value) { 7 uvwasi_serdes_write_uint32_t(ptr, offset, (uint32_t) value); 8 uvwasi_serdes_write_uint32_t(ptr, offset + 4, value >> 32); 9} 10 11void uvwasi_serdes_write_uint32_t(void* ptr, 12 size_t offset, 13 uint32_t value) { 14 uvwasi_serdes_write_uint16_t(ptr, offset, (uint16_t) value); 15 uvwasi_serdes_write_uint16_t(ptr, offset + 2, value >> 16); 16} 17 18void uvwasi_serdes_write_uint16_t(void* ptr, 19 size_t offset, 20 uint16_t value) { 21 uvwasi_serdes_write_uint8_t(ptr, offset, (uint8_t) value); 22 uvwasi_serdes_write_uint8_t(ptr, offset + 1, value >> 8); 23} 24 25void uvwasi_serdes_write_uint8_t(void* ptr, 26 size_t offset, 27 uint8_t value) { 28 ((uint8_t*) ptr)[offset] = value; 29} 30 31uint64_t uvwasi_serdes_read_uint64_t(const void* ptr, size_t offset) { 32 uint64_t low = uvwasi_serdes_read_uint32_t(ptr, offset); 33 uint64_t high = uvwasi_serdes_read_uint32_t(ptr, offset + 4); 34 return low | (high << 32); 35} 36 37uint32_t uvwasi_serdes_read_uint32_t(const void* ptr, size_t offset) { 38 uint32_t low = uvwasi_serdes_read_uint16_t(ptr, offset); 39 uint32_t high = uvwasi_serdes_read_uint16_t(ptr, offset + 2); 40 return low | (high << 16); 41} 42 43uint16_t uvwasi_serdes_read_uint16_t(const void* ptr, size_t offset) { 44 uint16_t low = uvwasi_serdes_read_uint8_t(ptr, offset); 45 uint16_t high = uvwasi_serdes_read_uint8_t(ptr, offset + 1); 46 return low | (high << 8); 47} 48 49uint8_t uvwasi_serdes_read_uint8_t(const void* ptr, size_t offset) { 50 return ((const uint8_t*) ptr)[offset]; 51} 52 53#define TYPE_SWITCH switch (value->type) 54 55#define ALL_TYPES(STRUCT, FIELD, ALIAS) \ 56 \ 57 ALIAS(advice_t, uint8_t) \ 58 ALIAS(clockid_t, uint32_t) \ 59 ALIAS(device_t, uint64_t) \ 60 ALIAS(dircookie_t, uint64_t) \ 61 ALIAS(errno_t, uint16_t) \ 62 ALIAS(eventrwflags_t, uint16_t) \ 63 ALIAS(eventtype_t, uint8_t) \ 64 ALIAS(exitcode_t, uint32_t) \ 65 ALIAS(fd_t, uint32_t) \ 66 ALIAS(fdflags_t, uint16_t) \ 67 ALIAS(filesize_t, uint64_t) \ 68 ALIAS(filetype_t, uint8_t) \ 69 ALIAS(fstflags_t, uint16_t) \ 70 ALIAS(inode_t, uint64_t) \ 71 ALIAS(linkcount_t, uint64_t) \ 72 ALIAS(lookupflags_t, uint32_t) \ 73 ALIAS(oflags_t, uint16_t) \ 74 ALIAS(preopentype_t, uint8_t) \ 75 ALIAS(riflags_t, uint16_t) \ 76 ALIAS(rights_t, uint64_t) \ 77 ALIAS(roflags_t, uint16_t) \ 78 ALIAS(sdflags_t, uint8_t) \ 79 ALIAS(siflags_t, uint16_t) \ 80 ALIAS(signal_t, uint8_t) \ 81 ALIAS(size_t, uint32_t) \ 82 ALIAS(subclockflags_t, uint16_t) \ 83 ALIAS(timestamp_t, uint64_t) \ 84 ALIAS(userdata_t, uint64_t) \ 85 ALIAS(whence_t, uint8_t) \ 86 \ 87 STRUCT(dirent_t) { \ 88 FIELD( 0, dircookie_t, d_next); \ 89 FIELD( 8, inode_t, d_ino); \ 90 FIELD(16, uint32_t, d_namlen); \ 91 FIELD(20, filetype_t, d_type); \ 92 } \ 93 \ 94 STRUCT(fdstat_t) { \ 95 FIELD( 0, filetype_t, fs_filetype); \ 96 FIELD( 2, fdflags_t, fs_flags); \ 97 FIELD( 8, rights_t, fs_rights_base); \ 98 FIELD(16, rights_t, fs_rights_inheriting); \ 99 } \ 100 \ 101 STRUCT(filestat_t) { \ 102 FIELD( 0, device_t, st_dev); \ 103 FIELD( 8, inode_t, st_ino); \ 104 FIELD(16, filetype_t, st_filetype); \ 105 FIELD(24, linkcount_t, st_nlink); \ 106 FIELD(32, filesize_t, st_size); \ 107 FIELD(40, timestamp_t, st_atim); \ 108 FIELD(48, timestamp_t, st_mtim); \ 109 FIELD(56, timestamp_t, st_ctim); \ 110 } \ 111 \ 112 STRUCT(prestat_t) { \ 113 FIELD(0, preopentype_t, pr_type); \ 114 FIELD(4, uint32_t, u.dir.pr_name_len); \ 115 } \ 116 \ 117 STRUCT(event_t) { \ 118 FIELD( 0, userdata_t, userdata); \ 119 FIELD( 8, errno_t, error); \ 120 FIELD(10, eventtype_t, type); \ 121 TYPE_SWITCH { \ 122 case UVWASI_EVENTTYPE_FD_READ: \ 123 case UVWASI_EVENTTYPE_FD_WRITE: \ 124 FIELD(16, filesize_t, u.fd_readwrite.nbytes); \ 125 FIELD(24, eventrwflags_t, u.fd_readwrite.flags); \ 126 } \ 127 } \ 128 \ 129 STRUCT(subscription_t) { \ 130 FIELD(0, userdata_t, userdata); \ 131 FIELD(8, eventtype_t, type); \ 132 TYPE_SWITCH { \ 133 case UVWASI_EVENTTYPE_CLOCK: \ 134 FIELD(16, clockid_t, u.clock.clock_id); \ 135 FIELD(24, timestamp_t, u.clock.timeout); \ 136 FIELD(32, timestamp_t, u.clock.precision); \ 137 FIELD(40, subclockflags_t, u.clock.flags); \ 138 break; \ 139 case UVWASI_EVENTTYPE_FD_READ: \ 140 case UVWASI_EVENTTYPE_FD_WRITE: \ 141 FIELD(16, fd_t, u.fd_readwrite.fd); \ 142 } \ 143 } \ 144 145#define WRITE_STRUCT(name) \ 146 void uvwasi_serdes_write_##name(void* ptr, \ 147 size_t offset, \ 148 const uvwasi_##name* value) \ 149 150#define READ_STRUCT(name) \ 151 void uvwasi_serdes_read_##name(const void* ptr, \ 152 size_t offset, \ 153 uvwasi_##name* value) \ 154 155#define WRITE_FIELD(field_offset, type, field) \ 156 do { \ 157 uvwasi_serdes_write_##type(ptr, offset + field_offset, value->field); \ 158 } while (0) \ 159 160#define READ_FIELD(field_offset, type, field) \ 161 do { \ 162 value->field = uvwasi_serdes_read_##type(ptr, offset + field_offset); \ 163 } while (0) \ 164 165#define WRITE_ALIAS(new_name, old_name) \ 166 void uvwasi_serdes_write_##new_name(void* ptr, \ 167 size_t offset, \ 168 uvwasi_##new_name value) { \ 169 uvwasi_serdes_write_##old_name(ptr, offset, value); \ 170 } \ 171 172#define READ_ALIAS(new_name, old_name) \ 173 uvwasi_##new_name uvwasi_serdes_read_##new_name(const void* ptr, \ 174 size_t offset) { \ 175 return uvwasi_serdes_read_##old_name(ptr, offset); \ 176 } \ 177 178ALL_TYPES(WRITE_STRUCT, WRITE_FIELD, WRITE_ALIAS) 179ALL_TYPES(READ_STRUCT, READ_FIELD, READ_ALIAS) 180 181 182uvwasi_errno_t uvwasi_serdes_read_ciovec_t(const void* ptr, 183 size_t end, 184 size_t offset, 185 uvwasi_ciovec_t* value) { 186 uint32_t buf_ptr; 187 188 buf_ptr = uvwasi_serdes_read_uint32_t(ptr, offset); 189 value->buf_len = uvwasi_serdes_read_size_t(ptr, offset + 4); 190 191 if (!uvwasi_serdes_check_bounds(buf_ptr, end, value->buf_len)) 192 return UVWASI_EOVERFLOW; 193 194 value->buf = ((uint8_t*) ptr + buf_ptr); 195 return UVWASI_ESUCCESS; 196} 197 198 199uvwasi_errno_t uvwasi_serdes_read_iovec_t(const void* ptr, 200 size_t end, 201 size_t offset, 202 uvwasi_iovec_t* value) { 203 uint32_t buf_ptr; 204 205 buf_ptr = uvwasi_serdes_read_uint32_t(ptr, offset); 206 value->buf_len = uvwasi_serdes_read_size_t(ptr, offset + 4); 207 208 if (!uvwasi_serdes_check_bounds(buf_ptr, end, value->buf_len)) 209 return UVWASI_EOVERFLOW; 210 211 value->buf = ((uint8_t*) ptr + buf_ptr); 212 return UVWASI_ESUCCESS; 213} 214 215 216uvwasi_errno_t uvwasi_serdes_readv_ciovec_t(const void* ptr, 217 size_t end, 218 size_t offset, 219 uvwasi_ciovec_t* iovs, 220 uvwasi_size_t iovs_len) { 221 uvwasi_errno_t err; 222 uvwasi_size_t i; 223 224 for (i = 0; i < iovs_len; i++) { 225 err = uvwasi_serdes_read_ciovec_t(ptr, end, offset, &iovs[i]); 226 if (err != UVWASI_ESUCCESS) 227 return err; 228 offset += UVWASI_SERDES_SIZE_ciovec_t; 229 } 230 231 return UVWASI_ESUCCESS; 232} 233 234 235uvwasi_errno_t uvwasi_serdes_readv_iovec_t(const void* ptr, 236 size_t end, 237 size_t offset, 238 uvwasi_iovec_t* iovs, 239 uvwasi_size_t iovs_len) { 240 uvwasi_errno_t err; 241 uvwasi_size_t i; 242 243 for (i = 0; i < iovs_len; i++) { 244 err = uvwasi_serdes_read_iovec_t(ptr, end, offset, &iovs[i]); 245 if (err != UVWASI_ESUCCESS) 246 return err; 247 offset += UVWASI_SERDES_SIZE_iovec_t; 248 } 249 250 return UVWASI_ESUCCESS; 251} 252 253 254int uvwasi_serdes_check_bounds(size_t offset, size_t end, size_t size) { 255 return end > offset && size <= (end - offset); 256} 257 258 259int uvwasi_serdes_check_array_bounds(size_t offset, 260 size_t end, 261 size_t size, 262 size_t count) { 263 return end > offset && 264 ((count * size) / size == count) && 265 (count * size <= end - offset); 266} 267