@@ -1222,43 +1222,52 @@ __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 ;
1227+ size_t buf_len ;
12281228
1229+ error = os_fstatat (handle , path , & stat , __WASI_LOOKUP_SYMLINK_FOLLOW );
1230+ if (error != __WASI_ESUCCESS ) {
1231+ * p_len = 0 ;
1232+ * out_buf = NULL ;
1233+ return error ;
1234+ }
1235+
1236+ /*
1237+ * Some magic symlinks report `st_size` as zero. In that case, take
1238+ * 32 as the initial buffer size. Otherwise, use `st_size + 1`.
1239+ */
1240+ buf_len = stat .st_size ? stat .st_size + 1 : 32 ;
12291241 for (;;) {
1230- char * newbuf = wasm_runtime_malloc ((uint32 )len );
1242+ size_t bytes_read = 0 ;
1243+ char * buf ;
12311244
1232- if (newbuf == NULL ) {
1233- if (buf )
1234- wasm_runtime_free (buf );
1245+ buf = wasm_runtime_malloc ((uint32 )buf_len );
1246+ if (buf == NULL ) {
12351247 * out_buf = NULL ;
12361248 return __WASI_ENOMEM ;
12371249 }
12381250
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 );
1251+ error = os_readlinkat (handle , path , buf , buf_len , & bytes_read );
12481252 if (error != __WASI_ESUCCESS ) {
12491253 wasm_runtime_free (buf );
1254+ * p_len = 0 ;
12501255 * out_buf = NULL ;
12511256 return error ;
12521257 }
1253- if ((size_t )bytes_read + 1 < len ) {
1258+
1259+ /* not truncated */
1260+ if (bytes_read < buf_len ) {
12541261 buf [bytes_read ] = '\0' ;
1255- * p_len = len ;
1262+ * p_len = bytes_read + 1 ;
12561263 * out_buf = buf ;
1257-
12581264 return __WASI_ESUCCESS ;
12591265 }
1260- len_org = len ;
1261- len *= 2 ;
1266+
1267+ /* truncated, try again with a bigger buf */
1268+ wasm_runtime_free (buf );
1269+ buf = NULL ;
1270+ buf_len *= 2 ;
12621271 }
12631272}
12641273
0 commit comments