@@ -1222,43 +1222,56 @@ __wasi_errno_t
12221222readlinkat_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
0 commit comments