bpo-36301: Error if decoding pybuilddir.txt fails (GH-12422) · python/cpython@5f9cf23

5 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -30,7 +30,8 @@ PyAPI_FUNC(int) _Py_EncodeUTF8Ex(

3030
3131

PyAPI_FUNC(wchar_t*) _Py_DecodeUTF8_surrogateescape(

3232

const char *arg,

33-

Py_ssize_t arglen);

33+

Py_ssize_t arglen,

34+

size_t *wlen);

3435
3536

PyAPI_FUNC(int) _Py_GetForceASCII(void);

3637
Original file line numberDiff line numberDiff line change

@@ -0,0 +1,2 @@

1+

Python initialization now fails if decoding ``pybuilddir.txt`` configuration

2+

file fails at startup.

Original file line numberDiff line numberDiff line change

@@ -563,23 +563,27 @@ search_for_exec_prefix(const _PyCoreConfig *core_config,

563563

}

564564

else {

565565

char buf[MAXPATHLEN+1];

566-

wchar_t *rel_builddir_path;

567566

n = fread(buf, 1, MAXPATHLEN, f);

568567

buf[n] = '\0';

569568

fclose(f);

570-

rel_builddir_path = _Py_DecodeUTF8_surrogateescape(buf, n);

571-

if (rel_builddir_path) {

572-

wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN);

573-

exec_prefix[MAXPATHLEN] = L'\0';

574-

err = joinpath(exec_prefix, rel_builddir_path);

575-

PyMem_RawFree(rel_builddir_path );

576-

if (_Py_INIT_FAILED(err)) {

577-

return err;

578-

}

579569
580-

*found = -1;

581-

return _Py_INIT_OK();

570+

size_t dec_len;

571+

wchar_t *pybuilddir;

572+

pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len);

573+

if (!pybuilddir) {

574+

return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len);

582575

}

576+
577+

wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN);

578+

exec_prefix[MAXPATHLEN] = L'\0';

579+

err = joinpath(exec_prefix, pybuilddir);

580+

PyMem_RawFree(pybuilddir );

581+

if (_Py_INIT_FAILED(err)) {

582+

return err;

583+

}

584+
585+

*found = -1;

586+

return _Py_INIT_OK();

583587

}

584588

}

585589
Original file line numberDiff line numberDiff line change

@@ -5064,12 +5064,21 @@ _Py_DecodeUTF8Ex(const char *s, Py_ssize_t size, wchar_t **wstr, size_t *wlen,

50645064

return 0;

50655065

}

50665066
5067+
50675068

wchar_t*

5068-

_Py_DecodeUTF8_surrogateescape(const char *arg, Py_ssize_t arglen)

5069+

_Py_DecodeUTF8_surrogateescape(const char *arg, Py_ssize_t arglen,

5070+

size_t *wlen)

50695071

{

50705072

wchar_t *wstr;

5071-

int res = _Py_DecodeUTF8Ex(arg, arglen, &wstr, NULL, NULL, 1);

5073+

int res = _Py_DecodeUTF8Ex(arg, arglen,

5074+

&wstr, wlen,

5075+

NULL, _Py_ERROR_SURROGATEESCAPE);

50725076

if (res != 0) {

5077+

/* _Py_DecodeUTF8Ex() must support _Py_ERROR_SURROGATEESCAPE */

5078+

assert(res != -3);

5079+

if (wlen) {

5080+

*wlen = (size_t)res;

5081+

}

50735082

return NULL;

50745083

}

50755084

return wstr;

Original file line numberDiff line numberDiff line change

@@ -712,7 +712,7 @@ _Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,

712712

continue;

713713

}

714714
715-

wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n);

715+

wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);

716716

if (tmpbuffer) {

717717

wchar_t * state;

718718

wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);