Assorted UBSAN cleanups (#55112) · pandas-dev/pandas@f00efd0 (original) (raw)

1

``

`-

cimport cython

`

2

1

`from cpython.datetime cimport (

`

3

2

` PyDateTime_CheckExact,

`

4

3

` PyDateTime_DATE_GET_HOUR,

`

`@@ -18,6 +17,7 @@ from cpython.object cimport (

`

18

17

` Py_LT,

`

19

18

` Py_NE,

`

20

19

`)

`

``

20

`+

from libc.stdint cimport INT64_MAX

`

21

21

``

22

22

`import_datetime()

`

23

23

`PandasDateTime_IMPORT

`

`@@ -545,14 +545,14 @@ cdef ndarray astype_round_check(

`

545

545

`return iresult

`

546

546

``

547

547

``

548

``

`-

@cython.overflowcheck(True)

`

549

548

`cdef int64_t get_conversion_factor(

`

550

549

` NPY_DATETIMEUNIT from_unit,

`

551

550

` NPY_DATETIMEUNIT to_unit

`

552

551

`) except? -1:

`

553

552

`"""

`

554

553

` Find the factor by which we need to multiply to convert from from_unit to to_unit.

`

555

554

`"""

`

``

555

`+

cdef int64_t value, overflow_limit, factor

`

556

556

`if (

`

557

557

` from_unit == NPY_DATETIMEUNIT.NPY_FR_GENERIC

`

558

558

`or to_unit == NPY_DATETIMEUNIT.NPY_FR_GENERIC

`

`@@ -565,28 +565,44 @@ cdef int64_t get_conversion_factor(

`

565

565

`return 1

`

566

566

``

567

567

`if from_unit == NPY_DATETIMEUNIT.NPY_FR_W:

`

568

``

`-

return 7 * get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_D, to_unit)

`

``

568

`+

value = get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_D, to_unit)

`

``

569

`+

factor = 7

`

569

570

`elif from_unit == NPY_DATETIMEUNIT.NPY_FR_D:

`

570

``

`-

return 24 * get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_h, to_unit)

`

``

571

`+

value = get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_h, to_unit)

`

``

572

`+

factor = 24

`

571

573

`elif from_unit == NPY_DATETIMEUNIT.NPY_FR_h:

`

572

``

`-

return 60 * get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_m, to_unit)

`

``

574

`+

value = get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_m, to_unit)

`

``

575

`+

factor = 60

`

573

576

`elif from_unit == NPY_DATETIMEUNIT.NPY_FR_m:

`

574

``

`-

return 60 * get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_s, to_unit)

`

``

577

`+

value = get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_s, to_unit)

`

``

578

`+

factor = 60

`

575

579

`elif from_unit == NPY_DATETIMEUNIT.NPY_FR_s:

`

576

``

`-

return 1000 * get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_ms, to_unit)

`

``

580

`+

value = get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_ms, to_unit)

`

``

581

`+

factor = 1000

`

577

582

`elif from_unit == NPY_DATETIMEUNIT.NPY_FR_ms:

`

578

``

`-

return 1000 * get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_us, to_unit)

`

``

583

`+

value = get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_us, to_unit)

`

``

584

`+

factor = 1000

`

579

585

`elif from_unit == NPY_DATETIMEUNIT.NPY_FR_us:

`

580

``

`-

return 1000 * get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_ns, to_unit)

`

``

586

`+

value = get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_ns, to_unit)

`

``

587

`+

factor = 1000

`

581

588

`elif from_unit == NPY_DATETIMEUNIT.NPY_FR_ns:

`

582

``

`-

return 1000 * get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_ps, to_unit)

`

``

589

`+

value = get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_ps, to_unit)

`

``

590

`+

factor = 1000

`

583

591

`elif from_unit == NPY_DATETIMEUNIT.NPY_FR_ps:

`

584

``

`-

return 1000 * get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_fs, to_unit)

`

``

592

`+

value = get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_fs, to_unit)

`

``

593

`+

factor = 1000

`

585

594

`elif from_unit == NPY_DATETIMEUNIT.NPY_FR_fs:

`

586

``

`-

return 1000 * get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_as, to_unit)

`

``

595

`+

value = get_conversion_factor(NPY_DATETIMEUNIT.NPY_FR_as, to_unit)

`

``

596

`+

factor = 1000

`

587

597

`else:

`

588

598

`raise ValueError("Converting from M or Y units is not supported.")

`

589

599

``

``

600

`+

overflow_limit = INT64_MAX // factor

`

``

601

`+

if value > overflow_limit or value < -overflow_limit:

`

``

602

`+

raise OverflowError("result would overflow")

`

``

603

+

``

604

`+

return factor * value

`

``

605

+

590

606

``

591

607

`cdef int64_t convert_reso(

`

592

608

` int64_t value,

`

`@@ -595,7 +611,7 @@ cdef int64_t convert_reso(

`

595

611

` bint round_ok,

`

596

612

`) except? -1:

`

597

613

` cdef:

`

598

``

`-

int64_t res_value, mult, div, mod

`

``

614

`+

int64_t res_value, mult, div, mod, overflow_limit

`

599

615

``

600

616

`if from_reso == to_reso:

`

601

617

`return value

`

`@@ -624,9 +640,12 @@ cdef int64_t convert_reso(

`

624

640

`else:

`

625

641

`# e.g. ns -> us, risk of overflow, but no risk of lossy rounding

`

626

642

` mult = get_conversion_factor(from_reso, to_reso)

`

627

``

`-

with cython.overflowcheck(True):

`

``

643

`+

overflow_limit = INT64_MAX // mult

`

``

644

`+

if value > overflow_limit or value < -overflow_limit:

`

628

645

`# Note: caller is responsible for re-raising as OutOfBoundsTimedelta

`

629

``

`-

res_value = value * mult

`

``

646

`+

raise OverflowError("result would overflow")

`

``

647

+

``

648

`+

res_value = value * mult

`

630

649

``

631

650

`return res_value

`

632

651

``