Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deps: update uvwasi to 0.0.20 and fixup tests #51355

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion deps/uvwasi/include/uvwasi.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extern "C" {

#define UVWASI_VERSION_MAJOR 0
#define UVWASI_VERSION_MINOR 0
#define UVWASI_VERSION_PATCH 19
#define UVWASI_VERSION_PATCH 20
#define UVWASI_VERSION_HEX ((UVWASI_VERSION_MAJOR << 16) | \
(UVWASI_VERSION_MINOR << 8) | \
(UVWASI_VERSION_PATCH))
Expand Down
118 changes: 94 additions & 24 deletions deps/uvwasi/src/path_resolver.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,42 @@ static char* uvwasi__strchr_slash(const char* s) {
return NULL;
}

static uvwasi_errno_t uvwasi__combine_paths(const uvwasi_t* uvwasi,
const char* path1,
uvwasi_size_t path1_len,
const char* path2,
uvwasi_size_t path2_len,
char** combined_path,
uvwasi_size_t* combined_len) {
/* This function joins two paths with '/'. */
uvwasi_errno_t err;
char* combined;
int combined_size;
int r;

*combined_path = NULL;
*combined_len = 0;

/* The max combined size is the path1 length + the path2 length
+ 2 for a terminating NULL and a possible path separator. */
combined_size = path1_len + path2_len + 2;
combined = uvwasi__malloc(uvwasi, combined_size);
if (combined == NULL) return UVWASI_ENOMEM;

r = snprintf(combined, combined_size, "%s/%s", path1, path2);
if (r <= 0) {
err = uvwasi__translate_uv_error(uv_translate_sys_error(errno));
goto exit;
}

err = UVWASI_ESUCCESS;
*combined_path = combined;
*combined_len = strlen(combined);

exit:
if (err != UVWASI_ESUCCESS) uvwasi__free(uvwasi, combined);
return err;
}

uvwasi_errno_t uvwasi__normalize_path(const char* path,
uvwasi_size_t path_len,
Expand Down Expand Up @@ -234,39 +270,35 @@ static uvwasi_errno_t uvwasi__normalize_relative_path(
uvwasi_errno_t err;
char* combined;
char* normalized;
int combined_size;
int fd_path_len;
int norm_len;
int r;
uvwasi_size_t combined_len;
uvwasi_size_t fd_path_len;
uvwasi_size_t norm_len;

*normalized_path = NULL;
*normalized_len = 0;

/* The max combined size is the path length + the file descriptor's path
length + 2 for a terminating NULL and a possible path separator. */
fd_path_len = strlen(fd->normalized_path);
combined_size = path_len + fd_path_len + 2;
combined = uvwasi__malloc(uvwasi, combined_size);
if (combined == NULL)
return UVWASI_ENOMEM;

normalized = uvwasi__malloc(uvwasi, combined_size);
err = uvwasi__combine_paths(uvwasi,
fd->normalized_path,
fd_path_len,
path,
path_len,
&combined,
&combined_len);
if (err != UVWASI_ESUCCESS) goto exit;

normalized = uvwasi__malloc(uvwasi, combined_len + 1);
if (normalized == NULL) {
err = UVWASI_ENOMEM;
goto exit;
}

r = snprintf(combined, combined_size, "%s/%s", fd->normalized_path, path);
if (r <= 0) {
err = uvwasi__translate_uv_error(uv_translate_sys_error(errno));
goto exit;
}

/* Normalize the input path. */
err = uvwasi__normalize_path(combined,
combined_size - 1,
combined_len,
normalized,
combined_size - 1);
combined_len);
if (err != UVWASI_ESUCCESS)
goto exit;

Expand Down Expand Up @@ -374,9 +406,14 @@ uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi,
char* host_path;
char* normalized_path;
char* link_target;
char* normalized_parent;
char* resolved_link_target;
uvwasi_size_t input_len;
uvwasi_size_t host_path_len;
uvwasi_size_t normalized_len;
uvwasi_size_t link_target_len;
uvwasi_size_t normalized_parent_len;
uvwasi_size_t resolved_link_target_len;
int follow_count;
int r;

Expand All @@ -385,6 +422,8 @@ uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi,
link_target = NULL;
follow_count = 0;
host_path = NULL;
normalized_parent = NULL;
resolved_link_target = NULL;

start:
normalized_path = NULL;
Expand Down Expand Up @@ -458,19 +497,47 @@ uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi,
goto exit;
}

input_len = strlen(req.ptr);
link_target_len = strlen(req.ptr);
uvwasi__free(uvwasi, link_target);
link_target = uvwasi__malloc(uvwasi, input_len + 1);
link_target = uvwasi__malloc(uvwasi, link_target_len + 1);
if (link_target == NULL) {
uv_fs_req_cleanup(&req);
err = UVWASI_ENOMEM;
goto exit;
}

memcpy(link_target, req.ptr, input_len + 1);
input = link_target;
uvwasi__free(uvwasi, normalized_path);
memcpy(link_target, req.ptr, link_target_len + 1);
uv_fs_req_cleanup(&req);

if (1 == uvwasi__is_absolute_path(link_target, link_target_len)) {
input = link_target;
input_len = link_target_len;
} else {
uvwasi__free(uvwasi, normalized_parent);
uvwasi__free(uvwasi, resolved_link_target);

err = uvwasi__combine_paths(uvwasi,
normalized_path,
normalized_len,
"..",
2,
&normalized_parent,
&normalized_parent_len);
if (err != UVWASI_ESUCCESS) goto exit;
err = uvwasi__combine_paths(uvwasi,
normalized_parent,
normalized_parent_len,
link_target,
link_target_len,
&resolved_link_target,
&resolved_link_target_len);
if (err != UVWASI_ESUCCESS) goto exit;

input = resolved_link_target;
input_len = resolved_link_target_len;
}

uvwasi__free(uvwasi, normalized_path);
goto start;
}

Expand All @@ -484,5 +551,8 @@ uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi,

uvwasi__free(uvwasi, link_target);
uvwasi__free(uvwasi, normalized_path);
uvwasi__free(uvwasi, normalized_parent);
uvwasi__free(uvwasi, resolved_link_target);

return err;
}
55 changes: 45 additions & 10 deletions deps/uvwasi/src/uvwasi.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
# include <dirent.h>
# include <time.h>
#else
# define _CRT_INTERNAL_NONSTDC_NAMES 1
# include <sys/stat.h>
# include <io.h>
#endif /* _WIN32 */

Expand All @@ -17,6 +19,10 @@
# define UVWASI_FD_READDIR_SUPPORTED 1
#endif

#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif

#include "uvwasi.h"
#include "uvwasi_alloc.h"
#include "uv.h"
Expand All @@ -37,10 +43,13 @@

#define VALIDATE_FSTFLAGS_OR_RETURN(flags) \
do { \
if ((flags) & ~(UVWASI_FILESTAT_SET_ATIM | \
UVWASI_FILESTAT_SET_ATIM_NOW | \
UVWASI_FILESTAT_SET_MTIM | \
UVWASI_FILESTAT_SET_MTIM_NOW)) { \
uvwasi_fstflags_t f = flags; \
if (((f) & ~(UVWASI_FILESTAT_SET_ATIM | UVWASI_FILESTAT_SET_ATIM_NOW | \
UVWASI_FILESTAT_SET_MTIM | UVWASI_FILESTAT_SET_MTIM_NOW)) || \
((f) & (UVWASI_FILESTAT_SET_ATIM | UVWASI_FILESTAT_SET_ATIM_NOW)) \
== (UVWASI_FILESTAT_SET_ATIM | UVWASI_FILESTAT_SET_ATIM_NOW) || \
((f) & (UVWASI_FILESTAT_SET_MTIM | UVWASI_FILESTAT_SET_MTIM_NOW)) \
== (UVWASI_FILESTAT_SET_MTIM | UVWASI_FILESTAT_SET_MTIM_NOW)) { \
return UVWASI_EINVAL; \
} \
} while (0)
Expand Down Expand Up @@ -624,9 +633,10 @@ uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi,
uvwasi_advice_t advice) {
struct uvwasi_fd_wrap_t* wrap;
uvwasi_errno_t err;
uv_fs_t req;
int r;
#ifdef POSIX_FADV_NORMAL
int mapped_advice;
int r;
#endif /* POSIX_FADV_NORMAL */

UVWASI_DEBUG("uvwasi_fd_advise(uvwasi=%p, fd=%d, offset=%"PRIu64", "
Expand Down Expand Up @@ -679,14 +689,27 @@ uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;

r = uv_fs_fstat(NULL, &req, wrap->fd, NULL);
if (r == -1) {
err = uvwasi__translate_uv_error(r);
goto exit;
}

if (S_ISDIR(req.statbuf.st_mode)) {
err = UVWASI_EBADF;
goto exit;
}

err = UVWASI_ESUCCESS;

#ifdef POSIX_FADV_NORMAL
r = posix_fadvise(wrap->fd, offset, len, mapped_advice);
if (r != 0)
err = uvwasi__translate_uv_error(uv_translate_sys_error(r));
#endif /* POSIX_FADV_NORMAL */
exit:
uv_mutex_unlock(&wrap->mutex);
uv_fs_req_cleanup(&req);
return err;
}

Expand Down Expand Up @@ -1775,8 +1798,6 @@ uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi,
if (uvwasi == NULL || path == NULL)
return UVWASI_EINVAL;

VALIDATE_FSTFLAGS_OR_RETURN(fst_flags);

err = uvwasi_fd_table_get(uvwasi->fds,
fd,
&wrap,
Expand All @@ -1785,6 +1806,8 @@ uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;

VALIDATE_FSTFLAGS_OR_RETURN(fst_flags);

err = uvwasi__resolve_path(uvwasi,
wrap,
path,
Expand Down Expand Up @@ -2306,6 +2329,7 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi,
uvwasi_fd_t fd,
const char* new_path,
uvwasi_size_t new_path_len) {
char* truncated_old_path;
char* resolved_new_path;
struct uvwasi_fd_wrap_t* wrap;
uvwasi_errno_t err;
Expand All @@ -2332,6 +2356,15 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;

truncated_old_path = uvwasi__malloc(uvwasi, old_path_len + 1);
if (truncated_old_path == NULL) {
uv_mutex_unlock(&wrap->mutex);
return UVWASI_ENOMEM;
}

memcpy(truncated_old_path, old_path, old_path_len);
truncated_old_path[old_path_len] = '\0';

err = uvwasi__resolve_path(uvwasi,
wrap,
new_path,
Expand All @@ -2340,12 +2373,14 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi,
0);
if (err != UVWASI_ESUCCESS) {
uv_mutex_unlock(&wrap->mutex);
uvwasi__free(uvwasi, truncated_old_path);
return err;
}

/* Windows support may require setting the flags option. */
r = uv_fs_symlink(NULL, &req, old_path, resolved_new_path, 0, NULL);
r = uv_fs_symlink(NULL, &req, truncated_old_path, resolved_new_path, 0, NULL);
uv_mutex_unlock(&wrap->mutex);
uvwasi__free(uvwasi, truncated_old_path);
uvwasi__free(uvwasi, resolved_new_path);
uv_fs_req_cleanup(&req);
if (r != 0)
Expand Down Expand Up @@ -2696,7 +2731,7 @@ uvwasi_errno_t uvwasi_sock_shutdown(uvwasi_t* uvwasi,
uvwasi_sdflags_t how) {
struct uvwasi_fd_wrap_t* wrap;
uvwasi_errno_t err = 0;
shutdown_data_t shutdown_data;
shutdown_data_t shutdown_data = {0};

if (how & ~UVWASI_SHUT_WR)
return UVWASI_ENOTSUP;
Expand Down Expand Up @@ -2794,7 +2829,7 @@ uvwasi_errno_t uvwasi_sock_accept(uvwasi_t* uvwasi,
goto close_sock_and_error_exit;
}

int r = uv_accept((uv_stream_t*) wrap->sock, (uv_stream_t*) uv_connect_sock);
r = uv_accept((uv_stream_t*) wrap->sock, (uv_stream_t*) uv_connect_sock);
if (r == UV_EAGAIN) {
// still no connection or error so run the loop again
continue;
Expand Down
2 changes: 1 addition & 1 deletion test/wasi/c/create_symlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <unistd.h>

int main() {
const char* target = "./input.txt";
const char* target = "./input-in-subdir.txt";
const char* linkpath = "/sandbox/subdir/test_link";
char readlink_result[128];
size_t result_size = sizeof(readlink_result);
Expand Down
20 changes: 12 additions & 8 deletions test/wasi/test-wasi-symlinks.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ if (process.argv[2] === 'wasi-child') {
const sandboxedFile = path.join(sandbox, 'input.txt');
const externalFile = tmpdir.resolve('outside.txt');
const sandboxedDir = path.join(sandbox, 'subdir');
const sandboxedFileInSubdir = path.join(sandboxedDir, 'input-in-subdir.txt');
const sandboxedSymlink = path.join(sandboxedDir, 'input_link.txt');
const escapingSymlink = path.join(sandboxedDir, 'outside.txt');
const loopSymlink1 = path.join(sandboxedDir, 'loop1');
Expand All @@ -52,13 +53,14 @@ if (process.argv[2] === 'wasi-child') {
fs.mkdirSync(sandboxedDir);
fs.mkdirSync(sandboxedTmp);
fs.writeFileSync(sandboxedFile, 'hello from input.txt', 'utf8');
fs.writeFileSync(sandboxedFileInSubdir, 'hello from input in subdir.txt',
'utf8');
fs.writeFileSync(externalFile, 'this should be inaccessible', 'utf8');
fs.symlinkSync(path.join('.', 'input.txt'), sandboxedSymlink, 'file');
fs.symlinkSync(path.join('..', 'outside.txt'), escapingSymlink, 'file');
fs.symlinkSync(path.join('subdir', 'loop2'),
loopSymlink1, 'file');
fs.symlinkSync(path.join('subdir', 'loop1'),
loopSymlink2, 'file');
fs.symlinkSync(path.join('.', 'input-in-subdir.txt'),
sandboxedSymlink, 'file');
fs.symlinkSync(path.join('..', '..', 'outside.txt'), escapingSymlink, 'file');
fs.symlinkSync('loop2', loopSymlink1, 'file');
fs.symlinkSync('loop1', loopSymlink2, 'file');

function runWASI(options) {
console.log('executing', options.test);
Expand All @@ -76,8 +78,10 @@ if (process.argv[2] === 'wasi-child') {
assert.strictEqual(child.stdout.toString(), options.stdout || '');
}

runWASI({ test: 'create_symlink', stdout: 'hello from input.txt' });
runWASI({ test: 'follow_symlink', stdout: 'hello from input.txt' });
runWASI({ test: 'create_symlink',
stdout: 'hello from input in subdir.txt' });
runWASI({ test: 'follow_symlink',
stdout: 'hello from input in subdir.txt' });
runWASI({ test: 'link' });
runWASI({ test: 'symlink_escape' });
runWASI({ test: 'symlink_loop' });
Expand Down
Binary file modified test/wasi/wasm/create_symlink.wasm
Binary file not shown.
Loading