• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "wasi_serdes.h"
2 #include "wasi_types.h"
3 
uvwasi_serdes_write_uint64_t(void * ptr,size_t offset,uint64_t value)4 void 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 
uvwasi_serdes_write_uint32_t(void * ptr,size_t offset,uint32_t value)11 void 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 
uvwasi_serdes_write_uint16_t(void * ptr,size_t offset,uint16_t value)18 void 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 
uvwasi_serdes_write_uint8_t(void * ptr,size_t offset,uint8_t value)25 void uvwasi_serdes_write_uint8_t(void* ptr,
26                                  size_t offset,
27                                  uint8_t value) {
28   ((uint8_t*) ptr)[offset] = value;
29 }
30 
uvwasi_serdes_read_uint64_t(const void * ptr,size_t offset)31 uint64_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 
uvwasi_serdes_read_uint32_t(const void * ptr,size_t offset)37 uint32_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 
uvwasi_serdes_read_uint16_t(const void * ptr,size_t offset)43 uint16_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 
uvwasi_serdes_read_uint8_t(const void * ptr,size_t offset)49 uint8_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 
ALL_TYPES(WRITE_STRUCT,WRITE_FIELD,WRITE_ALIAS)178 ALL_TYPES(WRITE_STRUCT, WRITE_FIELD, WRITE_ALIAS)
179 ALL_TYPES(READ_STRUCT, READ_FIELD, READ_ALIAS)
180 
181 
182 uvwasi_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 
uvwasi_serdes_read_iovec_t(const void * ptr,size_t end,size_t offset,uvwasi_iovec_t * value)199 uvwasi_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 
uvwasi_serdes_readv_ciovec_t(const void * ptr,size_t end,size_t offset,uvwasi_ciovec_t * iovs,uvwasi_size_t iovs_len)216 uvwasi_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 
uvwasi_serdes_readv_iovec_t(const void * ptr,size_t end,size_t offset,uvwasi_iovec_t * iovs,uvwasi_size_t iovs_len)235 uvwasi_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 
uvwasi_serdes_check_bounds(size_t offset,size_t end,size_t size)254 int uvwasi_serdes_check_bounds(size_t offset, size_t end, size_t size) {
255   return end > offset && size <= (end - offset);
256 }
257 
258 
uvwasi_serdes_check_array_bounds(size_t offset,size_t end,size_t size,size_t count)259 int 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