Skip to content

Commit 7579e29

Browse files
addaleaxcjihrig
authored andcommitted
keep referential integrity for file table entries
Before this, some functions such as `uvwasi_path_open()` could crash, because they acquired a reference to a fd table entry using `uvwasi_fd_table_get()` and continued to use the result after calling `uvwasi_fd_table_insert_fd()`; however, the latter could `realloc()` the fd table, potentially invalidating the earlier return value of `uvwasi_fd_table_get()`. Since the previous commit introduced a per-fd allocation anyway, this modifies the code to allocate the table entry itself as part of that allocation. This ensures referential integrity for the table entry. (Aside -- I’m not sure that it was valid to call `uv_mutex_init()` and then move that mutex around in memory, either.)
1 parent 20d20fe commit 7579e29

File tree

2 files changed

+22
-19
lines changed

2 files changed

+22
-19
lines changed

include/fd_table.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@ struct uvwasi_fd_wrap_t {
1717
uvwasi_rights_t rights_base;
1818
uvwasi_rights_t rights_inheriting;
1919
int preopen;
20-
int valid;
2120
uv_mutex_t mutex;
2221
};
2322

2423
struct uvwasi_fd_table_t {
25-
struct uvwasi_fd_wrap_t* fds;
24+
struct uvwasi_fd_wrap_t** fds;
2625
uint32_t size;
2726
uint32_t used;
2827
uv_rwlock_t rwlock;

src/fd_table.c

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ static uvwasi_errno_t uvwasi__fd_table_insert(uvwasi_t* uvwasi,
187187
int preopen,
188188
struct uvwasi_fd_wrap_t** wrap) {
189189
struct uvwasi_fd_wrap_t* entry;
190-
struct uvwasi_fd_wrap_t* new_fds;
190+
struct uvwasi_fd_wrap_t** new_fds;
191191
uvwasi_errno_t err;
192192
uint32_t new_size;
193193
int index;
@@ -200,8 +200,11 @@ static uvwasi_errno_t uvwasi__fd_table_insert(uvwasi_t* uvwasi,
200200

201201
mp_len = strlen(mapped_path);
202202
rp_len = strlen(real_path);
203-
mp_copy = uvwasi__malloc(uvwasi, mp_len + rp_len + 2);
204-
if (mp_copy == NULL) return UVWASI_ENOMEM;
203+
entry = (struct uvwasi_fd_wrap_t*)
204+
uvwasi__malloc(uvwasi, sizeof(*entry) + mp_len + rp_len + 2);
205+
if (entry == NULL) return UVWASI_ENOMEM;
206+
207+
mp_copy = (char*)(entry + 1);
205208
rp_copy = mp_copy + mp_len + 1;
206209
memcpy(mp_copy, mapped_path, mp_len);
207210
mp_copy[mp_len] = '\0';
@@ -215,12 +218,13 @@ static uvwasi_errno_t uvwasi__fd_table_insert(uvwasi_t* uvwasi,
215218
new_size = table->size * 2;
216219
new_fds = uvwasi__realloc(uvwasi, table->fds, new_size * sizeof(*new_fds));
217220
if (new_fds == NULL) {
221+
uvwasi__free(uvwasi, entry);
218222
err = UVWASI_ENOMEM;
219223
goto exit;
220224
}
221225

222226
for (i = table->size; i < new_size; ++i)
223-
new_fds[i].valid = 0;
227+
new_fds[i] = NULL;
224228

225229
index = table->size;
226230
table->fds = new_fds;
@@ -229,20 +233,21 @@ static uvwasi_errno_t uvwasi__fd_table_insert(uvwasi_t* uvwasi,
229233
/* The table is big enough, so find an empty slot for the new data. */
230234
index = -1;
231235
for (i = 0; i < table->size; ++i) {
232-
if (table->fds[i].valid != 1) {
236+
if (table->fds[i] == NULL) {
233237
index = i;
234238
break;
235239
}
236240
}
237241

238242
/* index should never be -1. */
239243
if (index == -1) {
244+
uvwasi__free(uvwasi, entry);
240245
err = UVWASI_ENOSPC;
241246
goto exit;
242247
}
243248
}
244249

245-
entry = &table->fds[index];
250+
table->fds[index] = entry;
246251

247252
r = uv_mutex_init(&entry->mutex);
248253
if (r != 0) {
@@ -258,7 +263,6 @@ static uvwasi_errno_t uvwasi__fd_table_insert(uvwasi_t* uvwasi,
258263
entry->rights_base = rights_base;
259264
entry->rights_inheriting = rights_inheriting;
260265
entry->preopen = preopen;
261-
entry->valid = 1;
262266
table->used++;
263267

264268
if (wrap != NULL)
@@ -295,7 +299,7 @@ uvwasi_errno_t uvwasi_fd_table_init(uvwasi_t* uvwasi,
295299
table->size = init_size;
296300
table->fds = uvwasi__calloc(uvwasi,
297301
init_size,
298-
sizeof(struct uvwasi_fd_wrap_t));
302+
sizeof(struct uvwasi_fd_wrap_t*));
299303

300304
if (table->fds == NULL) {
301305
err = UVWASI_ENOMEM;
@@ -346,11 +350,11 @@ void uvwasi_fd_table_free(uvwasi_t* uvwasi, struct uvwasi_fd_table_t* table) {
346350
return;
347351

348352
for (i = 0; i < table->size; i++) {
349-
entry = &table->fds[i];
350-
if (!entry->valid) continue;
353+
entry = table->fds[i];
354+
if (entry == NULL) continue;
351355

352-
uvwasi__free(uvwasi, entry->path);
353356
uv_mutex_destroy(&entry->mutex);
357+
uvwasi__free(uvwasi, entry);
354358
}
355359

356360
uvwasi__free(uvwasi, table->fds);
@@ -455,9 +459,9 @@ uvwasi_errno_t uvwasi_fd_table_get(const struct uvwasi_fd_table_t* table,
455459
goto exit;
456460
}
457461

458-
entry = &table->fds[id];
462+
entry = table->fds[id];
459463

460-
if (entry->valid != 1 || entry->id != id) {
464+
if (entry == NULL || entry->id != id) {
461465
err = UVWASI_EBADF;
462466
goto exit;
463467
}
@@ -494,16 +498,16 @@ uvwasi_errno_t uvwasi_fd_table_remove(uvwasi_t* uvwasi,
494498
goto exit;
495499
}
496500

497-
entry = &table->fds[id];
501+
entry = table->fds[id];
498502

499-
if (entry->valid != 1 || entry->id != id) {
503+
if (entry == NULL || entry->id != id) {
500504
err = UVWASI_EBADF;
501505
goto exit;
502506
}
503507

504-
uvwasi__free(uvwasi, entry->path);
505508
uv_mutex_destroy(&entry->mutex);
506-
entry->valid = 0;
509+
uvwasi__free(uvwasi, entry);
510+
table->fds[id] = NULL;
507511
table->used--;
508512
err = UVWASI_ESUCCESS;
509513
exit:

0 commit comments

Comments
 (0)