Skip to content

Commit 8bec019

Browse files
authored
Merge branch 'main' into gh-161270/bolt-skipif
2 parents d0fcb2b + 0170881 commit 8bec019

16 files changed

Lines changed: 194 additions & 29 deletions

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
*.pyo
2121
*.rej
2222
*.swp
23+
*.pickle
2324
*~
2425
*.gc??
2526
*.profclang?

‎Doc/library/collections.abc.rst‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,9 @@ of three ways.
109109
Collections Abstract Base Classes
110110
---------------------------------
111111

112-
The collections module offers the following :term:`ABCs <abstract base class>`:
113-
114-
The "Abstract Methods" column lists all required abstract methods,
115-
including those inherited from parent classes.
112+
The collections module offers the following :term:`ABCs <abstract base class>`,
113+
where the "Abstract Methods" column lists all required abstract methods,
114+
including those inherited from parent classes:
116115

117116
.. tabularcolumns:: |l|L|L|L|
118117

‎Doc/library/tarfile.rst‎

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,14 +1120,15 @@ reused in custom filters:
11201120
Implements the ``'tar'`` filter.
11211121

11221122
- Strip leading slashes (``/`` and :data:`os.sep`) from filenames.
1123-
- :ref:`Refuse <tarfile-extraction-refuse>` to extract files with absolute
1124-
paths (in case the name is absolute
1125-
even after stripping slashes, e.g. ``C:/foo`` on Windows).
1126-
This raises :class:`~tarfile.AbsolutePathError`.
11271123
- Normalize filenames (:attr:`TarInfo.name`) that contain ``..`` components
11281124
using :func:`os.path.normpath`.
11291125
Note that this removes internal ``..`` components, which may change the
11301126
meaning of the name if it traverses symbolic links.
1127+
- :ref:`Refuse <tarfile-extraction-refuse>` to extract files with absolute
1128+
paths (in case the name is absolute
1129+
even after stripping slashes, e.g. ``C:/foo`` on Windows)
1130+
or with a drive (e.g. ``C:foo`` on Windows).
1131+
This raises :class:`~tarfile.AbsolutePathError`.
11311132
- :ref:`Refuse <tarfile-extraction-refuse>` to extract files whose absolute
11321133
path (after following symlinks) would end up outside the destination.
11331134
This raises :class:`~tarfile.OutsideDestinationError`.
@@ -1152,6 +1153,10 @@ reused in custom filters:
11521153

11531154
Filenames containing ``..`` components are now normalized.
11541155

1156+
.. versionchanged:: next
1157+
1158+
Filenames with a drive that are not absolute are now refused.
1159+
11551160
.. function:: data_filter(member, path)
11561161

11571162
Implements the ``'data'`` filter.
@@ -1164,7 +1169,8 @@ reused in custom filters:
11641169
symbolic links.
11651170

11661171
- :ref:`Refuse <tarfile-extraction-refuse>` to extract links (hard or soft)
1167-
that link to absolute paths, or ones that link outside the destination.
1172+
that link to absolute paths or to paths with a drive,
1173+
or ones that link outside the destination.
11681174

11691175
This raises :class:`~tarfile.AbsoluteLinkError` or
11701176
:class:`~tarfile.LinkOutsideDestinationError`.
@@ -1198,6 +1204,10 @@ reused in custom filters:
11981204

11991205
Link targets are now normalized.
12001206

1207+
.. versionchanged:: next
1208+
1209+
Link targets with a drive that are not absolute are now refused.
1210+
12011211

12021212
.. _tarfile-extraction-refuse:
12031213

‎Include/pyport.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,11 @@ extern "C" {
550550
# define _Py_TYPEOF(expr) __typeof__(expr)
551551
#endif
552552

553+
#ifdef _Py_TESTCEXT_NO_TYPEOF
554+
// Exercise fallback implementations in test_cext.
555+
# undef _Py_TYPEOF
556+
#endif
557+
553558

554559
/* A convenient way for code to know if sanitizers are enabled. */
555560
#if defined(__has_feature)

‎Include/refcount.h‎

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
489489
_Py_TYPEOF(op) _tmp_old_op = (*_tmp_op_ptr); \
490490
if (_tmp_old_op != _Py_NULL) { \
491491
*_tmp_op_ptr = _Py_NULL; \
492-
Py_DECREF(_tmp_old_op); \
492+
Py_DECREF(_PyObject_CAST(_tmp_old_op)); \
493493
} \
494494
} while (0)
495495
#elif defined(__cplusplus) && (__cplusplus >= 201103L || _MSVC_LANG >= 201103L)
@@ -499,14 +499,15 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
499499
auto _tmp_old_op = (*_tmp_op_ptr); \
500500
if (_tmp_old_op != _Py_NULL) { \
501501
*_tmp_op_ptr = _Py_NULL; \
502-
Py_DECREF(_tmp_old_op); \
502+
Py_DECREF(_PyObject_CAST(_tmp_old_op)); \
503503
} \
504504
} while (0)
505505
#else
506506
#define Py_CLEAR(op) \
507507
do { \
508508
PyObject **_tmp_op_ptr = _Py_CAST(PyObject**, &(op)); \
509-
PyObject *_tmp_old_op = (*_tmp_op_ptr); \
509+
PyObject *_tmp_old_op; \
510+
memcpy(&_tmp_old_op, _tmp_op_ptr, sizeof(PyObject*)); \
510511
if (_tmp_old_op != _Py_NULL) { \
511512
PyObject *_null_ptr = _Py_NULL; \
512513
memcpy(_tmp_op_ptr, &_null_ptr, sizeof(PyObject*)); \
@@ -545,22 +546,23 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
545546
_Py_TYPEOF(&(dst)) _tmp_dst_ptr = &(dst); \
546547
_Py_TYPEOF(dst) _tmp_old_dst = (*_tmp_dst_ptr); \
547548
*_tmp_dst_ptr = (src); \
548-
Py_DECREF(_tmp_old_dst); \
549+
Py_DECREF(_PyObject_CAST(_tmp_old_dst)); \
549550
} while (0)
550551
#elif defined(__cplusplus) && (__cplusplus >= 201103L || _MSVC_LANG >= 201103L)
551552
#define Py_SETREF(dst, src) \
552553
do { \
553554
auto _tmp_dst_ptr = &(dst); \
554555
auto _tmp_old_dst = (*_tmp_dst_ptr); \
555556
*_tmp_dst_ptr = (src); \
556-
Py_DECREF(_tmp_old_dst); \
557+
Py_DECREF(_PyObject_CAST(_tmp_old_dst)); \
557558
} while (0)
558559
#else
559560
#define Py_SETREF(dst, src) \
560561
do { \
561562
PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
562-
PyObject *_tmp_old_dst = (*_tmp_dst_ptr); \
563+
PyObject *_tmp_old_dst; \
563564
PyObject *_tmp_src = _PyObject_CAST(src); \
565+
memcpy(&_tmp_old_dst, _tmp_dst_ptr, sizeof(PyObject*)); \
564566
memcpy(_tmp_dst_ptr, &_tmp_src, sizeof(PyObject*)); \
565567
Py_DECREF(_tmp_old_dst); \
566568
} while (0)
@@ -575,22 +577,23 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
575577
_Py_TYPEOF(&(dst)) _tmp_dst_ptr = &(dst); \
576578
_Py_TYPEOF(dst) _tmp_old_dst = (*_tmp_dst_ptr); \
577579
*_tmp_dst_ptr = (src); \
578-
Py_XDECREF(_tmp_old_dst); \
580+
Py_XDECREF(_PyObject_CAST(_tmp_old_dst)); \
579581
} while (0)
580582
#elif defined(__cplusplus) && (__cplusplus >= 201103L || _MSVC_LANG >= 201103L)
581583
#define Py_XSETREF(dst, src) \
582584
do { \
583585
auto _tmp_dst_ptr = &(dst); \
584586
auto _tmp_old_dst = (*_tmp_dst_ptr); \
585587
*_tmp_dst_ptr = (src); \
586-
Py_XDECREF(_tmp_old_dst); \
588+
Py_XDECREF(_PyObject_CAST(_tmp_old_dst)); \
587589
} while (0)
588590
#else
589591
#define Py_XSETREF(dst, src) \
590592
do { \
591593
PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
592-
PyObject *_tmp_old_dst = (*_tmp_dst_ptr); \
594+
PyObject *_tmp_old_dst; \
593595
PyObject *_tmp_src = _PyObject_CAST(src); \
596+
memcpy(&_tmp_old_dst, _tmp_dst_ptr, sizeof(PyObject*)); \
594597
memcpy(_tmp_dst_ptr, &_tmp_src, sizeof(PyObject*)); \
595598
Py_XDECREF(_tmp_old_dst); \
596599
} while (0)

‎Lib/json/__init__.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True,
134134
135135
If ``check_circular`` is false, then the circular reference check
136136
for container types will be skipped and a circular reference will
137-
result in an ``RecursionError`` (or worse).
137+
result in a ``RecursionError`` (or worse).
138138
139139
If ``allow_nan`` is false, then it will be a ``ValueError`` to
140140
serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
@@ -198,7 +198,7 @@ def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
198198
199199
If ``check_circular`` is false, then the circular reference check
200200
for container types will be skipped and a circular reference will
201-
result in an ``RecursionError`` (or worse).
201+
result in a ``RecursionError`` (or worse).
202202
203203
If ``allow_nan`` is false, then it will be a ``ValueError`` to
204204
serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in

‎Lib/json/encoder.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def __init__(self, *, skipkeys=False, ensure_ascii=True,
118118
119119
If check_circular is true, then lists, dicts, and custom encoded
120120
objects will be checked for circular references during encoding to
121-
prevent an infinite recursion (which would cause an RecursionError).
121+
prevent an infinite recursion (which would cause a RecursionError).
122122
Otherwise, no such check takes place.
123123
124124
If allow_nan is true, then NaN, Infinity, and -Infinity will be
-15 KB
Binary file not shown.
-1.2 KB
Binary file not shown.

‎Lib/tarfile.py‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -839,10 +839,6 @@ def _get_filtered_attrs(member, dest_path, for_data=True):
839839
# Include os.sep (target OS directory separator) as well.
840840
if name.startswith(('/', os.sep)):
841841
name = new_attrs['name'] = member.path.lstrip('/' + os.sep)
842-
if os.path.isabs(name):
843-
# Path is absolute even after stripping.
844-
# For example, 'C:/foo' on Windows.
845-
raise AbsolutePathError(member)
846842
# Ensure we stay in the destination
847843
if '..' in name.replace(os.sep, '/').split('/'):
848844
# Directories are created from the name as given, so a name that
@@ -851,6 +847,11 @@ def _get_filtered_attrs(member, dest_path, for_data=True):
851847
normalized = os.path.normpath(name)
852848
if normalized != name:
853849
name = new_attrs['name'] = normalized
850+
if os.path.isabs(name) or os.path.splitdrive(name)[0]:
851+
# Path is absolute even after stripping, or has a drive.
852+
# For example, 'C:/foo' or 'C:foo' on Windows.
853+
# os.path.join() ignores a destination without a drive for 'C:foo'.
854+
raise AbsolutePathError(member)
854855
target_path = os.path.realpath(os.path.join(dest_path, name),
855856
strict=os.path.ALLOW_MISSING)
856857
if os.path.commonpath([target_path, dest_path]) != dest_path:
@@ -894,11 +895,11 @@ def _get_filtered_attrs(member, dest_path, for_data=True):
894895
new_attrs['gname'] = None
895896
# Check link destination for 'data'
896897
if member.islnk() or member.issym():
897-
if os.path.isabs(member.linkname):
898-
raise AbsoluteLinkError(member)
899898
normalized = os.path.normpath(member.linkname)
900899
if normalized != member.linkname:
901900
new_attrs['linkname'] = normalized
901+
if os.path.isabs(normalized) or os.path.splitdrive(normalized)[0]:
902+
raise AbsoluteLinkError(member)
902903
if member.issym():
903904
# The symlink is created at `name` with trailing separators
904905
# stripped, so its target is relative to the directory

0 commit comments

Comments
 (0)