bpo-20443: _PyConfig_Read() gets the absolute path of run_filename (GH-14053)

Python now gets the absolute path of the script filename specified on
the command line (ex: "python3 script.py"): the __file__ attribute of
the __main__ module, sys.argv[0] and sys.path[0] become an absolute
path, rather than a relative path.

* Add _Py_isabs() and _Py_abspath() functions.
* _PyConfig_Read() now tries to get the absolute path of
  run_filename, but keeps the relative path if _Py_abspath() fails.
* Reimplement os._getfullpathname() using _Py_abspath().
* Use _Py_isabs() in getpath.c.
diff --git a/Modules/getpath.c b/Modules/getpath.c
index 5f80738..751c0b7 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -240,7 +240,7 @@
 joinpath(wchar_t *buffer, const wchar_t *stuff, size_t buflen)
 {
     size_t n, k;
-    if (stuff[0] != SEP) {
+    if (!_Py_isabs(stuff)) {
         n = wcslen(buffer);
         if (n >= buflen) {
             return PATHLEN_ERR();
@@ -283,7 +283,7 @@
 static PyStatus
 copy_absolute(wchar_t *path, const wchar_t *p, size_t pathlen)
 {
-    if (p[0] == SEP) {
+    if (_Py_isabs(p)) {
         if (safe_wcscpy(path, p, pathlen) < 0) {
             return PATHLEN_ERR();
         }
@@ -312,7 +312,7 @@
 static PyStatus
 absolutize(wchar_t *path, size_t path_len)
 {
-    if (path[0] == SEP) {
+    if (_Py_isabs(path)) {
         return _PyStatus_OK();
     }
 
@@ -761,7 +761,7 @@
       * absolutize() should help us out below
       */
     else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) &&
-            execpath[0] == SEP)
+            _Py_isabs(execpath))
     {
         size_t len;
         wchar_t *path = Py_DecodeLocale(execpath, &len);
@@ -815,7 +815,7 @@
     else {
         program_full_path[0] = '\0';
     }
-    if (program_full_path[0] != SEP && program_full_path[0] != '\0') {
+    if (!_Py_isabs(program_full_path) && program_full_path[0] != '\0') {
         status = absolutize(program_full_path, program_full_path_len);
         if (_PyStatus_EXCEPTION(status)) {
             return status;
@@ -916,7 +916,7 @@
     const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer);
     int linklen = _Py_wreadlink(program_full_path, tmpbuffer, buflen);
     while (linklen != -1) {
-        if (tmpbuffer[0] == SEP) {
+        if (_Py_isabs(tmpbuffer)) {
             /* tmpbuffer should never be longer than MAXPATHLEN,
                but extra check does not hurt */
             if (safe_wcscpy(calculate->argv0_path, tmpbuffer, argv0_path_len) < 0) {
@@ -1046,7 +1046,7 @@
     while (1) {
         wchar_t *delim = wcschr(defpath, DELIM);
 
-        if (defpath[0] != SEP) {
+        if (!_Py_isabs(defpath)) {
             /* Paths are relative to prefix */
             bufsz += prefixsz;
         }
@@ -1088,7 +1088,7 @@
     while (1) {
         wchar_t *delim = wcschr(defpath, DELIM);
 
-        if (defpath[0] != SEP) {
+        if (!_Py_isabs(defpath)) {
             wcscat(buf, prefix);
             if (prefixsz >= 2 && prefix[prefixsz - 2] != SEP &&
                 defpath[0] != (delim ? DELIM : L'\0'))
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index b2fd45b..10549d6f 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -3784,29 +3784,25 @@
 os__getfullpathname_impl(PyObject *module, path_t *path)
 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
 {
-    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
-    wchar_t *wtemp;
-    DWORD result;
-    PyObject *v;
+    wchar_t *abspath;
 
-    result = GetFullPathNameW(path->wide,
-                              Py_ARRAY_LENGTH(woutbuf),
-                              woutbuf, &wtemp);
-    if (result > Py_ARRAY_LENGTH(woutbuf)) {
-        woutbufp = PyMem_New(wchar_t, result);
-        if (!woutbufp)
-            return PyErr_NoMemory();
-        result = GetFullPathNameW(path->wide, result, woutbufp, &wtemp);
+    /* _Py_abspath() is implemented with GetFullPathNameW() on Windows */
+    if (_Py_abspath(path->wide, &abspath) < 0) {
+        return win32_error_object("GetFullPathNameW", path->object);
     }
-    if (result) {
-        v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp));
-        if (path->narrow)
-            Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
-    } else
-        v = win32_error_object("GetFullPathNameW", path->object);
-    if (woutbufp != woutbuf)
-        PyMem_Free(woutbufp);
-    return v;
+    if (abspath == NULL) {
+        return PyErr_NoMemory();
+    }
+
+    PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
+    PyMem_RawFree(abspath);
+    if (str == NULL) {
+        return NULL;
+    }
+    if (path->narrow) {
+        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
+    }
+    return str;
 }