Skip to content

Commit ee8b8b9

Browse files
committed
Fix: lzopen and zstdopen: don't close supplied fd
In the case of failure of some functions, the `fp` file stream has been closed. And the stream closed the associated supplied `fd` file descriptor. The caller then closed the closed descriptor again (eg `curlfopen` in `repoinfo_download.c`: `if (!Fp) close (fd);`) -> double_close. In multithreaded software risk of race conditions. Another thread open another file and reuse just closed file descriptor. The caller then closes the file of another thread.
1 parent 6864aef commit ee8b8b9

1 file changed

Lines changed: 26 additions & 19 deletions

File tree

ext/solv_xfopen.c

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ static LZFILE *lzopen(const char *path, const char *mode, int fd, int isxz)
165165
LZFILE *lzfile;
166166
lzma_ret ret;
167167

168-
if (!path && fd < 0)
168+
if ((!path && fd < 0) || (path && fd >= 0))
169169
return 0;
170170
for (; *mode; mode++)
171171
{
@@ -176,14 +176,7 @@ static LZFILE *lzopen(const char *path, const char *mode, int fd, int isxz)
176176
else if (*mode >= '1' && *mode <= '9')
177177
level = *mode - '0';
178178
}
179-
if (fd != -1)
180-
fp = fdopen(fd, encoding ? "w" : "r");
181-
else
182-
fp = fopen(path, encoding ? "w" : "r");
183-
if (!fp)
184-
return 0;
185179
lzfile = solv_calloc(1, sizeof(*lzfile));
186-
lzfile->file = fp;
187180
lzfile->encoding = encoding;
188181
lzfile->eof = 0;
189182
lzfile->strm = stream_init;
@@ -198,10 +191,20 @@ static LZFILE *lzopen(const char *path, const char *mode, int fd, int isxz)
198191
ret = lzma_auto_decoder(&lzfile->strm, 100 << 20, 0);
199192
if (ret != LZMA_OK)
200193
{
201-
fclose(fp);
202194
solv_free(lzfile);
203195
return 0;
204196
}
197+
if (!path)
198+
fp = fdopen(fd, encoding ? "w" : "r");
199+
else
200+
fp = fopen(path, encoding ? "w" : "r");
201+
if (!fp)
202+
{
203+
lzma_end(&lzfile->strm);
204+
solv_free(lzfile);
205+
return 0;
206+
}
207+
lzfile->file = fp;
205208
return lzfile;
206209
}
207210

@@ -346,7 +349,7 @@ static ZSTDFILE *zstdopen(const char *path, const char *mode, int fd)
346349
FILE *fp;
347350
ZSTDFILE *zstdfile;
348351

349-
if (!path && fd < 0)
352+
if ((!path && fd < 0) || (path && fd >= 0))
350353
return 0;
351354
for (; *mode; mode++)
352355
{
@@ -357,12 +360,6 @@ static ZSTDFILE *zstdopen(const char *path, const char *mode, int fd)
357360
else if (*mode >= '1' && *mode <= '9')
358361
level = *mode - '0';
359362
}
360-
if (fd != -1)
361-
fp = fdopen(fd, encoding ? "w" : "r");
362-
else
363-
fp = fopen(path, encoding ? "w" : "r");
364-
if (!fp)
365-
return 0;
366363
zstdfile = solv_calloc(1, sizeof(*zstdfile));
367364
zstdfile->encoding = encoding;
368365
if (encoding)
@@ -372,14 +369,12 @@ static ZSTDFILE *zstdopen(const char *path, const char *mode, int fd)
372369
if (!zstdfile->cstream)
373370
{
374371
solv_free(zstdfile);
375-
fclose(fp);
376372
return 0;
377373
}
378374
if (ZSTD_isError(ZSTD_initCStream(zstdfile->cstream, level)))
379375
{
380376
ZSTD_freeCStream(zstdfile->cstream);
381377
solv_free(zstdfile);
382-
fclose(fp);
383378
return 0;
384379
}
385380
zstdfile->out.dst = zstdfile->buf;
@@ -393,13 +388,25 @@ static ZSTDFILE *zstdopen(const char *path, const char *mode, int fd)
393388
{
394389
ZSTD_freeDStream(zstdfile->dstream);
395390
solv_free(zstdfile);
396-
fclose(fp);
397391
return 0;
398392
}
399393
zstdfile->in.src = zstdfile->buf;
400394
zstdfile->in.pos = 0;
401395
zstdfile->in.size = 0;
402396
}
397+
if (!path)
398+
fp = fdopen(fd, encoding ? "w" : "r");
399+
else
400+
fp = fopen(path, encoding ? "w" : "r");
401+
if (!fp)
402+
{
403+
if (encoding)
404+
ZSTD_freeCStream(zstdfile->cstream);
405+
else
406+
ZSTD_freeDStream(zstdfile->dstream);
407+
solv_free(zstdfile);
408+
return 0;
409+
}
403410
zstdfile->file = fp;
404411
return zstdfile;
405412
}

0 commit comments

Comments
 (0)