Skip to content

Commit 1be0d11

Browse files
authored
bpo-36352: Clarify fileutils.h documentation (GH-12406)
The last parameter of _Py_wreadlink(), _Py_wrealpath() and _Py_wgetcwd() is a length, not a size: number of characters including the trailing NUL character. Enhance also documentation of error conditions.
1 parent 72c7b37 commit 1be0d11

2 files changed

Lines changed: 30 additions & 17 deletions

File tree

Include/fileutils.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,19 +140,25 @@ PyAPI_FUNC(Py_ssize_t) _Py_write_noraise(
140140
PyAPI_FUNC(int) _Py_wreadlink(
141141
const wchar_t *path,
142142
wchar_t *buf,
143-
size_t bufsiz);
143+
/* Number of characters of 'buf' buffer
144+
including the trailing NUL character */
145+
size_t buflen);
144146
#endif
145147

146148
#ifdef HAVE_REALPATH
147149
PyAPI_FUNC(wchar_t*) _Py_wrealpath(
148150
const wchar_t *path,
149151
wchar_t *resolved_path,
150-
size_t resolved_path_size);
152+
/* Number of characters of 'resolved_path' buffer
153+
including the trailing NUL character */
154+
size_t resolved_path_len);
151155
#endif
152156

153157
PyAPI_FUNC(wchar_t*) _Py_wgetcwd(
154158
wchar_t *buf,
155-
size_t size);
159+
/* Number of characters of 'buf' buffer
160+
including the trailing NUL character */
161+
size_t buflen);
156162

157163
PyAPI_FUNC(int) _Py_get_inheritable(int fd);
158164

Python/fileutils.c

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,10 +1629,12 @@ _Py_write_noraise(int fd, const void *buf, size_t count)
16291629
#ifdef HAVE_READLINK
16301630

16311631
/* Read value of symbolic link. Encode the path to the locale encoding, decode
1632-
the result from the locale encoding. Return -1 on error. */
1632+
the result from the locale encoding.
16331633
1634+
Return -1 on encoding error, on readlink() error, if the internal buffer is
1635+
too short, on decoding error, or if 'buf' is too short. */
16341636
int
1635-
_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz)
1637+
_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t buflen)
16361638
{
16371639
char *cpath;
16381640
char cbuf[MAXPATHLEN];
@@ -1659,12 +1661,13 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz)
16591661
errno = EINVAL;
16601662
return -1;
16611663
}
1662-
if (bufsiz <= r1) {
1664+
/* wbuf must have space to store the trailing NUL character */
1665+
if (buflen <= r1) {
16631666
PyMem_RawFree(wbuf);
16641667
errno = EINVAL;
16651668
return -1;
16661669
}
1667-
wcsncpy(buf, wbuf, bufsiz);
1670+
wcsncpy(buf, wbuf, buflen);
16681671
PyMem_RawFree(wbuf);
16691672
return (int)r1;
16701673
}
@@ -1674,11 +1677,12 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz)
16741677

16751678
/* Return the canonicalized absolute pathname. Encode path to the locale
16761679
encoding, decode the result from the locale encoding.
1677-
Return NULL on error. */
16781680
1681+
Return NULL on encoding error, realpath() error, decoding error
1682+
or if 'resolved_path' is too short. */
16791683
wchar_t*
16801684
_Py_wrealpath(const wchar_t *path,
1681-
wchar_t *resolved_path, size_t resolved_path_size)
1685+
wchar_t *resolved_path, size_t resolved_path_len)
16821686
{
16831687
char *cpath;
16841688
char cresolved_path[MAXPATHLEN];
@@ -1700,27 +1704,29 @@ _Py_wrealpath(const wchar_t *path,
17001704
errno = EINVAL;
17011705
return NULL;
17021706
}
1703-
if (resolved_path_size <= r) {
1707+
/* wresolved_path must have space to store the trailing NUL character */
1708+
if (resolved_path_len <= r) {
17041709
PyMem_RawFree(wresolved_path);
17051710
errno = EINVAL;
17061711
return NULL;
17071712
}
1708-
wcsncpy(resolved_path, wresolved_path, resolved_path_size);
1713+
wcsncpy(resolved_path, wresolved_path, resolved_path_len);
17091714
PyMem_RawFree(wresolved_path);
17101715
return resolved_path;
17111716
}
17121717
#endif
17131718

17141719
/* Get the current directory. size is the buffer size in wide characters
17151720
including the null character. Decode the path from the locale encoding.
1716-
Return NULL on error. */
17171721
1722+
Return NULL on getcwd() error, on decoding error, or if 'buf' is
1723+
too short. */
17181724
wchar_t*
1719-
_Py_wgetcwd(wchar_t *buf, size_t size)
1725+
_Py_wgetcwd(wchar_t *buf, size_t buflen)
17201726
{
17211727
#ifdef MS_WINDOWS
1722-
int isize = (int)Py_MIN(size, INT_MAX);
1723-
return _wgetcwd(buf, isize);
1728+
int ibuflen = (int)Py_MIN(buflen, INT_MAX);
1729+
return _wgetcwd(buf, ibuflen);
17241730
#else
17251731
char fname[MAXPATHLEN];
17261732
wchar_t *wname;
@@ -1731,11 +1737,12 @@ _Py_wgetcwd(wchar_t *buf, size_t size)
17311737
wname = Py_DecodeLocale(fname, &len);
17321738
if (wname == NULL)
17331739
return NULL;
1734-
if (size <= len) {
1740+
/* wname must have space to store the trailing NUL character */
1741+
if (buflen <= len) {
17351742
PyMem_RawFree(wname);
17361743
return NULL;
17371744
}
1738-
wcsncpy(buf, wname, size);
1745+
wcsncpy(buf, wname, buflen);
17391746
PyMem_RawFree(wname);
17401747
return buf;
17411748
#endif

0 commit comments

Comments
 (0)