Skip to content

Commit fbea687

Browse files
committed
handle error propagation correctly
1 parent 56dd431 commit fbea687

File tree

2 files changed

+49
-20
lines changed

2 files changed

+49
-20
lines changed

Lib/test/test_struct.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,23 @@ def test_error_msg(prefix, int_type, is_unsigned):
756756
int_type = 'n'
757757
test_error_msg("@", int_type, False)
758758

759+
def test_issue92848_error_propagation(self):
760+
class Div0:
761+
def __index__(self):
762+
1 / 0
763+
764+
def test_error_propagation(fmt_str):
765+
with self.subTest(format_str=fmt_str, exception="ZeroDivisionError"):
766+
with self.assertRaises(ZeroDivisionError):
767+
struct.pack(fmt_str, Div0())
768+
769+
for prefix in '@=<>':
770+
for int_type in 'BHILQbhilq':
771+
test_error_propagation(prefix + int_type)
772+
773+
test_error_propagation('N')
774+
test_error_propagation('n')
775+
759776
class UnpackIteratorTest(unittest.TestCase):
760777
"""
761778
Tests for iterative unpacking (struct.Struct.iter_unpack).

Modules/_struct.c

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -527,12 +527,15 @@ static int
527527
np_byte(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
528528
{
529529
long x;
530-
if (get_long(state, v, &x) < 0 || x < -128 || x > 127) {
531-
if (!PyErr_ExceptionMatches(state->StructError)) {
530+
if (get_long(state, v, &x) < 0) {
531+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
532532
RANGE_ERROR(state, f, 0);
533533
}
534534
return -1;
535535
}
536+
if (x < -128 || x > 127) {
537+
RANGE_ERROR(state, f, 0);
538+
}
536539
*p = (char)x;
537540
return 0;
538541
}
@@ -541,12 +544,15 @@ static int
541544
np_ubyte(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
542545
{
543546
long x;
544-
if (get_long(state, v, &x) < 0 || x < 0 || x > 255) {
545-
if (!PyErr_ExceptionMatches(state->StructError)) {
547+
if (get_long(state, v, &x) < 0) {
548+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
546549
RANGE_ERROR(state, f, 1);
547550
}
548551
return -1;
549552
}
553+
if (x < 0 || x > 255) {
554+
RANGE_ERROR(state, f, 1);
555+
}
550556
*(unsigned char *)p = (unsigned char)x;
551557
return 0;
552558
}
@@ -568,12 +574,15 @@ np_short(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
568574
{
569575
long x;
570576
short y;
571-
if (get_long(state, v, &x) < 0 || x < SHRT_MIN || x > SHRT_MAX) {
572-
if (!PyErr_ExceptionMatches(state->StructError)) {
577+
if (get_long(state, v, &x) < 0) {
578+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
573579
RANGE_ERROR(state, f, 0);
574580
}
575581
return -1;
576582
}
583+
if (x < SHRT_MIN || x > SHRT_MAX) {
584+
RANGE_ERROR(state, f, 0);
585+
}
577586
y = (short)x;
578587
memcpy(p, (char *)&y, sizeof y);
579588
return 0;
@@ -584,12 +593,15 @@ np_ushort(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
584593
{
585594
long x;
586595
unsigned short y;
587-
if (get_long(state, v, &x) < 0 || x < 0 || x > USHRT_MAX) {
588-
if (!PyErr_ExceptionMatches(state->StructError)) {
596+
if (get_long(state, v, &x) < 0) {
597+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
589598
RANGE_ERROR(state, f, 1);
590599
}
591600
return -1;
592601
}
602+
if (x < 0 || x > USHRT_MAX) {
603+
RANGE_ERROR(state, f, 1);
604+
}
593605
y = (unsigned short)x;
594606
memcpy(p, (char *)&y, sizeof y);
595607
return 0;
@@ -601,7 +613,7 @@ np_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
601613
long x;
602614
int y;
603615
if (get_long(state, v, &x) < 0) {
604-
if (!PyErr_ExceptionMatches(state->StructError)) {
616+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
605617
RANGE_ERROR(state, f, 0);
606618
}
607619
return -1;
@@ -621,7 +633,7 @@ np_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
621633
unsigned long x;
622634
unsigned int y;
623635
if (get_ulong(state, v, &x) < 0) {
624-
if (!PyErr_ExceptionMatches(state->StructError)) {
636+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
625637
RANGE_ERROR(state, f, 1);
626638
}
627639
return -1;
@@ -640,7 +652,7 @@ np_long(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
640652
{
641653
long x;
642654
if (get_long(state, v, &x) < 0) {
643-
if (!PyErr_ExceptionMatches(state->StructError)) {
655+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
644656
RANGE_ERROR(state, f, 0);
645657
}
646658
return -1;
@@ -654,7 +666,7 @@ np_ulong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
654666
{
655667
unsigned long x;
656668
if (get_ulong(state, v, &x) < 0) {
657-
if (!PyErr_ExceptionMatches(state->StructError)) {
669+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
658670
RANGE_ERROR(state, f, 1);
659671
}
660672
return -1;
@@ -668,7 +680,7 @@ np_ssize_t(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
668680
{
669681
Py_ssize_t x;
670682
if (get_ssize_t(state, v, &x) < 0) {
671-
if (!PyErr_ExceptionMatches(state->StructError)) {
683+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
672684
RANGE_ERROR(state, f, 0);
673685
}
674686
return -1;
@@ -682,7 +694,7 @@ np_size_t(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
682694
{
683695
size_t x;
684696
if (get_size_t(state, v, &x) < 0) {
685-
if (!PyErr_ExceptionMatches(state->StructError)) {
697+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
686698
RANGE_ERROR(state, f, 1);
687699
}
688700
return -1;
@@ -696,7 +708,7 @@ np_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
696708
{
697709
long long x;
698710
if (get_longlong(state, v, &x) < 0) {
699-
if (!PyErr_ExceptionMatches(state->StructError)) {
711+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
700712
PyErr_Format(state->StructError,
701713
"'%c' format requires %lld <= number <= %lld",
702714
f->format,
@@ -714,7 +726,7 @@ np_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f
714726
{
715727
unsigned long long x;
716728
if (get_ulonglong(state, v, &x) < 0) {
717-
if (!PyErr_ExceptionMatches(state->StructError)) {
729+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
718730
PyErr_Format(state->StructError,
719731
"'%c' format requires 0 <= number <= %llu",
720732
f->format,
@@ -927,7 +939,7 @@ bp_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
927939
Py_ssize_t i;
928940
unsigned char *q = (unsigned char *)p;
929941
if (get_long(state, v, &x) < 0) {
930-
if (!PyErr_ExceptionMatches(state->StructError)) {
942+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
931943
RANGE_ERROR(state, f, 0);
932944
}
933945
return -1;
@@ -955,7 +967,7 @@ bp_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
955967
Py_ssize_t i;
956968
unsigned char *q = (unsigned char *)p;
957969
if (get_ulong(state, v, &x) < 0) {
958-
if (!PyErr_ExceptionMatches(state->StructError)) {
970+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
959971
RANGE_ERROR(state, f, 1);
960972
}
961973
return -1;
@@ -1187,7 +1199,7 @@ lp_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
11871199
Py_ssize_t i;
11881200
unsigned char *q = (unsigned char *)p;
11891201
if (get_long(state, v, &x) < 0) {
1190-
if (!PyErr_ExceptionMatches(state->StructError)) {
1202+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
11911203
RANGE_ERROR(state, f, 0);
11921204
}
11931205
return -1;
@@ -1215,7 +1227,7 @@ lp_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
12151227
Py_ssize_t i;
12161228
unsigned char *q = (unsigned char *)p;
12171229
if (get_ulong(state, v, &x) < 0) {
1218-
if (!PyErr_ExceptionMatches(state->StructError)) {
1230+
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
12191231
RANGE_ERROR(state, f, 1);
12201232
}
12211233
return -1;

0 commit comments

Comments
 (0)