@@ -3413,6 +3413,192 @@ S_lossless_NV_to_IV(const NV nv, IV *ivp)
34133413 return FALSE;
34143414}
34153415
3416+ /*
3417+ * S_iv_{add,sub,mul}_may_overflow(a, b, p) virtually compute "a <op> b"
3418+ * (where <op> is +, -, or *) in infinite precision, and, if the result
3419+ * is (or may be) not representable with IV, return true.
3420+ * Otherwise (no overflow), store the result to *p and return false.
3421+ * These functions allow false positives (so their names contain "may")
3422+ * to speed up simple common cases.
3423+ */
3424+
3425+ /* Define IV_*_OVERFLOW_IS_EXPENSIVE below to nonzero value
3426+ * if strict overflow checks are too expensive
3427+ * (for example, for CPUs that have no hardware overflow detection flags).
3428+ * If these macros have nonzero value, or overflow-checking compiler intrinsics
3429+ * are not available, good-old heuristics (with some false positives)
3430+ * will be used. */
3431+ # ifndef IV_ADD_SUB_OVERFLOW_IS_EXPENSIVE
3432+ # define IV_ADD_SUB_OVERFLOW_IS_EXPENSIVE 0
3433+ # endif
3434+ # ifndef IV_MUL_OVERFLOW_IS_EXPENSIVE
3435+ /* Strict overflow check for IV multiplication is generally expensive
3436+ * when IV is a multi-word integer.
3437+ * We assume that PTRSIZE matches the platform word size; LONGSIZE might not
3438+ * match for LLP64 platforms such as Win32 x86-64. */
3439+ # define IV_MUL_OVERFLOW_IS_EXPENSIVE (IVSIZE > PTRSIZE)
3440+ # endif
3441+
3442+ # if defined(I_STDCKDINT ) && !IV_ADD_SUB_OVERFLOW_IS_EXPENSIVE
3443+ /* XXX Preparation for upcoming C23, but I_STDCKDINT is not yet tested */
3444+ # define S_iv_add_may_overflow (il , ir , result ) ckd_add(result, il, ir)
3445+ # elif defined(HAS_BUILTIN_ADD_OVERFLOW ) && !IV_ADD_SUB_OVERFLOW_IS_EXPENSIVE
3446+ # define S_iv_add_may_overflow __builtin_add_overflow
3447+ # else
3448+ PERL_STATIC_INLINE bool
3449+ S_iv_add_may_overflow (IV il , IV ir , IV * const result )
3450+ {
3451+ /* topl and topr hold only 2 bits */
3452+ PERL_UINT_FAST8_T const topl = ((UV )il ) >> (UVSIZE * 8 - 2 );
3453+ PERL_UINT_FAST8_T const topr = ((UV )ir ) >> (UVSIZE * 8 - 2 );
3454+
3455+ /* if both are in a range that can't under/overflow, do a simple integer
3456+ * add: if the top of both numbers are 00 or 11, then it's safe */
3457+ if (!( ((topl + 1 ) | (topr + 1 )) & 2 )) {
3458+ * result = il + ir ;
3459+ return false;
3460+ }
3461+ return true; /* addition may overflow */
3462+ }
3463+ # endif
3464+
3465+ /*
3466+ * S_uv_{add,sub,mul}_overflow(a, b, p) are similar, but the results are UV
3467+ * and they should perform strict overflow check (no false positives).
3468+ */
3469+
3470+ # if defined(I_STDCKDINT )
3471+ /* XXX Preparation for upcoming C23, but I_STDCKDINT is not yet tested */
3472+ # define S_uv_add_overflow (auv , buv , result ) ckd_add(result, auv, buv)
3473+ # elif defined(HAS_BUILTIN_ADD_OVERFLOW )
3474+ # define S_uv_add_overflow __builtin_add_overflow
3475+ # else
3476+ PERL_STATIC_INLINE bool
3477+ S_uv_add_overflow (UV auv , UV buv , UV * const result )
3478+ {
3479+ /* (auv + buv) < auv means that the addition wrapped around,
3480+ i.e. overflowed. Note that unsigned integer overflow is well-defined
3481+ in standard C to wrap around, in constrast to signed integer overflow
3482+ whose behaviour is undefined. */
3483+ return (* result = auv + buv ) < auv ;
3484+ }
3485+ # endif
3486+
3487+ # if defined(I_STDCKDINT ) && !IV_ADD_SUB_OVERFLOW_IS_EXPENSIVE
3488+ /* XXX Preparation for upcoming C23, but I_STDCKDINT is not yet tested */
3489+ # define S_iv_sub_may_overflow (il , ir , result ) ckd_sub(result, il, ir)
3490+ # elif defined(HAS_BUILTIN_SUB_OVERFLOW ) && !IV_ADD_SUB_OVERFLOW_IS_EXPENSIVE
3491+ # define S_iv_sub_may_overflow __builtin_sub_overflow
3492+ # else
3493+ PERL_STATIC_INLINE bool
3494+ S_iv_sub_may_overflow (IV il , IV ir , IV * const result )
3495+ {
3496+ PERL_UINT_FAST8_T const topl = ((UV )il ) >> (UVSIZE * 8 - 2 );
3497+ PERL_UINT_FAST8_T const topr = ((UV )ir ) >> (UVSIZE * 8 - 2 );
3498+
3499+ /* if both are in a range that can't under/overflow, do a simple integer
3500+ * subtract: if the top of both numbers are 00 or 11, then it's safe */
3501+ if (!( ((topl + 1 ) | (topr + 1 )) & 2 )) {
3502+ * result = il - ir ;
3503+ return false;
3504+ }
3505+ return true; /* subtraction may overflow */
3506+ }
3507+ # endif
3508+
3509+ # if defined(I_STDCKDINT )
3510+ /* XXX Preparation for upcoming C23, but I_STDCKDINT is not yet tested */
3511+ # define S_uv_sub_overflow (auv , buv , result ) ckd_sub(result, auv, buv)
3512+ # elif defined(HAS_BUILTIN_SUB_OVERFLOW )
3513+ # define S_uv_sub_overflow __builtin_sub_overflow
3514+ # else
3515+ PERL_STATIC_INLINE bool
3516+ S_uv_sub_overflow (UV auv , UV buv , UV * const result )
3517+ {
3518+ return (* result = auv - buv ) > auv ;
3519+ }
3520+ # endif
3521+
3522+ # if defined(I_STDCKDINT ) && !IV_MUL_OVERFLOW_IS_EXPENSIVE
3523+ /* XXX Preparation for upcoming C23, but I_STDCKDINT is not yet tested */
3524+ # define S_iv_mul_may_overflow (il , ir , result ) ckd_mul(result, il, ir)
3525+ # elif defined(HAS_BUILTIN_MUL_OVERFLOW ) && !IV_MUL_OVERFLOW_IS_EXPENSIVE
3526+ # define S_iv_mul_may_overflow __builtin_mul_overflow
3527+ # else
3528+ PERL_STATIC_INLINE bool
3529+ S_iv_mul_may_overflow (IV il , IV ir , IV * const result )
3530+ {
3531+ UV const topl = ((UV )il ) >> (UVSIZE * 4 - 1 );
3532+ UV const topr = ((UV )ir ) >> (UVSIZE * 4 - 1 );
3533+
3534+ /* if both are in a range that can't under/overflow, do a simple integer
3535+ * multiply: if the top halves(*) of both numbers are 00...00 or 11...11,
3536+ * then it's safe.
3537+ * (*) for 32-bits, the "top half" is the top 17 bits,
3538+ * for 64-bits, its 33 bits */
3539+ if (!(
3540+ ((topl + 1 ) | (topr + 1 ))
3541+ & ( (((UV )1 ) << (UVSIZE * 4 + 1 )) - 2 ) /* 11..110 */
3542+ )) {
3543+ * result = il * ir ;
3544+ return false;
3545+ }
3546+ return true; /* multiplication may overflow */
3547+ }
3548+ # endif
3549+
3550+ # if defined(I_STDCKDINT )
3551+ /* XXX Preparation for upcoming C23, but I_STDCKDINT is not yet tested */
3552+ # define S_uv_mul_overflow (auv , buv , result ) ckd_mul(result, auv, buv)
3553+ # elif defined(HAS_BUILTIN_MUL_OVERFLOW )
3554+ # define S_uv_mul_overflow __builtin_mul_overflow
3555+ # else
3556+ PERL_STATIC_INLINE bool
3557+ S_uv_mul_overflow (UV auv , UV buv , UV * const result )
3558+ {
3559+ const UV topmask = (~ (UV )0 ) << (4 * sizeof (UV ));
3560+ const UV botmask = ~topmask ;
3561+
3562+ # if UVSIZE > LONGSIZE && UVSIZE <= 2 * LONGSIZE
3563+ /* If UV is double-word integer, declare these variables as single-word
3564+ integers to help compiler to avoid double-word multiplication. */
3565+ unsigned long alow , ahigh , blow , bhigh ;
3566+ # else
3567+ UV alow , ahigh , blow , bhigh ;
3568+ # endif
3569+
3570+ /* If this does sign extension on unsigned it's time for plan B */
3571+ ahigh = auv >> (4 * sizeof (UV ));
3572+ alow = auv & botmask ;
3573+ bhigh = buv >> (4 * sizeof (UV ));
3574+ blow = buv & botmask ;
3575+
3576+ if (ahigh && bhigh )
3577+ /* eg 32 bit is at least 0x10000 * 0x10000 == 0x100000000
3578+ which is overflow. */
3579+ return true;
3580+
3581+ UV product_middle = 0 ;
3582+ if (ahigh || bhigh ) {
3583+ /* One operand is large, 1 small */
3584+ /* Either ahigh or bhigh is zero here, so the addition below
3585+ can't overflow. */
3586+ product_middle = (UV )ahigh * blow + (UV )alow * bhigh ;
3587+ if (product_middle & topmask )
3588+ return true;
3589+ /* OK, product_middle won't lose bits when we shift it. */
3590+ product_middle <<= 4 * sizeof (UV );
3591+ }
3592+ /* else: eg 32 bit is at most 0xFFFF * 0xFFFF == 0xFFFE0001
3593+ so the unsigned multiply cannot overflow. */
3594+
3595+ /* (UV) cast below is necessary to force the multiplication to produce
3596+ UV result, as alow and blow might be narrower than UV */
3597+ UV product_low = (UV )alow * blow ;
3598+ return S_uv_add_overflow (product_middle , product_low , result );
3599+ }
3600+ # endif
3601+
34163602#endif
34173603
34183604/* ------------------ pp.c, regcomp.c, toke.c, universal.c ------------ */
0 commit comments