Skip to content

Commit

Permalink
do not use PATH_MAX_BYTES for fd table
Browse files Browse the repository at this point in the history
This would usually waste memory otherwise. Instead, store the
mapped path and the realpath in a separate buffer per-entry.

As a drive-by fix, this also destroys the per-fd mutexes now
in `uvwasi_fd_table_free()`.
  • Loading branch information
addaleax authored and cjihrig committed Dec 4, 2019
1 parent 3bf0fb2 commit 20d20fe
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 19 deletions.
17 changes: 4 additions & 13 deletions include/fd_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,13 @@
#include "wasi_types.h"
#include "uv_mapping.h"

/* TODO(cjihrig): PATH_MAX_BYTES shouldn't be stack allocated. On Windows, paths
can be 32k long, and this PATH_MAX_BYTES is an artificial limitation. */
#ifdef _WIN32
/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
# define PATH_MAX_BYTES (MAX_PATH * 4)
#else
# include <limits.h>
# define PATH_MAX_BYTES (PATH_MAX)
#endif

struct uvwasi_s;

struct uvwasi_fd_wrap_t {
uvwasi_fd_t id;
uv_file fd;
char path[PATH_MAX_BYTES];
char real_path[PATH_MAX_BYTES];
char* path;
char* real_path;
uvwasi_filetype_t type;
uvwasi_rights_t rights_base;
uvwasi_rights_t rights_inheriting;
Expand Down Expand Up @@ -61,7 +51,8 @@ uvwasi_errno_t uvwasi_fd_table_get(const struct uvwasi_fd_table_t* table,
struct uvwasi_fd_wrap_t** wrap,
uvwasi_rights_t rights_base,
uvwasi_rights_t rights_inheriting);
uvwasi_errno_t uvwasi_fd_table_remove(struct uvwasi_fd_table_t* table,
uvwasi_errno_t uvwasi_fd_table_remove(struct uvwasi_s* uvwasi,
struct uvwasi_fd_table_t* table,
const uvwasi_fd_t id);

#endif /* __UVWASI_FD_TABLE_H__ */
33 changes: 30 additions & 3 deletions src/fd_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,20 @@ static uvwasi_errno_t uvwasi__fd_table_insert(uvwasi_t* uvwasi,
int index;
uint32_t i;
int r;
size_t mp_len;
char* mp_copy;
size_t rp_len;
char* rp_copy;

mp_len = strlen(mapped_path);
rp_len = strlen(real_path);
mp_copy = uvwasi__malloc(uvwasi, mp_len + rp_len + 2);
if (mp_copy == NULL) return UVWASI_ENOMEM;
rp_copy = mp_copy + mp_len + 1;
memcpy(mp_copy, mapped_path, mp_len);
mp_copy[mp_len] = '\0';
memcpy(rp_copy, real_path, rp_len);
rp_copy[rp_len] = '\0';

uv_rwlock_wrlock(&table->rwlock);

Expand Down Expand Up @@ -238,8 +252,8 @@ static uvwasi_errno_t uvwasi__fd_table_insert(uvwasi_t* uvwasi,

entry->id = index;
entry->fd = fd;
strcpy(entry->path, mapped_path);
strcpy(entry->real_path, real_path);
entry->path = mp_copy;
entry->real_path = rp_copy;
entry->type = type;
entry->rights_base = rights_base;
entry->rights_inheriting = rights_inheriting;
Expand Down Expand Up @@ -325,9 +339,20 @@ uvwasi_errno_t uvwasi_fd_table_init(uvwasi_t* uvwasi,


void uvwasi_fd_table_free(uvwasi_t* uvwasi, struct uvwasi_fd_table_t* table) {
struct uvwasi_fd_wrap_t* entry;
uint32_t i;

if (table == NULL)
return;

for (i = 0; i < table->size; i++) {
entry = &table->fds[i];
if (!entry->valid) continue;

uvwasi__free(uvwasi, entry->path);
uv_mutex_destroy(&entry->mutex);
}

uvwasi__free(uvwasi, table->fds);
table->fds = NULL;
table->size = 0;
Expand Down Expand Up @@ -453,7 +478,8 @@ uvwasi_errno_t uvwasi_fd_table_get(const struct uvwasi_fd_table_t* table,
}


uvwasi_errno_t uvwasi_fd_table_remove(struct uvwasi_fd_table_t* table,
uvwasi_errno_t uvwasi_fd_table_remove(uvwasi_t* uvwasi,
struct uvwasi_fd_table_t* table,
const uvwasi_fd_t id) {
struct uvwasi_fd_wrap_t* entry;
uvwasi_errno_t err;
Expand All @@ -475,6 +501,7 @@ uvwasi_errno_t uvwasi_fd_table_remove(struct uvwasi_fd_table_t* table,
goto exit;
}

uvwasi__free(uvwasi, entry->path);
uv_mutex_destroy(&entry->mutex);
entry->valid = 0;
table->used--;
Expand Down
16 changes: 13 additions & 3 deletions src/uvwasi.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@
#include "fd_table.h"
#include "clocks.h"

/* TODO(cjihrig): PATH_MAX_BYTES shouldn't be stack allocated. On Windows, paths
can be 32k long, and this PATH_MAX_BYTES is an artificial limitation. */
#ifdef _WIN32
/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
# define PATH_MAX_BYTES (MAX_PATH * 4)
#else
# include <limits.h>
# define PATH_MAX_BYTES (PATH_MAX)
#endif

static void* default_malloc(size_t size, void* mem_user_data) {
return malloc(size);
}
Expand Down Expand Up @@ -688,7 +698,7 @@ uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd) {
if (r != 0)
return uvwasi__translate_uv_error(r);

return uvwasi_fd_table_remove(&uvwasi->fds, fd);
return uvwasi_fd_table_remove(uvwasi, &uvwasi->fds, fd);
}


Expand Down Expand Up @@ -1319,7 +1329,7 @@ uvwasi_errno_t uvwasi_fd_renumber(uvwasi_t* uvwasi,
to_wrap->id = to;
uv_mutex_unlock(&from_wrap->mutex);
uv_mutex_unlock(&to_wrap->mutex);
return uvwasi_fd_table_remove(&uvwasi->fds, from);
return uvwasi_fd_table_remove(uvwasi, &uvwasi->fds, from);
}


Expand Down Expand Up @@ -1773,7 +1783,7 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi,
if ((o_flags & UVWASI_O_DIRECTORY) != 0 &&
wrap.type != UVWASI_FILETYPE_DIRECTORY) {
uv_mutex_unlock(&dirfd_wrap->mutex);
uvwasi_fd_table_remove(&uvwasi->fds, wrap.id);
uvwasi_fd_table_remove(uvwasi, &uvwasi->fds, wrap.id);
err = UVWASI_ENOTDIR;
goto close_file_and_error_exit;
}
Expand Down

0 comments on commit 20d20fe

Please sign in to comment.