Skip to content

Commit 1a72dcf

Browse files
authored
Improve readlinkat_dup() to handle symlink size correctly (#4229)
* In readlinkat_dup(), use fstatat() to estimate size first. * Reduce additional space in samples/file
1 parent 6aa223d commit 1a72dcf

File tree

2 files changed

+35
-22
lines changed
  • core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src
  • samples/file/wasm-app

2 files changed

+35
-22
lines changed

core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,43 +1222,56 @@ __wasi_errno_t
12221222
readlinkat_dup(os_file_handle handle, const char *path, size_t *p_len,
12231223
char **out_buf)
12241224
{
1225-
char *buf = NULL;
1226-
size_t len = 32;
1227-
size_t len_org = len;
1225+
__wasi_errno_t error;
1226+
struct __wasi_filestat_t stat = { 0 };
1227+
size_t buf_len;
1228+
1229+
/*
1230+
* use fstatat to get a better estimation
1231+
* If path is a symbolic link, do not dereference it:
1232+
* instead return information about the link itself,
1233+
* like lstat().
1234+
*/
1235+
error = os_fstatat(handle, path, &stat, 0);
1236+
if (error != __WASI_ESUCCESS) {
1237+
stat.st_size = 0;
1238+
}
12281239

1240+
/*
1241+
* Some magic symlinks report `st_size` as zero. In that case, take
1242+
* 32 as the initial buffer size. Otherwise, use `st_size + 1`.
1243+
*/
1244+
buf_len = stat.st_size ? stat.st_size + 1 : 32;
12291245
for (;;) {
1230-
char *newbuf = wasm_runtime_malloc((uint32)len);
1246+
size_t bytes_read = 0;
1247+
char *buf;
12311248

1232-
if (newbuf == NULL) {
1233-
if (buf)
1234-
wasm_runtime_free(buf);
1249+
buf = wasm_runtime_malloc((uint32)buf_len);
1250+
if (buf == NULL) {
12351251
*out_buf = NULL;
12361252
return __WASI_ENOMEM;
12371253
}
12381254

1239-
if (buf != NULL) {
1240-
bh_memcpy_s(newbuf, (uint32)len, buf, (uint32)len_org);
1241-
wasm_runtime_free(buf);
1242-
}
1243-
1244-
buf = newbuf;
1245-
size_t bytes_read = 0;
1246-
__wasi_errno_t error =
1247-
os_readlinkat(handle, path, buf, len, &bytes_read);
1255+
error = os_readlinkat(handle, path, buf, buf_len, &bytes_read);
12481256
if (error != __WASI_ESUCCESS) {
12491257
wasm_runtime_free(buf);
1258+
*p_len = 0;
12501259
*out_buf = NULL;
12511260
return error;
12521261
}
1253-
if ((size_t)bytes_read + 1 < len) {
1262+
1263+
/* not truncated */
1264+
if (bytes_read < buf_len) {
12541265
buf[bytes_read] = '\0';
1255-
*p_len = len;
1266+
*p_len = bytes_read + 1;
12561267
*out_buf = buf;
1257-
12581268
return __WASI_ESUCCESS;
12591269
}
1260-
len_org = len;
1261-
len *= 2;
1270+
1271+
/* truncated, try again with a bigger buf */
1272+
wasm_runtime_free(buf);
1273+
buf = NULL;
1274+
buf_len *= 2;
12621275
}
12631276
}
12641277

samples/file/wasm-app/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#define WORLD_OFFSET 7
1919
#define NAME_REPLACMENT "James"
2020
#define NAME_REPLACMENT_LEN (sizeof(NAME_REPLACMENT) - 1)
21-
#define ADDITIONAL_SPACE 1 * 1024 * 1024
21+
#define ADDITIONAL_SPACE 16 * 1024
2222

2323
int
2424
main(int argc, char **argv)

0 commit comments

Comments
 (0)