@@ -291,19 +291,25 @@ uvwasi_errno_t uvwasi_fd_table_init(uvwasi_t* uvwasi,
291
291
return UVWASI_EINVAL ;
292
292
293
293
table -> fds = NULL ;
294
- r = uv_rwlock_init (& table -> rwlock );
295
- if (r != 0 )
296
- return uvwasi__translate_uv_error (r );
297
-
298
294
table -> used = 0 ;
299
295
table -> size = init_size ;
300
296
table -> fds = uvwasi__calloc (uvwasi ,
301
297
init_size ,
302
298
sizeof (struct uvwasi_fd_wrap_t * ));
303
299
304
- if (table -> fds == NULL ) {
305
- err = UVWASI_ENOMEM ;
306
- goto error_exit ;
300
+ if (table -> fds == NULL )
301
+ return UVWASI_ENOMEM ;
302
+
303
+ r = uv_rwlock_init (& table -> rwlock );
304
+ if (r != 0 ) {
305
+ err = uvwasi__translate_uv_error (r );
306
+ /* Free table->fds and set it to NULL here. This is done explicitly instead
307
+ of jumping to error_exit because uvwasi_fd_table_free() relies on fds
308
+ being NULL to know whether or not to destroy the rwlock.
309
+ */
310
+ uvwasi__free (uvwasi , table -> fds );
311
+ table -> fds = NULL ;
312
+ return err ;
307
313
}
308
314
309
315
/* Create the stdio FDs. */
@@ -358,13 +364,6 @@ void uvwasi_fd_table_free(uvwasi_t* uvwasi, struct uvwasi_fd_table_t* table) {
358
364
}
359
365
360
366
if (table -> fds != NULL ) {
361
- /* It's fine to call uvwasi__free() multiple times on table->fds. However,
362
- it is not fine to call uv_rwlock_destroy() multiple times. Guard against
363
- that by ensuring that table->fds is not NULL. Technically, it's possible
364
- that uvwasi_fd_table_init() initialized the rwlock successfully, but
365
- failed to initialize fds. However, the only way that's possible is if
366
- the application already ran out of memory.
367
- */
368
367
uvwasi__free (uvwasi , table -> fds );
369
368
table -> fds = NULL ;
370
369
table -> size = 0 ;
0 commit comments