Skip to content

Commit 7257785

Browse files
committed
Fix: zchunkopen: resources leaks, don't close supplied fd
System variant: - resource leaks when `zck_init_read` or `zck_init_write` fails - supplied fd will be closed if `zck_create` fails Libsolv limited zchunk implementation: - resource leak when `strcmp(mode, "r") != 0` - supplied fd will be closed if `solv_zchunk_open` fails (Fix is thread unsafe. However the original version caused a double-close in the caller function and was thread unsafe too.)
1 parent ee8b8b9 commit 7257785

1 file changed

Lines changed: 34 additions & 10 deletions

File tree

ext/solv_xfopen.c

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -548,9 +548,9 @@ static void *zchunkopen(const char *path, const char *mode, int fd)
548548
{
549549
zckCtx *f;
550550

551-
if (!path && fd < 0)
551+
if ((!path && fd < 0) || (path && fd >= 0))
552552
return 0;
553-
if (fd == -1)
553+
if (path)
554554
{
555555
if (*mode != 'w')
556556
fd = open(path, O_RDONLY);
@@ -562,18 +562,29 @@ static void *zchunkopen(const char *path, const char *mode, int fd)
562562
f = zck_create();
563563
if (!f)
564564
{
565-
close(fd);
565+
if (path)
566+
close(fd);
566567
return 0;
567568
}
568569
if (*mode != 'w')
569570
{
570571
if(!zck_init_read(f, fd))
571-
return 0;
572+
{
573+
zck_free(&f);
574+
if (path)
575+
close(fd);
576+
return 0;
577+
}
572578
}
573579
else
574580
{
575581
if(!zck_init_write(f, fd))
576-
return 0;
582+
{
583+
zck_free(&f);
584+
if (path)
585+
close(fd);
586+
return 0;
587+
}
577588
}
578589
return cookieopen(f, mode, cookie_zckread, cookie_zckwrite, cookie_zckclose);
579590
}
@@ -587,19 +598,32 @@ static void *zchunkopen(const char *path, const char *mode, int fd)
587598
{
588599
FILE *fp;
589600
void *f;
590-
if (!path && fd < 0)
601+
int tmpfd;
602+
if ((!path && fd < 0) || (path && fd >= 0))
591603
return 0;
592-
if (fd != -1)
604+
if (strcmp(mode, "r") != 0)
605+
return 0;
606+
if (!path)
593607
fp = fdopen(fd, mode);
594608
else
595609
fp = fopen(path, mode);
596610
if (!fp)
597611
return 0;
598-
if (strcmp(mode, "r") != 0)
599-
return 0;
600612
f = solv_zchunk_open(fp, 1);
601613
if (!f)
602-
fclose(fp);
614+
{
615+
/* When 0 is returned, fd passed by user must not be closed! */
616+
/* Dup (save) the original fd to a temporary variable and then back. */
617+
/* It is ugly and thread unsafe hack (non atomical sequence fclose dup2). */
618+
if (!path)
619+
tmpfd = dup(fd);
620+
fclose(fp);
621+
if (!path)
622+
{
623+
dup2(tmpfd, fd);
624+
close(tmpfd);
625+
}
626+
}
603627
return cookieopen(f, mode, (ssize_t (*)(void *, char *, size_t))solv_zchunk_read, 0, (int (*)(void *))solv_zchunk_close);
604628
}
605629

0 commit comments

Comments
 (0)