From 1be0d1135f5627d0525eab635cf2da441d9cbc08 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 18 Mar 2019 17:47:26 +0100 Subject: [PATCH] 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. --- Include/fileutils.h | 12 +++++++++--- Python/fileutils.c | 35 +++++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/Include/fileutils.h b/Include/fileutils.h index 830e56ad367..0be8b0ae3b3 100644 --- a/Include/fileutils.h +++ b/Include/fileutils.h @@ -140,19 +140,25 @@ PyAPI_FUNC(Py_ssize_t) _Py_write_noraise( PyAPI_FUNC(int) _Py_wreadlink( const wchar_t *path, wchar_t *buf, - size_t bufsiz); + /* Number of characters of 'buf' buffer + including the trailing NUL character */ + size_t buflen); #endif #ifdef HAVE_REALPATH PyAPI_FUNC(wchar_t*) _Py_wrealpath( const wchar_t *path, wchar_t *resolved_path, - size_t resolved_path_size); + /* Number of characters of 'resolved_path' buffer + including the trailing NUL character */ + size_t resolved_path_len); #endif PyAPI_FUNC(wchar_t*) _Py_wgetcwd( wchar_t *buf, - size_t size); + /* Number of characters of 'buf' buffer + including the trailing NUL character */ + size_t buflen); PyAPI_FUNC(int) _Py_get_inheritable(int fd); diff --git a/Python/fileutils.c b/Python/fileutils.c index 75e015afaec..0ac690a211c 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -1629,10 +1629,12 @@ _Py_write_noraise(int fd, const void *buf, size_t count) #ifdef HAVE_READLINK /* Read value of symbolic link. Encode the path to the locale encoding, decode - the result from the locale encoding. Return -1 on error. */ + the result from the locale encoding. + Return -1 on encoding error, on readlink() error, if the internal buffer is + too short, on decoding error, or if 'buf' is too short. */ int -_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) +_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t buflen) { char *cpath; char cbuf[MAXPATHLEN]; @@ -1659,12 +1661,13 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) errno = EINVAL; return -1; } - if (bufsiz <= r1) { + /* wbuf must have space to store the trailing NUL character */ + if (buflen <= r1) { PyMem_RawFree(wbuf); errno = EINVAL; return -1; } - wcsncpy(buf, wbuf, bufsiz); + wcsncpy(buf, wbuf, buflen); PyMem_RawFree(wbuf); return (int)r1; } @@ -1674,11 +1677,12 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) /* Return the canonicalized absolute pathname. Encode path to the locale encoding, decode the result from the locale encoding. - Return NULL on error. */ + Return NULL on encoding error, realpath() error, decoding error + or if 'resolved_path' is too short. */ wchar_t* _Py_wrealpath(const wchar_t *path, - wchar_t *resolved_path, size_t resolved_path_size) + wchar_t *resolved_path, size_t resolved_path_len) { char *cpath; char cresolved_path[MAXPATHLEN]; @@ -1700,12 +1704,13 @@ _Py_wrealpath(const wchar_t *path, errno = EINVAL; return NULL; } - if (resolved_path_size <= r) { + /* wresolved_path must have space to store the trailing NUL character */ + if (resolved_path_len <= r) { PyMem_RawFree(wresolved_path); errno = EINVAL; return NULL; } - wcsncpy(resolved_path, wresolved_path, resolved_path_size); + wcsncpy(resolved_path, wresolved_path, resolved_path_len); PyMem_RawFree(wresolved_path); return resolved_path; } @@ -1713,14 +1718,15 @@ _Py_wrealpath(const wchar_t *path, /* Get the current directory. size is the buffer size in wide characters including the null character. Decode the path from the locale encoding. - Return NULL on error. */ + Return NULL on getcwd() error, on decoding error, or if 'buf' is + too short. */ wchar_t* -_Py_wgetcwd(wchar_t *buf, size_t size) +_Py_wgetcwd(wchar_t *buf, size_t buflen) { #ifdef MS_WINDOWS - int isize = (int)Py_MIN(size, INT_MAX); - return _wgetcwd(buf, isize); + int ibuflen = (int)Py_MIN(buflen, INT_MAX); + return _wgetcwd(buf, ibuflen); #else char fname[MAXPATHLEN]; wchar_t *wname; @@ -1731,11 +1737,12 @@ _Py_wgetcwd(wchar_t *buf, size_t size) wname = Py_DecodeLocale(fname, &len); if (wname == NULL) return NULL; - if (size <= len) { + /* wname must have space to store the trailing NUL character */ + if (buflen <= len) { PyMem_RawFree(wname); return NULL; } - wcsncpy(buf, wname, size); + wcsncpy(buf, wname, buflen); PyMem_RawFree(wname); return buf; #endif