Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-106242: Fix path truncation in normpath #106816

Merged
merged 27 commits into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d1fe8fa
added _Py_normpathAndSize
finnagin Jul 3, 2023
726da04
Merge remote-tracking branch 'upstream/main' into 106242
finnagin Jul 3, 2023
8cab42c
PyAPI_FUNC -> extern
finnagin Jul 5, 2023
82a9d36
remove prinfs
finnagin Jul 5, 2023
6c18bf8
fix length calculation
finnagin Jul 5, 2023
c90249d
length -> norm_size, fix begining null char case
finnagin Jul 6, 2023
8e1f1ea
fix norm_size calculation
finnagin Jul 6, 2023
3003891
add test cases
finnagin Jul 6, 2023
2fcae77
Merge remote-tracking branch 'upstream/main' into 106242
finnagin Jul 6, 2023
30fa3a4
move tests to test_genericpath.py
finnagin Jul 6, 2023
f0afe44
handle edge cases
finnagin Jul 6, 2023
6412901
decrement p2 when == minp2 & update minp2 handling with leading ./
finnagin Jul 13, 2023
78192de
change test case to no longer include null character
finnagin Jul 13, 2023
199abac
Merge remote-tracking branch 'upstream/main' into 106242
finnagin Jul 13, 2023
cbe57c4
Merge branch 'python:main' into 106242
finnagin Jul 13, 2023
4b9de2c
Add norm_size variable description, add normpath description
finnagin Jul 13, 2023
f1731f1
update normpathAndSize description
finnagin Jul 13, 2023
d7f7045
norm_size->normsize
finnagin Jul 16, 2023
184fde9
Merge remote-tracking branch 'upstream/main' into 106242
finnagin Jul 16, 2023
9e0d52a
remove trailing whitespace
finnagin Jul 16, 2023
3815967
Merge remote-tracking branch 'upstream/main' into 106242
finnagin Jul 16, 2023
d9d78cc
Merge branch 'python:main' into 106242
finnagin Jul 16, 2023
3ef9e3b
_Py_normpathAndSize -> _Py_normpath_and_size
finnagin Jul 17, 2023
c885d13
revert test_addpackage_import_bad_pth_file change
finnagin Jul 17, 2023
d896d45
merge upstream/main, fix merge conflicts
finnagin Aug 14, 2023
0959e2b
📜🤖 Added by blurb_it.
blurb-it[bot] Aug 14, 2023
aecae84
Update Misc/NEWS.d/next/Library/2023-08-14-23-11-11.gh-issue-106242.7…
finnagin Aug 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Include/internal/pycore_fileutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ extern int _Py_add_relfile(wchar_t *dirname,
size_t bufsize);
extern size_t _Py_find_basename(const wchar_t *filename);
PyAPI_FUNC(wchar_t*) _Py_normpath(wchar_t *path, Py_ssize_t size);
extern wchar_t *_Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *length);

// The Windows Games API family does not provide these functions
// so provide our own implementations. Remove them in case they get added
Expand Down
4 changes: 4 additions & 0 deletions Lib/test/test_genericpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,10 @@ def test_normpath_issue5827(self):
for path in ('', '.', '/', '\\', '///foo/.//bar//'):
self.assertIsInstance(self.pathmodule.normpath(path), str)

def test_normpath_issue106242(self):
for path in ('\x00', 'foo\x00bar', '\x00\x00', '\x00foo', 'foo\x00'):
self.assertEqual(self.pathmodule.normpath(path), path)

def test_abspath_issue3426(self):
# Check that abspath returns unicode when the arg is unicode
# with both ASCII and non-ASCII cwds.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixes :func:`os.path.normpath` to handle embedded null characters without truncating the path.
4 changes: 3 additions & 1 deletion Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -5274,7 +5274,9 @@ os__path_normpath_impl(PyObject *module, PyObject *path)
if (!buffer) {
return NULL;
}
PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1);
Py_ssize_t norm_len;
wchar_t *norm_path = _Py_normpath_and_size(buffer, len, &norm_len);
PyObject *result = PyUnicode_FromWideChar(norm_path, norm_len);
PyMem_Free(buffer);
return result;
}
Expand Down
29 changes: 21 additions & 8 deletions Python/fileutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -2377,12 +2377,14 @@
path, which will be within the original buffer. Guaranteed to not
make the path longer, and will not fail. 'size' is the length of
the path, if known. If -1, the first null character will be assumed
to be the end of the path. */
to be the end of the path. 'normsize' will be set to contain the
length of the resulting normalized path. */
wchar_t *
_Py_normpath(wchar_t *path, Py_ssize_t size)
_Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize)
{
assert(path != NULL);
if (!path[0] || size == 0) {
if (!path[0] && size < 0 || size == 0) {

Check warning on line 2386 in Python/fileutils.c

View workflow job for this annotation

GitHub Actions / Ubuntu

suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]

Check warning on line 2386 in Python/fileutils.c

View workflow job for this annotation

GitHub Actions / Ubuntu SSL tests with OpenSSL (1.1.1u)

suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]

Check warning on line 2386 in Python/fileutils.c

View workflow job for this annotation

GitHub Actions / Ubuntu SSL tests with OpenSSL (3.0.9)

suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]

Check warning on line 2386 in Python/fileutils.c

View workflow job for this annotation

GitHub Actions / Ubuntu SSL tests with OpenSSL (3.1.1)

suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]

Check warning on line 2386 in Python/fileutils.c

View workflow job for this annotation

GitHub Actions / Address sanitizer

suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]

Check warning on line 2386 in Python/fileutils.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
*normsize = 0;
return path;
}
wchar_t *pEnd = size >= 0 ? &path[size] : NULL;
Expand Down Expand Up @@ -2431,11 +2433,7 @@
*p2++ = lastC = *p1;
}
}
if (sepCount) {
minP2 = p2; // Invalid path
} else {
minP2 = p2 - 1; // Absolute path has SEP at minP2
}
minP2 = p2 - 1;
}
#else
// Skip past two leading SEPs
Expand Down Expand Up @@ -2495,13 +2493,28 @@
while (--p2 != minP2 && *p2 == SEP) {
*p2 = L'\0';
}
} else {
--p2;
}
*normsize = p2 - path + 1;
#undef SEP_OR_END
#undef IS_SEP
#undef IS_END
return path;
}

/* In-place path normalisation. Returns the start of the normalized
path, which will be within the original buffer. Guaranteed to not
make the path longer, and will not fail. 'size' is the length of
the path, if known. If -1, the first null character will be assumed
to be the end of the path. */
wchar_t *
_Py_normpath(wchar_t *path, Py_ssize_t size)
{
Py_ssize_t norm_length;
return _Py_normpath_and_size(path, size, &norm_length);
}


/* Get the current directory. buflen is the buffer size in wide characters
including the null character. Decode the path from the locale encoding.
Expand Down
Loading