Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c4ffdc5

Browse filesBrowse files
authored
Merge branch 'main' into streamline-family-syntax
2 parents 945f09d + 4b4a5b7 commit c4ffdc5
Copy full SHA for c4ffdc5

File tree

Expand file treeCollapse file tree

15 files changed

+184
-16
lines changed
Filter options
Expand file treeCollapse file tree

15 files changed

+184
-16
lines changed

‎Lib/asyncio/base_events.py

Copy file name to clipboardExpand all lines: Lib/asyncio/base_events.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ def call_later(self, delay, callback, *args, context=None):
727727
always relative to the current time.
728728
729729
Each callback will be called exactly once. If two callbacks
730-
are scheduled for exactly the same time, it undefined which
730+
are scheduled for exactly the same time, it is undefined which
731731
will be called first.
732732
733733
Any positional arguments after the callback will be passed to

‎Lib/asyncio/events.py

Copy file name to clipboardExpand all lines: Lib/asyncio/events.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ class AbstractEventLoopPolicy:
617617
def get_event_loop(self):
618618
"""Get the event loop for the current context.
619619
620-
Returns an event loop object implementing the BaseEventLoop interface,
620+
Returns an event loop object implementing the AbstractEventLoop interface,
621621
or raises an exception in case no event loop has been set for the
622622
current context and the current policy does not specify to create one.
623623

‎Lib/email/feedparser.py

Copy file name to clipboardExpand all lines: Lib/email/feedparser.py
+9-6Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
headerRE = re.compile(r'^(From |[\041-\071\073-\176]*:|[\t ])')
3838
EMPTYSTRING = ''
3939
NL = '\n'
40+
boundaryendRE = re.compile(
41+
r'(?P<end>--)?(?P<ws>[ \t]*)(?P<linesep>\r\n|\r|\n)?$')
4042

4143
NeedMoreData = object()
4244

@@ -327,9 +329,10 @@ def _parsegen(self):
327329
# this onto the input stream until we've scanned past the
328330
# preamble.
329331
separator = '--' + boundary
330-
boundaryre = re.compile(
331-
'(?P<sep>' + re.escape(separator) +
332-
r')(?P<end>--)?(?P<ws>[ \t]*)(?P<linesep>\r\n|\r|\n)?$')
332+
def boundarymatch(line):
333+
if not line.startswith(separator):
334+
return None
335+
return boundaryendRE.match(line, len(separator))
333336
capturing_preamble = True
334337
preamble = []
335338
linesep = False
@@ -341,7 +344,7 @@ def _parsegen(self):
341344
continue
342345
if line == '':
343346
break
344-
mo = boundaryre.match(line)
347+
mo = boundarymatch(line)
345348
if mo:
346349
# If we're looking at the end boundary, we're done with
347350
# this multipart. If there was a newline at the end of
@@ -373,13 +376,13 @@ def _parsegen(self):
373376
if line is NeedMoreData:
374377
yield NeedMoreData
375378
continue
376-
mo = boundaryre.match(line)
379+
mo = boundarymatch(line)
377380
if not mo:
378381
self._input.unreadline(line)
379382
break
380383
# Recurse to parse this subpart; the input stream points
381384
# at the subpart's first line.
382-
self._input.push_eof_matcher(boundaryre.match)
385+
self._input.push_eof_matcher(boundarymatch)
383386
for retval in self._parsegen():
384387
if retval is NeedMoreData:
385388
yield NeedMoreData

‎Lib/test/test_mmap.py

Copy file name to clipboardExpand all lines: Lib/test/test_mmap.py
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,27 @@ def test_find_end(self):
299299
self.assertEqual(m.find(b'one', 1, -2), -1)
300300
self.assertEqual(m.find(bytearray(b'one')), 0)
301301

302+
for i in range(-n-1, n+1):
303+
for j in range(-n-1, n+1):
304+
for p in [b"o", b"on", b"two", b"ones", b"s"]:
305+
expected = data.find(p, i, j)
306+
self.assertEqual(m.find(p, i, j), expected, (p, i, j))
307+
308+
def test_find_does_not_access_beyond_buffer(self):
309+
try:
310+
flags = mmap.MAP_PRIVATE | mmap.MAP_ANONYMOUS
311+
PAGESIZE = mmap.PAGESIZE
312+
PROT_NONE = 0
313+
PROT_READ = mmap.PROT_READ
314+
except AttributeError as e:
315+
raise unittest.SkipTest("mmap flags unavailable") from e
316+
for i in range(0, 2049):
317+
with mmap.mmap(-1, PAGESIZE * (i + 1),
318+
flags=flags, prot=PROT_NONE) as guard:
319+
with mmap.mmap(-1, PAGESIZE * (i + 2048),
320+
flags=flags, prot=PROT_READ) as fm:
321+
fm.find(b"fo", -2)
322+
302323

303324
def test_rfind(self):
304325
# test the new 'end' parameter works as expected

‎Lib/venv/scripts/common/Activate.ps1

Copy file name to clipboardExpand all lines: Lib/venv/scripts/common/Activate.ps1
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ deactivate -nondestructive
219219
# that there is an activated venv.
220220
$env:VIRTUAL_ENV = $VenvDir
221221

222+
$env:VIRTUAL_ENV_PROMPT = $Prompt
223+
222224
if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
223225

224226
Write-Verbose "Setting prompt to '$Prompt'"
@@ -233,7 +235,6 @@ if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
233235
Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
234236
_OLD_VIRTUAL_PROMPT
235237
}
236-
$env:VIRTUAL_ENV_PROMPT = $Prompt
237238
}
238239

239240
# Clear PYTHONHOME

‎Lib/venv/scripts/common/activate

Copy file name to clipboardExpand all lines: Lib/venv/scripts/common/activate
+3-2Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ _OLD_VIRTUAL_PATH="$PATH"
5252
PATH="$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
5353
export PATH
5454

55+
VIRTUAL_ENV_PROMPT="__VENV_PROMPT__"
56+
export VIRTUAL_ENV_PROMPT
57+
5558
# unset PYTHONHOME if set
5659
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
5760
# could use `if (set -u; : $PYTHONHOME) ;` in bash
@@ -64,8 +67,6 @@ if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
6467
_OLD_VIRTUAL_PS1="${PS1:-}"
6568
PS1="__VENV_PROMPT__${PS1:-}"
6669
export PS1
67-
VIRTUAL_ENV_PROMPT="__VENV_PROMPT__"
68-
export VIRTUAL_ENV_PROMPT
6970
fi
7071

7172
# This should detect bash and zsh, which have a hash command that must

‎Lib/venv/scripts/posix/activate.csh

Copy file name to clipboardExpand all lines: Lib/venv/scripts/posix/activate.csh
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ setenv VIRTUAL_ENV "__VENV_DIR__"
1313

1414
set _OLD_VIRTUAL_PATH="$PATH"
1515
setenv PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
16+
setenv VIRTUAL_ENV_PROMPT "__VENV_PROMPT__"
1617

1718

1819
set _OLD_VIRTUAL_PROMPT="$prompt"
1920

2021
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
2122
set prompt = "__VENV_PROMPT__$prompt"
22-
setenv VIRTUAL_ENV_PROMPT "__VENV_PROMPT__"
2323
endif
2424

2525
alias pydoc python -m pydoc

‎Lib/venv/scripts/posix/activate.fish

Copy file name to clipboardExpand all lines: Lib/venv/scripts/posix/activate.fish
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ set -gx VIRTUAL_ENV "__VENV_DIR__"
3737

3838
set -gx _OLD_VIRTUAL_PATH $PATH
3939
set -gx PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__" $PATH
40+
set -gx VIRTUAL_ENV_PROMPT "__VENV_PROMPT__"
4041

4142
# Unset PYTHONHOME if set.
4243
if set -q PYTHONHOME
@@ -65,5 +66,4 @@ if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
6566
end
6667

6768
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
68-
set -gx VIRTUAL_ENV_PROMPT "__VENV_PROMPT__"
6969
end

‎Misc/ACKS

Copy file name to clipboardExpand all lines: Misc/ACKS
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ Erik Bray
226226
Brian Brazil
227227
Demian Brecht
228228
Dave Brennan
229+
Christopher Richard James Brett
229230
Tom Bridgman
230231
Anthony Briggs
231232
Keith Briggs
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Prevent out-of-bounds memory access during ``mmap.find()`` calls.
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Set the environment variable ``VIRTUAL_ENV_PROMPT`` at :mod:`venv`
2+
activation, even when ``VIRTUAL_ENV_DISABLE_PROMPT`` is set.
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Speed up parsing of emails by about 20% by not compiling a new regular
2+
expression for every single email.

‎Modules/_testinternalcapi.c

Copy file name to clipboardExpand all lines: Modules/_testinternalcapi.c
+114Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "interpreteridobject.h" // _PyInterpreterID_LookUp()
1515
#include "pycore_atomic_funcs.h" // _Py_atomic_int_get()
1616
#include "pycore_bitutils.h" // _Py_bswap32()
17+
#include "pycore_bytesobject.h" // _PyBytes_Find()
1718
#include "pycore_compile.h" // _PyCompile_CodeGen, _PyCompile_OptimizeCfg, _PyCompile_Assemble
1819
#include "pycore_ceval.h" // _PyEval_AddPendingCall
1920
#include "pycore_fileutils.h" // _Py_normpath
@@ -443,6 +444,118 @@ test_edit_cost(PyObject *self, PyObject *Py_UNUSED(args))
443444
}
444445

445446

447+
static int
448+
check_bytes_find(const char *haystack0, const char *needle0,
449+
int offset, Py_ssize_t expected)
450+
{
451+
Py_ssize_t len_haystack = strlen(haystack0);
452+
Py_ssize_t len_needle = strlen(needle0);
453+
Py_ssize_t result_1 = _PyBytes_Find(haystack0, len_haystack,
454+
needle0, len_needle, offset);
455+
if (result_1 != expected) {
456+
PyErr_Format(PyExc_AssertionError,
457+
"Incorrect result_1: '%s' in '%s' (offset=%zd)",
458+
needle0, haystack0, offset);
459+
return -1;
460+
}
461+
// Allocate new buffer with no NULL terminator.
462+
char *haystack = PyMem_Malloc(len_haystack);
463+
if (haystack == NULL) {
464+
PyErr_NoMemory();
465+
return -1;
466+
}
467+
char *needle = PyMem_Malloc(len_needle);
468+
if (needle == NULL) {
469+
PyMem_Free(haystack);
470+
PyErr_NoMemory();
471+
return -1;
472+
}
473+
memcpy(haystack, haystack0, len_haystack);
474+
memcpy(needle, needle0, len_needle);
475+
Py_ssize_t result_2 = _PyBytes_Find(haystack, len_haystack,
476+
needle, len_needle, offset);
477+
PyMem_Free(haystack);
478+
PyMem_Free(needle);
479+
if (result_2 != expected) {
480+
PyErr_Format(PyExc_AssertionError,
481+
"Incorrect result_2: '%s' in '%s' (offset=%zd)",
482+
needle0, haystack0, offset);
483+
return -1;
484+
}
485+
return 0;
486+
}
487+
488+
static int
489+
check_bytes_find_large(Py_ssize_t len_haystack, Py_ssize_t len_needle,
490+
const char *needle)
491+
{
492+
char *zeros = PyMem_RawCalloc(len_haystack, 1);
493+
if (zeros == NULL) {
494+
PyErr_NoMemory();
495+
return -1;
496+
}
497+
Py_ssize_t res = _PyBytes_Find(zeros, len_haystack, needle, len_needle, 0);
498+
PyMem_RawFree(zeros);
499+
if (res != -1) {
500+
PyErr_Format(PyExc_AssertionError,
501+
"check_bytes_find_large(%zd, %zd) found %zd",
502+
len_haystack, len_needle, res);
503+
return -1;
504+
}
505+
return 0;
506+
}
507+
508+
static PyObject *
509+
test_bytes_find(PyObject *self, PyObject *Py_UNUSED(args))
510+
{
511+
#define CHECK(H, N, O, E) do { \
512+
if (check_bytes_find(H, N, O, E) < 0) { \
513+
return NULL; \
514+
} \
515+
} while (0)
516+
517+
CHECK("", "", 0, 0);
518+
CHECK("Python", "", 0, 0);
519+
CHECK("Python", "", 3, 3);
520+
CHECK("Python", "", 6, 6);
521+
CHECK("Python", "yth", 0, 1);
522+
CHECK("ython", "yth", 1, 1);
523+
CHECK("thon", "yth", 2, -1);
524+
CHECK("Python", "thon", 0, 2);
525+
CHECK("ython", "thon", 1, 2);
526+
CHECK("thon", "thon", 2, 2);
527+
CHECK("hon", "thon", 3, -1);
528+
CHECK("Pytho", "zz", 0, -1);
529+
CHECK("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "ab", 0, -1);
530+
CHECK("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "ba", 0, -1);
531+
CHECK("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bb", 0, -1);
532+
CHECK("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", "ab", 0, 30);
533+
CHECK("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaba", "ba", 0, 30);
534+
CHECK("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaabb", "bb", 0, 30);
535+
#undef CHECK
536+
537+
// Hunt for segfaults
538+
// n, m chosen here so that (n - m) % (m + 1) == 0
539+
// This would make default_find in fastsearch.h access haystack[n].
540+
if (check_bytes_find_large(2048, 2, "ab") < 0) {
541+
return NULL;
542+
}
543+
if (check_bytes_find_large(4096, 16, "0123456789abcdef") < 0) {
544+
return NULL;
545+
}
546+
if (check_bytes_find_large(8192, 2, "ab") < 0) {
547+
return NULL;
548+
}
549+
if (check_bytes_find_large(16384, 4, "abcd") < 0) {
550+
return NULL;
551+
}
552+
if (check_bytes_find_large(32768, 2, "ab") < 0) {
553+
return NULL;
554+
}
555+
Py_RETURN_NONE;
556+
}
557+
558+
446559
static PyObject *
447560
normalize_path(PyObject *self, PyObject *filename)
448561
{
@@ -1328,6 +1441,7 @@ static PyMethodDef module_functions[] = {
13281441
{"reset_path_config", test_reset_path_config, METH_NOARGS},
13291442
{"test_atomic_funcs", test_atomic_funcs, METH_NOARGS},
13301443
{"test_edit_cost", test_edit_cost, METH_NOARGS},
1444+
{"test_bytes_find", test_bytes_find, METH_NOARGS},
13311445
{"normalize_path", normalize_path, METH_O, NULL},
13321446
{"get_getpath_codeobject", get_getpath_codeobject, METH_NOARGS, NULL},
13331447
{"EncodeLocaleEx", encode_locale_ex, METH_VARARGS},

‎Modules/mmapmodule.c

Copy file name to clipboardExpand all lines: Modules/mmapmodule.c
+6-1Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,12 +342,17 @@ mmap_gfind(mmap_object *self,
342342

343343
Py_ssize_t res;
344344
CHECK_VALID_OR_RELEASE(NULL, view);
345-
if (reverse) {
345+
if (end < start) {
346+
res = -1;
347+
}
348+
else if (reverse) {
349+
assert(0 <= start && start <= end && end <= self->size);
346350
res = _PyBytes_ReverseFind(
347351
self->data + start, end - start,
348352
view.buf, view.len, start);
349353
}
350354
else {
355+
assert(0 <= start && start <= end && end <= self->size);
351356
res = _PyBytes_Find(
352357
self->data + start, end - start,
353358
view.buf, view.len, start);

‎Objects/bytesobject.c

Copy file name to clipboardExpand all lines: Objects/bytesobject.c
+19-2Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,8 +1272,25 @@ _PyBytes_Find(const char *haystack, Py_ssize_t len_haystack,
12721272
const char *needle, Py_ssize_t len_needle,
12731273
Py_ssize_t offset)
12741274
{
1275-
return stringlib_find(haystack, len_haystack,
1276-
needle, len_needle, offset);
1275+
assert(len_haystack >= 0);
1276+
assert(len_needle >= 0);
1277+
// Extra checks because stringlib_find accesses haystack[len_haystack].
1278+
if (len_needle == 0) {
1279+
return offset;
1280+
}
1281+
if (len_needle > len_haystack) {
1282+
return -1;
1283+
}
1284+
assert(len_haystack >= 1);
1285+
Py_ssize_t res = stringlib_find(haystack, len_haystack - 1,
1286+
needle, len_needle, offset);
1287+
if (res == -1) {
1288+
Py_ssize_t last_align = len_haystack - len_needle;
1289+
if (memcmp(haystack + last_align, needle, len_needle) == 0) {
1290+
return offset + last_align;
1291+
}
1292+
}
1293+
return res;
12771294
}
12781295

12791296
Py_ssize_t

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.