@@ -4610,23 +4610,19 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
4610
4610
int is_generator = code_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR );
4611
4611
if (!is_generator ) {
4612
4612
PyObject * locals = code_flags & CO_OPTIMIZED ? NULL : PyFunction_GET_GLOBALS (function );
4613
+ STACK_SHRINK (oparg );
4613
4614
InterpreterFrame * new_frame = _PyEvalFramePushAndInit (
4614
4615
tstate , PyFunction_AS_FRAME_CONSTRUCTOR (function ), locals ,
4615
- stack_pointer - oparg ,
4616
+ stack_pointer ,
4616
4617
nargs , kwnames , 1 );
4617
- if (new_frame == NULL ) {
4618
- // When we exit here, we own all variables in the stack
4619
- // (the frame creation has not stolen any variable) so
4620
- // we need to clean the whole stack (done in the
4621
- // "error" label).
4622
- goto error ;
4623
- }
4624
-
4625
- STACK_SHRINK (oparg + stackadj );
4618
+ STACK_SHRINK (stackadj );
4626
4619
// The frame has stolen all the arguments from the stack,
4627
4620
// so there is no need to clean them up.
4628
4621
Py_XDECREF (kwnames );
4629
4622
Py_DECREF (function );
4623
+ if (new_frame == NULL ) {
4624
+ goto error ;
4625
+ }
4630
4626
_PyFrame_SetStackPointer (frame , stack_pointer );
4631
4627
new_frame -> depth = frame -> depth + 1 ;
4632
4628
tstate -> frame = frame = new_frame ;
@@ -5397,7 +5393,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5397
5393
if (co -> co_flags & CO_VARKEYWORDS ) {
5398
5394
kwdict = PyDict_New ();
5399
5395
if (kwdict == NULL ) {
5400
- goto fail ;
5396
+ goto fail_early ;
5401
5397
}
5402
5398
i = total_args ;
5403
5399
if (co -> co_flags & CO_VARARGS ) {
@@ -5436,11 +5432,19 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5436
5432
u = _PyTuple_FromArray (args + n , argcount - n );
5437
5433
}
5438
5434
if (u == NULL ) {
5439
- goto fail ;
5435
+ goto fail_post_positional ;
5440
5436
}
5441
5437
assert (localsplus [total_args ] == NULL );
5442
5438
localsplus [total_args ] = u ;
5443
5439
}
5440
+ else if (argcount > n ) {
5441
+ /* Too many postional args. Error is reported later */
5442
+ if (steal_args ) {
5443
+ for (j = n ; j < argcount ; j ++ ) {
5444
+ Py_DECREF (args [j ]);
5445
+ }
5446
+ }
5447
+ }
5444
5448
5445
5449
/* Handle keyword arguments */
5446
5450
if (kwnames != NULL ) {
@@ -5455,7 +5459,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5455
5459
_PyErr_Format (tstate , PyExc_TypeError ,
5456
5460
"%U() keywords must be strings" ,
5457
5461
con -> fc_qualname );
5458
- goto fail ;
5462
+ goto kw_fail ;
5459
5463
}
5460
5464
5461
5465
/* Speed hack: do raw pointer compares. As names are
@@ -5476,7 +5480,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5476
5480
goto kw_found ;
5477
5481
}
5478
5482
else if (cmp < 0 ) {
5479
- goto fail ;
5483
+ goto kw_fail ;
5480
5484
}
5481
5485
}
5482
5486
@@ -5488,29 +5492,38 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5488
5492
kwcount , kwnames ,
5489
5493
con -> fc_qualname ))
5490
5494
{
5491
- goto fail ;
5495
+ goto kw_fail ;
5492
5496
}
5493
5497
5494
5498
_PyErr_Format (tstate , PyExc_TypeError ,
5495
5499
"%U() got an unexpected keyword argument '%S'" ,
5496
5500
con -> fc_qualname , keyword );
5497
- goto fail ;
5501
+ goto kw_fail ;
5498
5502
}
5499
5503
5500
5504
if (PyDict_SetItem (kwdict , keyword , value ) == -1 ) {
5501
- goto fail ;
5505
+ goto kw_fail ;
5502
5506
}
5503
5507
if (steal_args ) {
5504
5508
Py_DECREF (value );
5505
5509
}
5506
5510
continue ;
5507
5511
5512
+ kw_fail :
5513
+ if (steal_args ) {
5514
+ for (;i < kwcount ; i ++ ) {
5515
+ PyObject * value = args [i + argcount ];
5516
+ Py_DECREF (value );
5517
+ }
5518
+ }
5519
+ goto fail_late ;
5520
+
5508
5521
kw_found :
5509
5522
if (localsplus [j ] != NULL ) {
5510
5523
_PyErr_Format (tstate , PyExc_TypeError ,
5511
5524
"%U() got multiple values for argument '%S'" ,
5512
5525
con -> fc_qualname , keyword );
5513
- goto fail ;
5526
+ goto kw_fail ;
5514
5527
}
5515
5528
if (!steal_args ) {
5516
5529
Py_INCREF (value );
@@ -5523,7 +5536,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5523
5536
if ((argcount > co -> co_argcount ) && !(co -> co_flags & CO_VARARGS )) {
5524
5537
too_many_positional (tstate , co , argcount , con -> fc_defaults , localsplus ,
5525
5538
con -> fc_qualname );
5526
- goto fail ;
5539
+ goto fail_late ;
5527
5540
}
5528
5541
5529
5542
/* Add missing positional arguments (copy default values from defs) */
@@ -5539,7 +5552,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5539
5552
if (missing ) {
5540
5553
missing_arguments (tstate , co , missing , defcount , localsplus ,
5541
5554
con -> fc_qualname );
5542
- goto fail ;
5555
+ goto fail_late ;
5543
5556
}
5544
5557
if (n > m )
5545
5558
i = n - m ;
@@ -5572,15 +5585,15 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5572
5585
continue ;
5573
5586
}
5574
5587
else if (_PyErr_Occurred (tstate )) {
5575
- goto fail ;
5588
+ goto fail_late ;
5576
5589
}
5577
5590
}
5578
5591
missing ++ ;
5579
5592
}
5580
5593
if (missing ) {
5581
5594
missing_arguments (tstate , co , missing , -1 , localsplus ,
5582
5595
con -> fc_qualname );
5583
- goto fail ;
5596
+ goto fail_late ;
5584
5597
}
5585
5598
}
5586
5599
@@ -5593,33 +5606,23 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5593
5606
5594
5607
return 0 ;
5595
5608
5596
- fail : /* Jump here from prelude on failure */
5609
+ fail_early :
5597
5610
if (steal_args ) {
5598
- // If we failed to initialize locals, make sure the caller still own all the
5599
- // arguments that were on the stack. We need to increment the reference count
5600
- // of everything we copied (everything in localsplus) that came from the stack
5601
- // (everything that is present in the "args" array).
5602
- Py_ssize_t kwcount = kwnames != NULL ? PyTuple_GET_SIZE (kwnames ) : 0 ;
5603
- for (Py_ssize_t k = 0 ; k < total_args ; k ++ ) {
5604
- PyObject * arg = localsplus [k ];
5605
- for (Py_ssize_t j = 0 ; j < argcount + kwcount ; j ++ ) {
5606
- if (args [j ] == arg ) {
5607
- Py_XINCREF (arg );
5608
- break ;
5609
- }
5610
- }
5611
+ for (j = 0 ; j < argcount ; j ++ ) {
5612
+ Py_DECREF (args [j ]);
5611
5613
}
5612
- // Restore all the **kwargs we placed into the kwargs dictionary
5613
- if ( kwdict ) {
5614
- PyObject * key , * value ;
5615
- Py_ssize_t pos = 0 ;
5616
- while ( PyDict_Next ( kwdict , & pos , & key , & value )) {
5617
- Py_INCREF ( value );
5618
- }
5614
+ }
5615
+ /* fall through */
5616
+ fail_post_positional :
5617
+ if ( steal_args ) {
5618
+ Py_ssize_t kwcount = kwnames != NULL ? PyTuple_GET_SIZE ( kwnames ) : 0 ;
5619
+ for ( j = argcount ; j < argcount + kwcount ; j ++ ) {
5620
+ Py_DECREF ( args [ j ]);
5619
5621
}
5620
5622
}
5623
+ /* fall through */
5624
+ fail_late :
5621
5625
return -1 ;
5622
-
5623
5626
}
5624
5627
5625
5628
static InterpreterFrame *
0 commit comments