debug: make __read_chk a cancellation point (bug 29274)
[platform/upstream/glibc.git] / debug / realpath_chk.c
1 /* Copyright (C) 2005-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
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.
8
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
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17
18 #include <limits.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22
23
24 char *
25 __realpath_chk (const char *buf, char *resolved, size_t resolvedlen)
26 {
27 #ifdef PATH_MAX
28   if (resolvedlen < PATH_MAX)
29     __chk_fail ();
30
31   return __realpath (buf, resolved);
32 #else
33   long int pathmax =__pathconf (buf, _PC_PATH_MAX);
34   if (pathmax != -1)
35     {
36       /* We do have a fixed limit.  */
37       if (resolvedlen < pathmax)
38         __chk_fail ();
39
40       return __realpath (buf, resolved);
41     }
42
43   /* Since there is no fixed limit we check whether the size is large
44      enough.  */
45   char *res = __realpath (buf, NULL);
46   if (res != NULL)
47     {
48       size_t actlen = strlen (res) + 1;
49       if (actlen > resolvedlen)
50         __chk_fail ();
51
52       memcpy (resolved, res, actlen);
53       free (res);
54       res = resolved;
55     }
56
57   return res;
58 #endif
59 }