]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/iofclose.c
Bug 20116: Fix use after free in pthread_create()
[thirdparty/glibc.git] / libio / iofclose.c
CommitLineData
bfff8b1b 1/* Copyright (C) 1993-2017 Free Software Foundation, Inc.
41bdb6e2 2 This file is part of the GNU C Library.
40a55d20 3
41bdb6e2
AJ
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
40a55d20 8
41bdb6e2
AJ
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
40a55d20 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2
AJ
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>.
41bdb6e2
AJ
17
18 As a special exception, if you link the code in this file with
19 files compiled with a GNU compiler to produce an executable,
20 that does not cause the resulting executable to be covered by
21 the GNU Lesser General Public License. This exception does not
22 however invalidate any other reasons why the executable file
23 might be covered by the GNU Lesser General Public License.
24 This exception applies to code released by its copyright holders
25 in files containing the exception. */
96aa2d94
RM
26
27#include "libioP.h"
96aa2d94 28#include <stdlib.h>
4e2e9999
UD
29#if _LIBC
30# include "../iconv/gconv_int.h"
0bf98029 31# include <shlib-compat.h>
319d719d
UD
32#else
33# define SHLIB_COMPAT(a, b, c) 0
34# define _IO_new_fclose fclose
4e2e9999 35#endif
96aa2d94
RM
36
37int
9d46370c 38_IO_new_fclose (_IO_FILE *fp)
96aa2d94
RM
39{
40 int status;
41
6bc31da0
UD
42 CHECK_FILE(fp, EOF);
43
16710d58 44#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
c7f7281e
UD
45 /* We desperately try to help programs which are using streams in a
46 strange way and mix old and new functions. Detect old streams
47 here. */
bbdef797 48 if (_IO_vtable_offset (fp) != 0)
c7f7281e 49 return _IO_old_fclose (fp);
f1778711 50#endif
c7f7281e 51
beafb752
UD
52 /* First unlink the stream. */
53 if (fp->_IO_file_flags & _IO_IS_FILEBUF)
d18ea0c5 54 _IO_un_link ((struct _IO_FILE_plus *) fp);
beafb752 55
0261d33f 56 _IO_acquire_lock (fp);
6bc31da0 57 if (fp->_IO_file_flags & _IO_IS_FILEBUF)
d18ea0c5 58 status = _IO_file_close_it (fp);
96aa2d94 59 else
6bc31da0 60 status = fp->_flags & _IO_ERR_SEEN ? -1 : 0;
a334319f 61 _IO_release_lock (fp);
407a5515 62 _IO_FINISH (fp);
4e2e9999
UD
63 if (fp->_mode > 0)
64 {
65#if _LIBC
66 /* This stream has a wide orientation. This means we have to free
67 the conversion functions. */
cd8b7ff9 68 struct _IO_codecvt *cc = fp->_codecvt;
4e2e9999 69
9e26f129 70 __libc_lock_lock (__gconv_lock);
129d706d
UD
71 __gconv_release_step (cc->__cd_in.__cd.__steps);
72 __gconv_release_step (cc->__cd_out.__cd.__steps);
9e26f129 73 __libc_lock_unlock (__gconv_lock);
4e2e9999 74#endif
77fe0b9c
UD
75 }
76 else
77 {
78 if (_IO_have_backup (fp))
d18ea0c5 79 _IO_free_backup_area (fp);
4e2e9999 80 }
6bc31da0 81 if (fp != _IO_stdin && fp != _IO_stdout && fp != _IO_stderr)
96aa2d94 82 {
6bc31da0
UD
83 fp->_IO_file_flags = 0;
84 free(fp);
96aa2d94 85 }
68dbb3a6 86
96aa2d94
RM
87 return status;
88}
89
319d719d 90#ifdef _LIBC
0bf98029 91versioned_symbol (libc, _IO_new_fclose, _IO_fclose, GLIBC_2_1);
6973fc01 92strong_alias (_IO_new_fclose, __new_fclose)
0bf98029 93versioned_symbol (libc, __new_fclose, fclose, GLIBC_2_1);
319d719d 94#endif