LCOV - code coverage report
Current view: | top level - Modules - getpath.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 218 | 374 | 58.3 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 15 | 22 | 68.2 %
|  |  | Branches: | 119 | 262 | 45.4 %

               Branch data     Line data    Source code
           1                 :            : /* Return the initial module search path. */
           2                 :            :
           3                 :            : #include "Python.h"
           4                 :            : #include "marshal.h"              // PyMarshal_ReadObjectFromString
           5                 :            : #include "osdefs.h"               // DELIM
           6                 :            : #include "pycore_initconfig.h"
           7                 :            : #include "pycore_fileutils.h"
           8                 :            : #include "pycore_pathconfig.h"
           9                 :            : #include "pycore_pymem.h"         // _PyMem_SetDefaultAllocator()
          10                 :            : #include <wchar.h>
          11                 :            :
          12                 :            : #ifdef MS_WINDOWS
          13                 :            : #  include <windows.h>            // GetFullPathNameW(), MAX_PATH
          14                 :            : #  include <pathcch.h>
          15                 :            : #endif
          16                 :            :
          17                 :            : #ifdef __APPLE__
          18                 :            : #  include <mach-o/dyld.h>
          19                 :            : #endif
          20                 :            :
          21                 :            : /* Reference the precompiled getpath.py */
          22                 :            : #include "../Python/frozen_modules/getpath.h"
          23                 :            :
          24                 :            : #if (!defined(PREFIX) || !defined(EXEC_PREFIX) \
          25                 :            :         || !defined(VERSION) || !defined(VPATH) \
          26                 :            :         || !defined(PLATLIBDIR))
          27                 :            : #error "PREFIX, EXEC_PREFIX, VERSION, VPATH and PLATLIBDIR macros must be defined"
          28                 :            : #endif
          29                 :            :
          30                 :            : #if !defined(PYTHONPATH)
          31                 :            : #define PYTHONPATH NULL
          32                 :            : #endif
          33                 :            :
          34                 :            : #if !defined(PYDEBUGEXT)
          35                 :            : #define PYDEBUGEXT NULL
          36                 :            : #endif
          37                 :            :
          38                 :            : #if !defined(PYWINVER)
          39                 :            : #ifdef MS_DLL_ID
          40                 :            : #define PYWINVER MS_DLL_ID
          41                 :            : #else
          42                 :            : #define PYWINVER NULL
          43                 :            : #endif
          44                 :            : #endif
          45                 :            :
          46                 :            : #if !defined(EXE_SUFFIX)
          47                 :            : #if defined(MS_WINDOWS) || defined(__CYGWIN__) || defined(__MINGW32__)
          48                 :            : #define EXE_SUFFIX L".exe"
          49                 :            : #else
          50                 :            : #define EXE_SUFFIX NULL
          51                 :            : #endif
          52                 :            : #endif
          53                 :            :
          54                 :            :
          55                 :            : /* HELPER FUNCTIONS for getpath.py */
          56                 :            :
          57                 :            : static PyObject *
          58                 :         25 : getpath_abspath(PyObject *Py_UNUSED(self), PyObject *args)
          59                 :            : {
          60                 :         25 :     PyObject *r = NULL;
          61                 :            :     PyObject *pathobj;
          62                 :            :     wchar_t *path;
          63         [ -  + ]:         25 :     if (!PyArg_ParseTuple(args, "U", &pathobj)) {
          64                 :          0 :         return NULL;
          65                 :            :     }
          66                 :            :     Py_ssize_t len;
          67                 :         25 :     path = PyUnicode_AsWideCharString(pathobj, &len);
          68         [ +  - ]:         25 :     if (path) {
          69                 :            :         wchar_t *abs;
          70   [ +  -  +  - ]:         25 :         if (_Py_abspath((const wchar_t *)_Py_normpath(path, -1), &abs) == 0 && abs) {
          71                 :         25 :             r = PyUnicode_FromWideChar(abs, -1);
          72                 :         25 :             PyMem_RawFree((void *)abs);
          73                 :            :         } else {
          74                 :          0 :             PyErr_SetString(PyExc_OSError, "failed to make path absolute");
          75                 :            :         }
          76                 :         25 :         PyMem_Free((void *)path);
          77                 :            :     }
          78                 :         25 :     return r;
          79                 :            : }
          80                 :            :
          81                 :            :
          82                 :            : static PyObject *
          83                 :          0 : getpath_basename(PyObject *Py_UNUSED(self), PyObject *args)
          84                 :            : {
          85                 :            :     PyObject *path;
          86         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "U", &path)) {
          87                 :          0 :         return NULL;
          88                 :            :     }
          89                 :          0 :     Py_ssize_t end = PyUnicode_GET_LENGTH(path);
          90                 :          0 :     Py_ssize_t pos = PyUnicode_FindChar(path, SEP, 0, end, -1);
          91         [ #  # ]:          0 :     if (pos < 0) {
          92                 :          0 :         return Py_NewRef(path);
          93                 :            :     }
          94                 :          0 :     return PyUnicode_Substring(path, pos + 1, end);
          95                 :            : }
          96                 :            :
          97                 :            :
          98                 :            : static PyObject *
          99                 :         75 : getpath_dirname(PyObject *Py_UNUSED(self), PyObject *args)
         100                 :            : {
         101                 :            :     PyObject *path;
         102         [ -  + ]:         75 :     if (!PyArg_ParseTuple(args, "U", &path)) {
         103                 :          0 :         return NULL;
         104                 :            :     }
         105                 :         75 :     Py_ssize_t end = PyUnicode_GET_LENGTH(path);
         106                 :         75 :     Py_ssize_t pos = PyUnicode_FindChar(path, SEP, 0, end, -1);
         107         [ -  + ]:         75 :     if (pos < 0) {
         108                 :          0 :         return PyUnicode_FromStringAndSize(NULL, 0);
         109                 :            :     }
         110                 :         75 :     return PyUnicode_Substring(path, 0, pos);
         111                 :            : }
         112                 :            :
         113                 :            :
         114                 :            : static PyObject *
         115                 :          0 : getpath_isabs(PyObject *Py_UNUSED(self), PyObject *args)
         116                 :            : {
         117                 :          0 :     PyObject *r = NULL;
         118                 :            :     PyObject *pathobj;
         119                 :            :     const wchar_t *path;
         120         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "U", &pathobj)) {
         121                 :          0 :         return NULL;
         122                 :            :     }
         123                 :          0 :     path = PyUnicode_AsWideCharString(pathobj, NULL);
         124         [ #  # ]:          0 :     if (path) {
         125         [ #  # ]:          0 :         r = _Py_isabs(path) ? Py_True : Py_False;
         126                 :          0 :         PyMem_Free((void *)path);
         127                 :            :     }
         128                 :          0 :     return Py_XNewRef(r);
         129                 :            : }
         130                 :            :
         131                 :            :
         132                 :            : static PyObject *
         133                 :          0 : getpath_hassuffix(PyObject *Py_UNUSED(self), PyObject *args)
         134                 :            : {
         135                 :          0 :     PyObject *r = NULL;
         136                 :            :     PyObject *pathobj;
         137                 :            :     PyObject *suffixobj;
         138                 :            :     const wchar_t *path;
         139                 :            :     const wchar_t *suffix;
         140         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "UU", &pathobj, &suffixobj)) {
         141                 :          0 :         return NULL;
         142                 :            :     }
         143                 :            :     Py_ssize_t len, suffixLen;
         144                 :          0 :     path = PyUnicode_AsWideCharString(pathobj, &len);
         145         [ #  # ]:          0 :     if (path) {
         146                 :          0 :         suffix = PyUnicode_AsWideCharString(suffixobj, &suffixLen);
         147         [ #  # ]:          0 :         if (suffix) {
         148         [ #  # ]:          0 :             if (suffixLen > len ||
         149                 :            : #ifdef MS_WINDOWS
         150                 :            :                 wcsicmp(&path[len - suffixLen], suffix) != 0
         151                 :            : #else
         152         [ #  # ]:          0 :                 wcscmp(&path[len - suffixLen], suffix) != 0
         153                 :            : #endif
         154                 :            :             ) {
         155                 :          0 :                 r = Py_NewRef(Py_False);
         156                 :            :             } else {
         157                 :          0 :                 r = Py_NewRef(Py_True);
         158                 :            :             }
         159                 :          0 :             PyMem_Free((void *)suffix);
         160                 :            :         }
         161                 :          0 :         PyMem_Free((void *)path);
         162                 :            :     }
         163                 :          0 :     return r;
         164                 :            : }
         165                 :            :
         166                 :            :
         167                 :            : static PyObject *
         168                 :          0 : getpath_isdir(PyObject *Py_UNUSED(self), PyObject *args)
         169                 :            : {
         170                 :          0 :     PyObject *r = NULL;
         171                 :            :     PyObject *pathobj;
         172                 :            :     const wchar_t *path;
         173         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "U", &pathobj)) {
         174                 :          0 :         return NULL;
         175                 :            :     }
         176                 :          0 :     path = PyUnicode_AsWideCharString(pathobj, NULL);
         177         [ #  # ]:          0 :     if (path) {
         178                 :            : #ifdef MS_WINDOWS
         179                 :            :         DWORD attr = GetFileAttributesW(path);
         180                 :            :         r = (attr != INVALID_FILE_ATTRIBUTES) &&
         181                 :            :             (attr & FILE_ATTRIBUTE_DIRECTORY) ? Py_True : Py_False;
         182                 :            : #else
         183                 :            :         struct stat st;
         184   [ #  #  #  # ]:          0 :         r = (_Py_wstat(path, &st) == 0) && S_ISDIR(st.st_mode) ? Py_True : Py_False;
         185                 :            : #endif
         186                 :          0 :         PyMem_Free((void *)path);
         187                 :            :     }
         188                 :          0 :     return Py_XNewRef(r);
         189                 :            : }
         190                 :            :
         191                 :            :
         192                 :            : static PyObject *
         193                 :         46 : getpath_isfile(PyObject *Py_UNUSED(self), PyObject *args)
         194                 :            : {
         195                 :         46 :     PyObject *r = NULL;
         196                 :            :     PyObject *pathobj;
         197                 :            :     const wchar_t *path;
         198         [ -  + ]:         46 :     if (!PyArg_ParseTuple(args, "U", &pathobj)) {
         199                 :          0 :         return NULL;
         200                 :            :     }
         201                 :         46 :     path = PyUnicode_AsWideCharString(pathobj, NULL);
         202         [ +  - ]:         46 :     if (path) {
         203                 :            : #ifdef MS_WINDOWS
         204                 :            :         DWORD attr = GetFileAttributesW(path);
         205                 :            :         r = (attr != INVALID_FILE_ATTRIBUTES) &&
         206                 :            :             !(attr & FILE_ATTRIBUTE_DIRECTORY) ? Py_True : Py_False;
         207                 :            : #else
         208                 :            :         struct stat st;
         209   [ +  -  +  - ]:         46 :         r = (_Py_wstat(path, &st) == 0) && S_ISREG(st.st_mode) ? Py_True : Py_False;
         210                 :            : #endif
         211                 :         46 :         PyMem_Free((void *)path);
         212                 :            :     }
         213                 :         46 :     return Py_XNewRef(r);
         214                 :            : }
         215                 :            :
         216                 :            :
         217                 :            : static PyObject *
         218                 :          0 : getpath_isxfile(PyObject *Py_UNUSED(self), PyObject *args)
         219                 :            : {
         220                 :          0 :     PyObject *r = NULL;
         221                 :            :     PyObject *pathobj;
         222                 :            :     const wchar_t *path;
         223                 :            :     Py_ssize_t cchPath;
         224         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "U", &pathobj)) {
         225                 :          0 :         return NULL;
         226                 :            :     }
         227                 :          0 :     path = PyUnicode_AsWideCharString(pathobj, &cchPath);
         228         [ #  # ]:          0 :     if (path) {
         229                 :            : #ifdef MS_WINDOWS
         230                 :            :         DWORD attr = GetFileAttributesW(path);
         231                 :            :         r = (attr != INVALID_FILE_ATTRIBUTES) &&
         232                 :            :             !(attr & FILE_ATTRIBUTE_DIRECTORY) &&
         233                 :            :             (cchPath >= 4) &&
         234                 :            :             (CompareStringOrdinal(path + cchPath - 4, -1, L".exe", -1, 1 /* ignore case */) == CSTR_EQUAL)
         235                 :            :             ? Py_True : Py_False;
         236                 :            : #else
         237                 :            :         struct stat st;
         238                 :          0 :         r = (_Py_wstat(path, &st) == 0) &&
         239         [ #  # ]:          0 :             S_ISREG(st.st_mode) &&
         240         [ #  # ]:          0 :             (st.st_mode & 0111)
         241         [ #  # ]:          0 :             ? Py_True : Py_False;
         242                 :            : #endif
         243                 :          0 :         PyMem_Free((void *)path);
         244                 :            :     }
         245                 :          0 :     return Py_XNewRef(r);
         246                 :            : }
         247                 :            :
         248                 :            :
         249                 :            : static PyObject *
         250                 :        221 : getpath_joinpath(PyObject *Py_UNUSED(self), PyObject *args)
         251                 :            : {
         252         [ -  + ]:        221 :     if (!PyTuple_Check(args)) {
         253                 :          0 :         PyErr_SetString(PyExc_TypeError, "requires tuple of arguments");
         254                 :          0 :         return NULL;
         255                 :            :     }
         256                 :        221 :     Py_ssize_t n = PyTuple_GET_SIZE(args);
         257         [ -  + ]:        221 :     if (n == 0) {
         258                 :          0 :         return PyUnicode_FromStringAndSize(NULL, 0);
         259                 :            :     }
         260                 :            :     /* Convert all parts to wchar and accumulate max final length */
         261                 :        221 :     wchar_t **parts = (wchar_t **)PyMem_Malloc(n * sizeof(wchar_t *));
         262                 :        221 :     memset(parts, 0, n * sizeof(wchar_t *));
         263                 :        221 :     Py_ssize_t cchFinal = 0;
         264                 :        221 :     Py_ssize_t first = 0;
         265                 :            :
         266         [ +  + ]:        663 :     for (Py_ssize_t i = 0; i < n; ++i) {
         267                 :        442 :         PyObject *s = PyTuple_GET_ITEM(args, i);
         268                 :            :         Py_ssize_t cch;
         269         [ +  + ]:        442 :         if (s == Py_None) {
         270                 :         25 :             cch = 0;
         271         [ +  - ]:        417 :         } else if (PyUnicode_Check(s)) {
         272                 :        417 :             parts[i] = PyUnicode_AsWideCharString(s, &cch);
         273         [ -  + ]:        417 :             if (!parts[i]) {
         274                 :          0 :                 cchFinal = -1;
         275                 :          0 :                 break;
         276                 :            :             }
         277         [ +  + ]:        417 :             if (_Py_isabs(parts[i])) {
         278                 :        221 :                 first = i;
         279                 :            :             }
         280                 :            :         } else {
         281                 :          0 :             PyErr_SetString(PyExc_TypeError, "all arguments to joinpath() must be str or None");
         282                 :          0 :             cchFinal = -1;
         283                 :          0 :             break;
         284                 :            :         }
         285                 :        442 :         cchFinal += cch + 1;
         286                 :            :     }
         287                 :            :
         288         [ +  - ]:        221 :     wchar_t *final = cchFinal > 0 ? (wchar_t *)PyMem_Malloc(cchFinal * sizeof(wchar_t)) : NULL;
         289         [ -  + ]:        221 :     if (!final) {
         290         [ #  # ]:          0 :         for (Py_ssize_t i = 0; i < n; ++i) {
         291                 :          0 :             PyMem_Free(parts[i]);
         292                 :            :         }
         293                 :          0 :         PyMem_Free(parts);
         294         [ #  # ]:          0 :         if (cchFinal) {
         295                 :          0 :             PyErr_NoMemory();
         296                 :          0 :             return NULL;
         297                 :            :         }
         298                 :          0 :         return PyUnicode_FromStringAndSize(NULL, 0);
         299                 :            :     }
         300                 :            :
         301                 :        221 :     final[0] = '\0';
         302                 :            :     /* Now join all the paths. The final result should be shorter than the buffer */
         303         [ +  + ]:        663 :     for (Py_ssize_t i = 0; i < n; ++i) {
         304         [ +  + ]:        442 :         if (!parts[i]) {
         305                 :         25 :             continue;
         306                 :            :         }
         307   [ +  -  +  - ]:        417 :         if (i >= first && final) {
         308         [ +  + ]:        417 :             if (!final[0]) {
         309                 :            :                 /* final is definitely long enough to fit any individual part */
         310                 :        221 :                 wcscpy(final, parts[i]);
         311         [ -  + ]:        196 :             } else if (_Py_add_relfile(final, parts[i], cchFinal) < 0) {
         312                 :            :                 /* if we fail, keep iterating to free memory, but stop adding parts */
         313                 :          0 :                 PyMem_Free(final);
         314                 :          0 :                 final = NULL;
         315                 :            :             }
         316                 :            :         }
         317                 :        417 :         PyMem_Free(parts[i]);
         318                 :            :     }
         319                 :        221 :     PyMem_Free(parts);
         320         [ -  + ]:        221 :     if (!final) {
         321                 :          0 :         PyErr_SetString(PyExc_SystemError, "failed to join paths");
         322                 :          0 :         return NULL;
         323                 :            :     }
         324                 :        221 :     PyObject *r = PyUnicode_FromWideChar(_Py_normpath(final, -1), -1);
         325                 :        221 :     PyMem_Free(final);
         326                 :        221 :     return r;
         327                 :            : }
         328                 :            :
         329                 :            :
         330                 :            : static PyObject *
         331                 :        125 : getpath_readlines(PyObject *Py_UNUSED(self), PyObject *args)
         332                 :            : {
         333                 :        125 :     PyObject *r = NULL;
         334                 :            :     PyObject *pathobj;
         335                 :            :     const wchar_t *path;
         336         [ -  + ]:        125 :     if (!PyArg_ParseTuple(args, "U", &pathobj)) {
         337                 :          0 :         return NULL;
         338                 :            :     }
         339                 :        125 :     path = PyUnicode_AsWideCharString(pathobj, NULL);
         340         [ -  + ]:        125 :     if (!path) {
         341                 :          0 :         return NULL;
         342                 :            :     }
         343                 :        125 :     FILE *fp = _Py_wfopen(path, L"rb");
         344                 :        125 :     PyMem_Free((void *)path);
         345         [ +  + ]:        125 :     if (!fp) {
         346                 :        121 :         PyErr_SetFromErrno(PyExc_OSError);
         347                 :        121 :         return NULL;
         348                 :            :     }
         349                 :            :
         350                 :          4 :     r = PyList_New(0);
         351         [ -  + ]:          4 :     if (!r) {
         352                 :          0 :         fclose(fp);
         353                 :          0 :         return NULL;
         354                 :            :     }
         355                 :          4 :     const size_t MAX_FILE = 32 * 1024;
         356                 :          4 :     char *buffer = (char *)PyMem_Malloc(MAX_FILE);
         357         [ -  + ]:          4 :     if (!buffer) {
         358                 :          0 :         Py_DECREF(r);
         359                 :          0 :         fclose(fp);
         360                 :          0 :         return NULL;
         361                 :            :     }
         362                 :            :
         363                 :          4 :     size_t cb = fread(buffer, 1, MAX_FILE, fp);
         364                 :          4 :     fclose(fp);
         365         [ -  + ]:          4 :     if (!cb) {
         366                 :          0 :         return r;
         367                 :            :     }
         368         [ -  + ]:          4 :     if (cb >= MAX_FILE) {
         369                 :          0 :         Py_DECREF(r);
         370                 :          0 :         PyErr_SetString(PyExc_MemoryError,
         371                 :            :             "cannot read file larger than 32KB during initialization");
         372                 :          0 :         return NULL;
         373                 :            :     }
         374                 :          4 :     buffer[cb] = '\0';
         375                 :            :
         376                 :            :     size_t len;
         377                 :          4 :     wchar_t *wbuffer = _Py_DecodeUTF8_surrogateescape(buffer, cb, &len);
         378                 :          4 :     PyMem_Free((void *)buffer);
         379         [ -  + ]:          4 :     if (!wbuffer) {
         380                 :          0 :         Py_DECREF(r);
         381                 :          0 :         PyErr_NoMemory();
         382                 :          0 :         return NULL;
         383                 :            :     }
         384                 :            :
         385                 :          4 :     wchar_t *p1 = wbuffer;
         386                 :          4 :     wchar_t *p2 = p1;
         387         [ +  + ]:          5 :     while ((p2 = wcschr(p1, L'\n')) != NULL) {
         388                 :          1 :         Py_ssize_t cb = p2 - p1;
         389   [ +  -  +  +  :          2 :         while (cb >= 0 && (p1[cb] == L'\n' || p1[cb] == L'\r')) {
                       -  + ]
         390                 :          1 :             --cb;
         391                 :            :         }
         392                 :          1 :         PyObject *u = PyUnicode_FromWideChar(p1, cb >= 0 ? cb + 1 : 0);
         393   [ +  -  -  + ]:          1 :         if (!u || PyList_Append(r, u) < 0) {
         394                 :          0 :             Py_XDECREF(u);
         395         [ #  # ]:          0 :             Py_CLEAR(r);
         396                 :          0 :             break;
         397                 :            :         }
         398                 :          1 :         Py_DECREF(u);
         399                 :          1 :         p1 = p2 + 1;
         400                 :            :     }
         401   [ +  -  +  -  :          4 :     if (r && p1 && *p1) {
                       +  + ]
         402                 :          3 :         PyObject *u = PyUnicode_FromWideChar(p1, -1);
         403   [ +  -  -  + ]:          3 :         if (!u || PyList_Append(r, u) < 0) {
         404         [ #  # ]:          0 :             Py_CLEAR(r);
         405                 :            :         }
         406                 :          3 :         Py_XDECREF(u);
         407                 :            :     }
         408                 :          4 :     PyMem_RawFree(wbuffer);
         409                 :          4 :     return r;
         410                 :            : }
         411                 :            :
         412                 :            :
         413                 :            : static PyObject *
         414                 :         25 : getpath_realpath(PyObject *Py_UNUSED(self) , PyObject *args)
         415                 :            : {
         416                 :            :     PyObject *pathobj;
         417         [ -  + ]:         25 :     if (!PyArg_ParseTuple(args, "U", &pathobj)) {
         418                 :          0 :         return NULL;
         419                 :            :     }
         420                 :            : #if defined(HAVE_READLINK)
         421                 :            :     /* This readlink calculation only resolves a symlinked file, and
         422                 :            :        does not resolve any path segments. This is consistent with
         423                 :            :        prior releases, however, the realpath implementation below is
         424                 :            :        potentially correct in more cases. */
         425                 :         25 :     PyObject *r = NULL;
         426                 :         25 :     int nlink = 0;
         427                 :         25 :     wchar_t *path = PyUnicode_AsWideCharString(pathobj, NULL);
         428         [ -  + ]:         25 :     if (!path) {
         429                 :          0 :         goto done;
         430                 :            :     }
         431                 :         25 :     wchar_t *path2 = _PyMem_RawWcsdup(path);
         432                 :         25 :     PyMem_Free((void *)path);
         433                 :         25 :     path = path2;
         434         [ +  - ]:         25 :     while (path) {
         435                 :            :         wchar_t resolved[MAXPATHLEN + 1];
         436                 :         25 :         int linklen = _Py_wreadlink(path, resolved, Py_ARRAY_LENGTH(resolved));
         437         [ +  - ]:         25 :         if (linklen == -1) {
         438                 :         25 :             r = PyUnicode_FromWideChar(path, -1);
         439                 :         25 :             break;
         440                 :            :         }
         441         [ #  # ]:          0 :         if (_Py_isabs(resolved)) {
         442                 :          0 :             PyMem_RawFree((void *)path);
         443                 :          0 :             path = _PyMem_RawWcsdup(resolved);
         444                 :            :         } else {
         445                 :          0 :             wchar_t *s = wcsrchr(path, SEP);
         446         [ #  # ]:          0 :             if (s) {
         447                 :          0 :                 *s = L'\0';
         448                 :            :             }
         449                 :          0 :             path2 = _Py_join_relfile(path, resolved);
         450         [ #  # ]:          0 :             if (path2) {
         451                 :          0 :                 path2 = _Py_normpath(path2, -1);
         452                 :            :             }
         453                 :          0 :             PyMem_RawFree((void *)path);
         454                 :          0 :             path = path2;
         455                 :            :         }
         456                 :          0 :         nlink++;
         457                 :            :         /* 40 is the Linux kernel 4.2 limit */
         458         [ #  # ]:          0 :         if (nlink >= 40) {
         459                 :          0 :             PyErr_SetString(PyExc_OSError, "maximum number of symbolic links reached");
         460                 :          0 :             break;
         461                 :            :         }
         462                 :            :     }
         463         [ +  - ]:         25 :     if (!path) {
         464                 :          0 :         PyErr_NoMemory();
         465                 :            :     }
         466                 :         25 : done:
         467                 :         25 :     PyMem_RawFree((void *)path);
         468                 :         25 :     return r;
         469                 :            :
         470                 :            : #elif defined(HAVE_REALPATH)
         471                 :            :     PyObject *r = NULL;
         472                 :            :     struct stat st;
         473                 :            :     const char *narrow = NULL;
         474                 :            :     wchar_t *path = PyUnicode_AsWideCharString(pathobj, NULL);
         475                 :            :     if (!path) {
         476                 :            :         goto done;
         477                 :            :     }
         478                 :            :     narrow = Py_EncodeLocale(path, NULL);
         479                 :            :     if (!narrow) {
         480                 :            :         PyErr_NoMemory();
         481                 :            :         goto done;
         482                 :            :     }
         483                 :            :     if (lstat(narrow, &st)) {
         484                 :            :         PyErr_SetFromErrno(PyExc_OSError);
         485                 :            :         goto done;
         486                 :            :     }
         487                 :            :     if (!S_ISLNK(st.st_mode)) {
         488                 :            :         r = Py_NewRef(pathobj);
         489                 :            :         goto done;
         490                 :            :     }
         491                 :            :     wchar_t resolved[MAXPATHLEN+1];
         492                 :            :     if (_Py_wrealpath(path, resolved, MAXPATHLEN) == NULL) {
         493                 :            :         PyErr_SetFromErrno(PyExc_OSError);
         494                 :            :     } else {
         495                 :            :         r = PyUnicode_FromWideChar(resolved, -1);
         496                 :            :     }
         497                 :            : done:
         498                 :            :     PyMem_Free((void *)path);
         499                 :            :     PyMem_Free((void *)narrow);
         500                 :            :     return r;
         501                 :            : #endif
         502                 :            :
         503                 :            :     return Py_NewRef(pathobj);
         504                 :            : }
         505                 :            :
         506                 :            :
         507                 :            : static PyMethodDef getpath_methods[] = {
         508                 :            :     {"abspath", getpath_abspath, METH_VARARGS, NULL},
         509                 :            :     {"basename", getpath_basename, METH_VARARGS, NULL},
         510                 :            :     {"dirname", getpath_dirname, METH_VARARGS, NULL},
         511                 :            :     {"hassuffix", getpath_hassuffix, METH_VARARGS, NULL},
         512                 :            :     {"isabs", getpath_isabs, METH_VARARGS, NULL},
         513                 :            :     {"isdir", getpath_isdir, METH_VARARGS, NULL},
         514                 :            :     {"isfile", getpath_isfile, METH_VARARGS, NULL},
         515                 :            :     {"isxfile", getpath_isxfile, METH_VARARGS, NULL},
         516                 :            :     {"joinpath", getpath_joinpath, METH_VARARGS, NULL},
         517                 :            :     {"readlines", getpath_readlines, METH_VARARGS, NULL},
         518                 :            :     {"realpath", getpath_realpath, METH_VARARGS, NULL},
         519                 :            :     {NULL, NULL, 0, NULL}
         520                 :            : };
         521                 :            :
         522                 :            :
         523                 :            : /* Two implementations of warn() to use depending on whether warnings
         524                 :            :    are enabled or not. */
         525                 :            :
         526                 :            : static PyObject *
         527                 :          0 : getpath_warn(PyObject *Py_UNUSED(self), PyObject *args)
         528                 :            : {
         529                 :            :     PyObject *msgobj;
         530         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "U", &msgobj)) {
         531                 :          0 :         return NULL;
         532                 :            :     }
         533                 :          0 :     fprintf(stderr, "%s\n", PyUnicode_AsUTF8(msgobj));
         534                 :          0 :     Py_RETURN_NONE;
         535                 :            : }
         536                 :            :
         537                 :            :
         538                 :            : static PyObject *
         539                 :          0 : getpath_nowarn(PyObject *Py_UNUSED(self), PyObject *args)
         540                 :            : {
         541                 :          0 :     Py_RETURN_NONE;
         542                 :            : }
         543                 :            :
         544                 :            :
         545                 :            : static PyMethodDef getpath_warn_method = {"warn", getpath_warn, METH_VARARGS, NULL};
         546                 :            : static PyMethodDef getpath_nowarn_method = {"warn", getpath_nowarn, METH_VARARGS, NULL};
         547                 :            :
         548                 :            : /* Add the helper functions to the dict */
         549                 :            : static int
         550                 :         25 : funcs_to_dict(PyObject *dict, int warnings)
         551                 :            : {
         552         [ +  + ]:        300 :     for (PyMethodDef *m = getpath_methods; m->ml_name; ++m) {
         553                 :        275 :         PyObject *f = PyCFunction_NewEx(m, NULL, NULL);
         554         [ -  + ]:        275 :         if (!f) {
         555                 :          0 :             return 0;
         556                 :            :         }
         557         [ -  + ]:        275 :         if (PyDict_SetItemString(dict, m->ml_name, f) < 0) {
         558                 :          0 :             Py_DECREF(f);
         559                 :          0 :             return 0;
         560                 :            :         }
         561                 :        275 :         Py_DECREF(f);
         562                 :            :     }
         563         [ +  + ]:         25 :     PyMethodDef *m2 = warnings ? &getpath_warn_method : &getpath_nowarn_method;
         564                 :         25 :     PyObject *f = PyCFunction_NewEx(m2, NULL, NULL);
         565         [ -  + ]:         25 :     if (!f) {
         566                 :          0 :         return 0;
         567                 :            :     }
         568         [ -  + ]:         25 :     if (PyDict_SetItemString(dict, m2->ml_name, f) < 0) {
         569                 :          0 :         Py_DECREF(f);
         570                 :          0 :         return 0;
         571                 :            :     }
         572                 :         25 :     Py_DECREF(f);
         573                 :         25 :     return 1;
         574                 :            : }
         575                 :            :
         576                 :            :
         577                 :            : /* Add a wide-character string constant to the dict */
         578                 :            : static int
         579                 :         75 : wchar_to_dict(PyObject *dict, const char *key, const wchar_t *s)
         580                 :            : {
         581                 :            :     PyObject *u;
         582                 :            :     int r;
         583   [ -  +  -  - ]:         75 :     if (s && s[0]) {
         584                 :          0 :         u = PyUnicode_FromWideChar(s, -1);
         585         [ #  # ]:          0 :         if (!u) {
         586                 :          0 :             return 0;
         587                 :            :         }
         588                 :            :     } else {
         589                 :         75 :         u = Py_NewRef(Py_None);
         590                 :            :     }
         591                 :         75 :     r = PyDict_SetItemString(dict, key, u) == 0;
         592                 :         75 :     Py_DECREF(u);
         593                 :         75 :     return r;
         594                 :            : }
         595                 :            :
         596                 :            :
         597                 :            : /* Add a narrow string constant to the dict, using default locale decoding */
         598                 :            : static int
         599                 :        200 : decode_to_dict(PyObject *dict, const char *key, const char *s)
         600                 :            : {
         601                 :        200 :     PyObject *u = NULL;
         602                 :            :     int r;
         603   [ +  +  +  + ]:        300 :     if (s && s[0]) {
         604                 :            :         size_t len;
         605                 :        100 :         const wchar_t *w = Py_DecodeLocale(s, &len);
         606         [ +  - ]:        100 :         if (w) {
         607                 :        100 :             u = PyUnicode_FromWideChar(w, len);
         608                 :        100 :             PyMem_RawFree((void *)w);
         609                 :            :         }
         610         [ -  + ]:        100 :         if (!u) {
         611                 :          0 :             return 0;
         612                 :            :         }
         613                 :            :     } else {
         614                 :        100 :         u = Py_NewRef(Py_None);
         615                 :            :     }
         616                 :        200 :     r = PyDict_SetItemString(dict, key, u) == 0;
         617                 :        200 :     Py_DECREF(u);
         618                 :        200 :     return r;
         619                 :            : }
         620                 :            :
         621                 :            : /* Add an environment variable to the dict, optionally clearing it afterwards */
         622                 :            : static int
         623                 :        100 : env_to_dict(PyObject *dict, const char *key, int and_clear)
         624                 :            : {
         625                 :        100 :     PyObject *u = NULL;
         626                 :        100 :     int r = 0;
         627                 :            :     assert(strncmp(key, "ENV_", 4) == 0);
         628                 :            :     assert(strlen(key) < 64);
         629                 :            : #ifdef MS_WINDOWS
         630                 :            :     wchar_t wkey[64];
         631                 :            :     // Quick convert to wchar_t, since we know key is ASCII
         632                 :            :     wchar_t *wp = wkey;
         633                 :            :     for (const char *p = &key[4]; *p; ++p) {
         634                 :            :         assert(*p < 128);
         635                 :            :         *wp++ = *p;
         636                 :            :     }
         637                 :            :     *wp = L'\0';
         638                 :            :     const wchar_t *v = _wgetenv(wkey);
         639                 :            :     if (v) {
         640                 :            :         u = PyUnicode_FromWideChar(v, -1);
         641                 :            :         if (!u) {
         642                 :            :             PyErr_Clear();
         643                 :            :         }
         644                 :            :     }
         645                 :            : #else
         646                 :        100 :     const char *v = getenv(&key[4]);
         647         [ +  + ]:        100 :     if (v) {
         648                 :            :         size_t len;
         649                 :         25 :         const wchar_t *w = Py_DecodeLocale(v, &len);
         650         [ +  - ]:         25 :         if (w) {
         651                 :         25 :             u = PyUnicode_FromWideChar(w, len);
         652         [ -  + ]:         25 :             if (!u) {
         653                 :          0 :                 PyErr_Clear();
         654                 :            :             }
         655                 :         25 :             PyMem_RawFree((void *)w);
         656                 :            :         }
         657                 :            :     }
         658                 :            : #endif
         659         [ +  + ]:        100 :     if (u) {
         660                 :         25 :         r = PyDict_SetItemString(dict, key, u) == 0;
         661                 :         25 :         Py_DECREF(u);
         662                 :            :     } else {
         663                 :         75 :         r = PyDict_SetItemString(dict, key, Py_None) == 0;
         664                 :            :     }
         665   [ +  -  +  + ]:        100 :     if (r && and_clear) {
         666                 :            : #ifdef MS_WINDOWS
         667                 :            :         _wputenv_s(wkey, L"");
         668                 :            : #else
         669                 :         25 :         unsetenv(&key[4]);
         670                 :            : #endif
         671                 :            :     }
         672                 :        100 :     return r;
         673                 :            : }
         674                 :            :
         675                 :            :
         676                 :            : /* Add an integer constant to the dict */
         677                 :            : static int
         678                 :         75 : int_to_dict(PyObject *dict, const char *key, int v)
         679                 :            : {
         680                 :            :     PyObject *o;
         681                 :            :     int r;
         682                 :         75 :     o = PyLong_FromLong(v);
         683         [ -  + ]:         75 :     if (!o) {
         684                 :          0 :         return 0;
         685                 :            :     }
         686                 :         75 :     r = PyDict_SetItemString(dict, key, o) == 0;
         687                 :         75 :     Py_DECREF(o);
         688                 :         75 :     return r;
         689                 :            : }
         690                 :            :
         691                 :            :
         692                 :            : #ifdef MS_WINDOWS
         693                 :            : static int
         694                 :            : winmodule_to_dict(PyObject *dict, const char *key, HMODULE mod)
         695                 :            : {
         696                 :            :     wchar_t *buffer = NULL;
         697                 :            :     for (DWORD cch = 256; buffer == NULL && cch < (1024 * 1024); cch *= 2) {
         698                 :            :         buffer = (wchar_t*)PyMem_RawMalloc(cch * sizeof(wchar_t));
         699                 :            :         if (buffer) {
         700                 :            :             if (GetModuleFileNameW(mod, buffer, cch) == cch) {
         701                 :            :                 PyMem_RawFree(buffer);
         702                 :            :                 buffer = NULL;
         703                 :            :             }
         704                 :            :         }
         705                 :            :     }
         706                 :            :     int r = wchar_to_dict(dict, key, buffer);
         707                 :            :     PyMem_RawFree(buffer);
         708                 :            :     return r;
         709                 :            : }
         710                 :            : #endif
         711                 :            :
         712                 :            :
         713                 :            : /* Add the current executable's path to the dict */
         714                 :            : static int
         715                 :         25 : progname_to_dict(PyObject *dict, const char *key)
         716                 :            : {
         717                 :            : #ifdef MS_WINDOWS
         718                 :            :     return winmodule_to_dict(dict, key, NULL);
         719                 :            : #elif defined(__APPLE__)
         720                 :            :     char *path;
         721                 :            :     uint32_t pathLen = 256;
         722                 :            :     while (pathLen) {
         723                 :            :         path = PyMem_RawMalloc((pathLen + 1) * sizeof(char));
         724                 :            :         if (!path) {
         725                 :            :             return 0;
         726                 :            :         }
         727                 :            :         if (_NSGetExecutablePath(path, &pathLen) != 0) {
         728                 :            :             PyMem_RawFree(path);
         729                 :            :             continue;
         730                 :            :         }
         731                 :            :         // Only keep if the path is absolute
         732                 :            :         if (path[0] == SEP) {
         733                 :            :             int r = decode_to_dict(dict, key, path);
         734                 :            :             PyMem_RawFree(path);
         735                 :            :             return r;
         736                 :            :         }
         737                 :            :         // Fall back and store None
         738                 :            :         PyMem_RawFree(path);
         739                 :            :         break;
         740                 :            :     }
         741                 :            : #endif
         742                 :         25 :     return PyDict_SetItemString(dict, key, Py_None) == 0;
         743                 :            : }
         744                 :            :
         745                 :            :
         746                 :            : /* Add the runtime library's path to the dict */
         747                 :            : static int
         748                 :         25 : library_to_dict(PyObject *dict, const char *key)
         749                 :            : {
         750                 :            : #ifdef MS_WINDOWS
         751                 :            : #ifdef Py_ENABLE_SHARED
         752                 :            :     extern HMODULE PyWin_DLLhModule;
         753                 :            :     if (PyWin_DLLhModule) {
         754                 :            :         return winmodule_to_dict(dict, key, PyWin_DLLhModule);
         755                 :            :     }
         756                 :            : #endif
         757                 :            : #elif defined(WITH_NEXT_FRAMEWORK)
         758                 :            :     static char modPath[MAXPATHLEN + 1];
         759                 :            :     static int modPathInitialized = -1;
         760                 :            :     if (modPathInitialized < 0) {
         761                 :            :         modPathInitialized = 0;
         762                 :            :
         763                 :            :         /* On Mac OS X we have a special case if we're running from a framework.
         764                 :            :            This is because the python home should be set relative to the library,
         765                 :            :            which is in the framework, not relative to the executable, which may
         766                 :            :            be outside of the framework. Except when we're in the build
         767                 :            :            directory... */
         768                 :            :         NSSymbol symbol = NSLookupAndBindSymbol("_Py_Initialize");
         769                 :            :         if (symbol != NULL) {
         770                 :            :             NSModule pythonModule = NSModuleForSymbol(symbol);
         771                 :            :             if (pythonModule != NULL) {
         772                 :            :                 /* Use dylib functions to find out where the framework was loaded from */
         773                 :            :                 const char *path = NSLibraryNameForModule(pythonModule);
         774                 :            :                 if (path) {
         775                 :            :                     strncpy(modPath, path, MAXPATHLEN);
         776                 :            :                     modPathInitialized = 1;
         777                 :            :                 }
         778                 :            :             }
         779                 :            :         }
         780                 :            :     }
         781                 :            :     if (modPathInitialized > 0) {
         782                 :            :         return decode_to_dict(dict, key, modPath);
         783                 :            :     }
         784                 :            : #endif
         785                 :         25 :     return PyDict_SetItemString(dict, key, Py_None) == 0;
         786                 :            : }
         787                 :            :
         788                 :            :
         789                 :            : PyObject *
         790                 :         25 : _Py_Get_Getpath_CodeObject(void)
         791                 :            : {
         792                 :         25 :     return PyMarshal_ReadObjectFromString(
         793                 :            :         (const char*)_Py_M__getpath, sizeof(_Py_M__getpath));
         794                 :            : }
         795                 :            :
         796                 :            :
         797                 :            : /* Perform the actual path calculation.
         798                 :            :
         799                 :            :    When compute_path_config is 0, this only reads any initialised path
         800                 :            :    config values into the PyConfig struct. For example, Py_SetHome() or
         801                 :            :    Py_SetPath(). The only error should be due to failed memory allocation.
         802                 :            :
         803                 :            :    When compute_path_config is 1, full path calculation is performed.
         804                 :            :    The GIL must be held, and there may be filesystem access, side
         805                 :            :    effects, and potential unraisable errors that are reported directly
         806                 :            :    to stderr.
         807                 :            :
         808                 :            :    Calling this function multiple times on the same PyConfig is only
         809                 :            :    safe because already-configured values are not recalculated. To
         810                 :            :    actually recalculate paths, you need a clean PyConfig.
         811                 :            : */
         812                 :            : PyStatus
         813                 :         71 : _PyConfig_InitPathConfig(PyConfig *config, int compute_path_config)
         814                 :            : {
         815                 :         71 :     PyStatus status = _PyPathConfig_ReadGlobal(config);
         816                 :            :
         817   [ +  -  +  + ]:         71 :     if (_PyStatus_EXCEPTION(status) || !compute_path_config) {
         818                 :         46 :         return status;
         819                 :            :     }
         820                 :            :
         821         [ -  + ]:         25 :     if (!_PyThreadState_UncheckedGet()) {
         822                 :          0 :         return PyStatus_Error("cannot calculate path configuration without GIL");
         823                 :            :     }
         824                 :            :
         825                 :         25 :     PyObject *configDict = _PyConfig_AsDict(config);
         826         [ -  + ]:         25 :     if (!configDict) {
         827                 :          0 :         PyErr_Clear();
         828                 :          0 :         return PyStatus_NoMemory();
         829                 :            :     }
         830                 :            :
         831                 :         25 :     PyObject *dict = PyDict_New();
         832         [ -  + ]:         25 :     if (!dict) {
         833                 :          0 :         PyErr_Clear();
         834                 :          0 :         Py_DECREF(configDict);
         835                 :          0 :         return PyStatus_NoMemory();
         836                 :            :     }
         837                 :            :
         838         [ -  + ]:         25 :     if (PyDict_SetItemString(dict, "config", configDict) < 0) {
         839                 :          0 :         PyErr_Clear();
         840                 :          0 :         Py_DECREF(configDict);
         841                 :          0 :         Py_DECREF(dict);
         842                 :          0 :         return PyStatus_NoMemory();
         843                 :            :     }
         844                 :            :     /* reference now held by dict */
         845                 :         25 :     Py_DECREF(configDict);
         846                 :            :
         847                 :         25 :     PyObject *co = _Py_Get_Getpath_CodeObject();
         848   [ +  -  -  + ]:         25 :     if (!co || !PyCode_Check(co)) {
         849                 :          0 :         PyErr_Clear();
         850                 :          0 :         Py_XDECREF(co);
         851                 :          0 :         Py_DECREF(dict);
         852                 :          0 :         return PyStatus_Error("error reading frozen getpath.py");
         853                 :            :     }
         854                 :            :
         855                 :            : #ifdef MS_WINDOWS
         856                 :            :     PyObject *winreg = PyImport_ImportModule("winreg");
         857                 :            :     if (!winreg || PyDict_SetItemString(dict, "winreg", winreg) < 0) {
         858                 :            :         PyErr_Clear();
         859                 :            :         Py_XDECREF(winreg);
         860                 :            :         if (PyDict_SetItemString(dict, "winreg", Py_None) < 0) {
         861                 :            :             PyErr_Clear();
         862                 :            :             Py_DECREF(co);
         863                 :            :             Py_DECREF(dict);
         864                 :            :             return PyStatus_Error("error importing winreg module");
         865                 :            :         }
         866                 :            :     } else {
         867                 :            :         Py_DECREF(winreg);
         868                 :            :     }
         869                 :            : #endif
         870                 :            :
         871         [ +  - ]:         25 :     if (
         872                 :            : #ifdef MS_WINDOWS
         873                 :            :         !decode_to_dict(dict, "os_name", "nt") ||
         874                 :            : #elif defined(__APPLE__)
         875                 :            :         !decode_to_dict(dict, "os_name", "darwin") ||
         876                 :            : #else
         877         [ +  - ]:         50 :         !decode_to_dict(dict, "os_name", "posix") ||
         878                 :            : #endif
         879                 :            : #ifdef WITH_NEXT_FRAMEWORK
         880                 :            :         !int_to_dict(dict, "WITH_NEXT_FRAMEWORK", 1) ||
         881                 :            : #else
         882         [ +  - ]:         50 :         !int_to_dict(dict, "WITH_NEXT_FRAMEWORK", 0) ||
         883                 :            : #endif
         884         [ +  - ]:         50 :         !decode_to_dict(dict, "PREFIX", PREFIX) ||
         885         [ +  - ]:         50 :         !decode_to_dict(dict, "EXEC_PREFIX", EXEC_PREFIX) ||
         886         [ +  - ]:         50 :         !decode_to_dict(dict, "PYTHONPATH", PYTHONPATH) ||
         887         [ +  - ]:         50 :         !decode_to_dict(dict, "VPATH", VPATH) ||
         888         [ +  - ]:         50 :         !decode_to_dict(dict, "PLATLIBDIR", PLATLIBDIR) ||
         889         [ +  - ]:         50 :         !decode_to_dict(dict, "PYDEBUGEXT", PYDEBUGEXT) ||
         890         [ +  - ]:         50 :         !int_to_dict(dict, "VERSION_MAJOR", PY_MAJOR_VERSION) ||
         891         [ +  - ]:         50 :         !int_to_dict(dict, "VERSION_MINOR", PY_MINOR_VERSION) ||
         892         [ +  - ]:         50 :         !decode_to_dict(dict, "PYWINVER", PYWINVER) ||
         893         [ +  - ]:         50 :         !wchar_to_dict(dict, "EXE_SUFFIX", EXE_SUFFIX) ||
         894         [ +  - ]:         50 :         !env_to_dict(dict, "ENV_PATH", 0) ||
         895         [ +  - ]:         50 :         !env_to_dict(dict, "ENV_PYTHONHOME", 0) ||
         896         [ +  - ]:         50 :         !env_to_dict(dict, "ENV_PYTHONEXECUTABLE", 0) ||
         897         [ +  - ]:         50 :         !env_to_dict(dict, "ENV___PYVENV_LAUNCHER__", 1) ||
         898         [ +  - ]:         50 :         !progname_to_dict(dict, "real_executable") ||
         899         [ +  - ]:         50 :         !library_to_dict(dict, "library") ||
         900         [ +  - ]:         50 :         !wchar_to_dict(dict, "executable_dir", NULL) ||
         901         [ +  - ]:         50 :         !wchar_to_dict(dict, "py_setpath", _PyPathConfig_GetGlobalModuleSearchPath()) ||
         902         [ +  - ]:         50 :         !funcs_to_dict(dict, config->pathconfig_warnings) ||
         903                 :            : #ifndef MS_WINDOWS
         904         [ -  + ]:         50 :         PyDict_SetItemString(dict, "winreg", Py_None) < 0 ||
         905                 :            : #endif
         906                 :         25 :         PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()) < 0
         907                 :            :     ) {
         908                 :          0 :         Py_DECREF(co);
         909                 :          0 :         Py_DECREF(dict);
         910                 :          0 :         _PyErr_WriteUnraisableMsg("error evaluating initial values", NULL);
         911                 :          0 :         return PyStatus_Error("error evaluating initial values");
         912                 :            :     }
         913                 :            :
         914                 :         25 :     PyObject *r = PyEval_EvalCode(co, dict, dict);
         915                 :         25 :     Py_DECREF(co);
         916                 :            :
         917         [ -  + ]:         25 :     if (!r) {
         918                 :          0 :         Py_DECREF(dict);
         919                 :          0 :         _PyErr_WriteUnraisableMsg("error evaluating path", NULL);
         920                 :          0 :         return PyStatus_Error("error evaluating path");
         921                 :            :     }
         922                 :         25 :     Py_DECREF(r);
         923                 :            :
         924                 :            : #if 0
         925                 :            :     PyObject *it = PyObject_GetIter(configDict);
         926                 :            :     for (PyObject *k = PyIter_Next(it); k; k = PyIter_Next(it)) {
         927                 :            :         if (!strcmp("__builtins__", PyUnicode_AsUTF8(k))) {
         928                 :            :             Py_DECREF(k);
         929                 :            :             continue;
         930                 :            :         }
         931                 :            :         fprintf(stderr, "%s = ", PyUnicode_AsUTF8(k));
         932                 :            :         PyObject *o = PyDict_GetItem(configDict, k);
         933                 :            :         o = PyObject_Repr(o);
         934                 :            :         fprintf(stderr, "%s\n", PyUnicode_AsUTF8(o));
         935                 :            :         Py_DECREF(o);
         936                 :            :         Py_DECREF(k);
         937                 :            :     }
         938                 :            :     Py_DECREF(it);
         939                 :            : #endif
         940                 :            :
         941         [ -  + ]:         25 :     if (_PyConfig_FromDict(config, configDict) < 0) {
         942                 :          0 :         _PyErr_WriteUnraisableMsg("reading getpath results", NULL);
         943                 :          0 :         Py_DECREF(dict);
         944                 :          0 :         return PyStatus_Error("error getting getpath results");
         945                 :            :     }
         946                 :            :
         947                 :         25 :     Py_DECREF(dict);
         948                 :            :
         949                 :         25 :     return _PyStatus_OK();
         950                 :            : }
         951                 :            :

Generated by: LCOV version 1.14